ccxt 4.2.77__py2.py3-none-any.whl → 4.4.49__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 +3205 -937
  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 +1525 -573
  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 +223 -97
  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 +639 -323
  126. ccxt/async_support/digifinex.py +465 -233
  127. ccxt/async_support/ellipx.py +1887 -0
  128. ccxt/async_support/exmo.py +317 -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 +433 -178
  133. ccxt/async_support/hollaex.py +207 -83
  134. ccxt/async_support/htx.py +1095 -563
  135. ccxt/async_support/huobijp.py +178 -56
  136. ccxt/async_support/hyperliquid.py +1678 -292
  137. ccxt/async_support/idex.py +219 -95
  138. ccxt/async_support/independentreserve.py +300 -31
  139. ccxt/async_support/indodax.py +226 -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 +198 -107
  145. ccxt/async_support/latoken.py +199 -79
  146. ccxt/async_support/lbank.py +360 -113
  147. ccxt/async_support/luno.py +185 -62
  148. ccxt/async_support/lykke.py +168 -55
  149. ccxt/async_support/mercado.py +101 -29
  150. ccxt/async_support/mexc.py +995 -429
  151. ccxt/async_support/myokx.py +53 -0
  152. ccxt/async_support/ndax.py +234 -82
  153. ccxt/async_support/novadax.py +195 -75
  154. ccxt/async_support/oceanex.py +244 -59
  155. ccxt/async_support/okcoin.py +301 -165
  156. ccxt/async_support/okx.py +1776 -454
  157. ccxt/async_support/onetrading.py +198 -414
  158. ccxt/async_support/oxfun.py +2898 -0
  159. ccxt/async_support/p2b.py +142 -52
  160. ccxt/async_support/paradex.py +2085 -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 +3205 -937
  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 +1525 -573
  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 +223 -97
  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 +639 -323
  234. ccxt/digifinex.py +465 -233
  235. ccxt/ellipx.py +1887 -0
  236. ccxt/exmo.py +317 -128
  237. ccxt/gate.py +1472 -463
  238. ccxt/gemini.py +206 -84
  239. ccxt/hashkey.py +4164 -0
  240. ccxt/hitbtc.py +433 -178
  241. ccxt/hollaex.py +207 -83
  242. ccxt/htx.py +1095 -563
  243. ccxt/huobijp.py +178 -56
  244. ccxt/hyperliquid.py +1677 -292
  245. ccxt/idex.py +219 -95
  246. ccxt/independentreserve.py +299 -31
  247. ccxt/indodax.py +226 -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 +198 -107
  253. ccxt/latoken.py +199 -79
  254. ccxt/lbank.py +360 -113
  255. ccxt/luno.py +185 -62
  256. ccxt/lykke.py +168 -55
  257. ccxt/mercado.py +101 -29
  258. ccxt/mexc.py +994 -429
  259. ccxt/myokx.py +53 -0
  260. ccxt/ndax.py +234 -82
  261. ccxt/novadax.py +195 -75
  262. ccxt/oceanex.py +244 -59
  263. ccxt/okcoin.py +301 -165
  264. ccxt/okx.py +1776 -454
  265. ccxt/onetrading.py +198 -414
  266. ccxt/oxfun.py +2897 -0
  267. ccxt/p2b.py +142 -52
  268. ccxt/paradex.py +2085 -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 +143 -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.49.dist-info/LICENSE.txt +21 -0
  496. ccxt-4.4.49.dist-info/METADATA +646 -0
  497. ccxt-4.4.49.dist-info/RECORD +669 -0
  498. {ccxt-4.2.77.dist-info → ccxt-4.4.49.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.49.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.bitmart 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, TransferEntry
9
+ from ccxt.base.types import Balances, BorrowInterest, Currencies, Currency, DepositAddress, FundingHistory, Int, IsolatedBorrowRate, IsolatedBorrowRates, LedgerEntry, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFeeInterface, Transaction, TransferEntry
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 AccountSuspended
14
15
  from ccxt.base.errors import ArgumentsRequired
@@ -24,7 +25,6 @@ from ccxt.base.errors import RateLimitExceeded
24
25
  from ccxt.base.errors import ExchangeNotAvailable
25
26
  from ccxt.base.errors import OnMaintenance
26
27
  from ccxt.base.errors import InvalidNonce
27
- from ccxt.base.errors import AuthenticationError
28
28
  from ccxt.base.decimal_to_precision import TRUNCATE
29
29
  from ccxt.base.decimal_to_precision import TICK_SIZE
30
30
  from ccxt.base.precise import Precise
@@ -54,11 +54,12 @@ class bitmart(Exchange, ImplicitAPI):
54
54
  'borrowIsolatedMargin': True,
55
55
  'cancelAllOrders': True,
56
56
  'cancelOrder': True,
57
- 'cancelOrders': False,
57
+ 'cancelOrders': True,
58
58
  'createMarketBuyOrderWithCost': True,
59
59
  'createMarketOrderWithCost': False,
60
60
  'createMarketSellOrderWithCost': False,
61
61
  'createOrder': True,
62
+ 'createOrders': True,
62
63
  'createPostOnlyOrder': True,
63
64
  'createStopLimitOrder': False,
64
65
  'createStopMarketOrder': False,
@@ -80,12 +81,13 @@ class bitmart(Exchange, ImplicitAPI):
80
81
  'fetchDeposits': True,
81
82
  'fetchDepositWithdrawFee': True,
82
83
  'fetchDepositWithdrawFees': False,
83
- 'fetchFundingHistory': None,
84
+ 'fetchFundingHistory': True,
84
85
  'fetchFundingRate': True,
85
86
  'fetchFundingRateHistory': False,
86
87
  'fetchFundingRates': False,
87
88
  'fetchIsolatedBorrowRate': True,
88
89
  'fetchIsolatedBorrowRates': True,
90
+ 'fetchLedger': True,
89
91
  'fetchLiquidations': False,
90
92
  'fetchMarginMode': False,
91
93
  'fetchMarkets': True,
@@ -126,9 +128,10 @@ class bitmart(Exchange, ImplicitAPI):
126
128
  },
127
129
  'hostname': 'bitmart.com', # bitmart.info, bitmart.news for Hong Kong users
128
130
  'urls': {
129
- 'logo': 'https://user-images.githubusercontent.com/1294454/129991357-8f47464b-d0f4-41d6-8a82-34122f0d1398.jpg',
131
+ 'logo': 'https://github.com/user-attachments/assets/0623e9c4-f50e-48c9-82bd-65c3908c3a14',
130
132
  'api': {
131
- 'rest': 'https://api-cloud.{hostname}', # bitmart.info for Hong Kong users
133
+ 'spot': 'https://api-cloud.{hostname}',
134
+ 'swap': 'https://api-cloud-v2.{hostname}', # bitmart.info for Hong Kong users
132
135
  },
133
136
  'www': 'https://www.bitmart.com/',
134
137
  'doc': 'https://developer-pro.bitmart.com/',
@@ -171,6 +174,7 @@ class bitmart(Exchange, ImplicitAPI):
171
174
  'contract/public/depth': 5,
172
175
  'contract/public/open-interest': 30,
173
176
  'contract/public/funding-rate': 30,
177
+ 'contract/public/funding-rate-history': 30,
174
178
  'contract/public/kline': 6, # should be 5 but errors
175
179
  'account/v1/currencies': 30,
176
180
  },
@@ -198,7 +202,7 @@ class bitmart(Exchange, ImplicitAPI):
198
202
  'spot/v2/orders': 5,
199
203
  'spot/v1/trades': 5,
200
204
  # newer order endpoint
201
- 'spot/v2/trades': 5,
205
+ 'spot/v2/trades': 4,
202
206
  'spot/v3/orders': 5,
203
207
  'spot/v2/order_detail': 1,
204
208
  # margin
@@ -218,6 +222,10 @@ class bitmart(Exchange, ImplicitAPI):
218
222
  'contract/private/get-open-orders': 1.2,
219
223
  'contract/private/current-plan-order': 1.2,
220
224
  'contract/private/trades': 10,
225
+ 'contract/private/position-risk': 10,
226
+ 'contract/private/affilate/rebate-list': 10,
227
+ 'contract/private/affilate/trade-list': 10,
228
+ 'contract/private/transaction-history': 10,
221
229
  },
222
230
  'post': {
223
231
  # sub-account endpoints
@@ -242,6 +250,9 @@ class bitmart(Exchange, ImplicitAPI):
242
250
  'spot/v4/query/history-orders': 5, # 12 times/2 sec = 6/s => 30/6 = 5
243
251
  'spot/v4/query/trades': 5, # 12 times/2 sec = 6/s => 30/6 = 5
244
252
  'spot/v4/query/order-trades': 5, # 12 times/2 sec = 6/s => 30/6 = 5
253
+ 'spot/v4/cancel_orders': 3,
254
+ 'spot/v4/cancel_all': 90,
255
+ 'spot/v4/batch_orders': 3,
245
256
  # newer endpoint
246
257
  'spot/v3/cancel_order': 1,
247
258
  'spot/v2/batch_orders': 1,
@@ -260,6 +271,10 @@ class bitmart(Exchange, ImplicitAPI):
260
271
  'contract/private/submit-plan-order': 2.5,
261
272
  'contract/private/cancel-plan-order': 1.5,
262
273
  'contract/private/submit-leverage': 2.5,
274
+ 'contract/private/submit-tp-sl-order': 2.5,
275
+ 'contract/private/modify-plan-order': 2.5,
276
+ 'contract/private/modify-preset-plan-order': 2.5,
277
+ 'contract/private/modify-tp-sl-order': 2.5,
263
278
  },
264
279
  },
265
280
  },
@@ -509,8 +524,8 @@ class bitmart(Exchange, ImplicitAPI):
509
524
  '40045': InvalidOrder, # 400, The order open type is invalid
510
525
  '40046': PermissionDenied, # 403, The account is not opened futures
511
526
  '40047': PermissionDenied, # 403, Services is not available in you countries and areas
512
- '40048': BadRequest, # 403, ClientOrderId only allows a combination of numbers and letters
513
- '40049': BadRequest, # 403, The maximum length of clientOrderId cannot exceed 32
527
+ '40048': InvalidOrder, # 403, ClientOrderId only allows a combination of numbers and letters
528
+ '40049': InvalidOrder, # 403, The maximum length of clientOrderId cannot exceed 32
514
529
  '40050': InvalidOrder, # 403, Client OrderId duplicated with existing orders
515
530
  },
516
531
  'broad': {},
@@ -530,6 +545,8 @@ class bitmart(Exchange, ImplicitAPI):
530
545
  'defaultNetworks': {
531
546
  'USDT': 'ERC20',
532
547
  },
548
+ 'timeDifference': 0, # the difference between system clock and exchange clock
549
+ 'adjustForTimeDifference': False, # controls the adjustment logic upon instantiation
533
550
  'networks': {
534
551
  'ERC20': 'ERC20',
535
552
  'SOL': 'SOL',
@@ -692,6 +709,148 @@ class bitmart(Exchange, ImplicitAPI):
692
709
  'createMarketBuyOrderRequiresPrice': True,
693
710
  'brokerId': 'CCXTxBitmart000',
694
711
  },
712
+ 'features': {
713
+ 'default': {
714
+ 'sandbox': False,
715
+ 'createOrder': {
716
+ 'marginMode': True,
717
+ 'triggerPrice': False,
718
+ 'triggerPriceType': None,
719
+ 'triggerDirection': False,
720
+ 'stopLossPrice': False,
721
+ 'takeProfitPrice': False,
722
+ 'attachedStopLossTakeProfit': None,
723
+ 'timeInForce': {
724
+ 'IOC': True,
725
+ 'FOK': False,
726
+ 'PO': True,
727
+ 'GTD': False,
728
+ },
729
+ 'hedged': False,
730
+ 'trailing': False,
731
+ 'marketBuyRequiresPrice': False, # todo: https://developer-pro.bitmart.com/en/spot/#new-order-v2-signed
732
+ 'marketBuyByCost': True,
733
+ 'leverage': True, # todo: implement
734
+ 'selfTradePrevention': False,
735
+ 'iceberg': False,
736
+ },
737
+ 'createOrders': {
738
+ 'max': 10,
739
+ },
740
+ 'fetchMyTrades': {
741
+ 'marginMode': True,
742
+ 'limit': 200,
743
+ 'daysBack': None,
744
+ 'untilDays': 99999,
745
+ },
746
+ 'fetchOrder': {
747
+ 'marginMode': False,
748
+ 'trigger': False,
749
+ 'trailing': False,
750
+ },
751
+ 'fetchOpenOrders': {
752
+ 'marginMode': True,
753
+ 'limit': 200,
754
+ 'trigger': False,
755
+ 'trailing': False,
756
+ },
757
+ 'fetchOrders': None,
758
+ 'fetchClosedOrders': {
759
+ 'marginMode': True,
760
+ 'limit': 200,
761
+ 'daysBack': None,
762
+ 'daysBackCanceled': None,
763
+ 'untilDays': None,
764
+ 'trigger': False,
765
+ 'trailing': False,
766
+ },
767
+ 'fetchOHLCV': {
768
+ 'limit': 1000, # variable timespans for recent endpoint, 200 for historical
769
+ },
770
+ },
771
+ 'forDerivatives': {
772
+ 'extends': 'default',
773
+ 'createOrder': {
774
+ 'marginMode': True,
775
+ 'triggerPrice': True,
776
+ 'triggerPriceType': {
777
+ 'last': True,
778
+ 'mark': True,
779
+ 'index': False,
780
+ },
781
+ 'triggerDirection': True, # todo: implementation broken
782
+ 'stopLossPrice': True,
783
+ 'takeProfitPrice': True,
784
+ 'attachedStopLossTakeProfit': {
785
+ 'triggerPriceType': {
786
+ 'last': True,
787
+ 'mark': True,
788
+ 'index': False,
789
+ },
790
+ 'price': False,
791
+ },
792
+ 'timeInForce': {
793
+ 'IOC': True,
794
+ 'FOK': True,
795
+ 'PO': True,
796
+ 'GTD': False,
797
+ },
798
+ 'hedged': False,
799
+ 'trailing': True,
800
+ 'marketBuyRequiresPrice': True,
801
+ 'marketBuyByCost': True,
802
+ # exchange-supported features
803
+ # 'selfTradePrevention': True,
804
+ # 'twap': False,
805
+ # 'iceberg': False,
806
+ # 'oco': False,
807
+ },
808
+ 'fetchMyTrades': {
809
+ 'marginMode': True,
810
+ 'limit': None,
811
+ 'daysBack': None,
812
+ 'untilDays': 99999,
813
+ },
814
+ 'fetchOrder': {
815
+ 'marginMode': False,
816
+ 'trigger': False,
817
+ 'trailing': True,
818
+ },
819
+ 'fetchOpenOrders': {
820
+ 'marginMode': False,
821
+ 'limit': 100,
822
+ 'trigger': True,
823
+ 'trailing': False,
824
+ },
825
+ 'fetchClosedOrders': {
826
+ 'marginMode': True,
827
+ 'limit': 200,
828
+ 'daysBack': None,
829
+ 'daysBackCanceled': None,
830
+ 'untilDays': None,
831
+ 'trigger': False,
832
+ 'trailing': False,
833
+ },
834
+ 'fetchOHLCV': {
835
+ 'limit': 500,
836
+ },
837
+ },
838
+ 'spot': {
839
+ 'extends': 'default',
840
+ },
841
+ 'swap': {
842
+ 'linear': {
843
+ 'extends': 'forDerivatives',
844
+ },
845
+ 'inverse': {
846
+ 'extends': 'forDerivatives',
847
+ },
848
+ },
849
+ 'future': {
850
+ 'linear': None,
851
+ 'inverse': None,
852
+ },
853
+ },
695
854
  })
696
855
 
697
856
  async def fetch_time(self, params={}):
@@ -711,7 +870,7 @@ class bitmart(Exchange, ImplicitAPI):
711
870
  # }
712
871
  # }
713
872
  #
714
- data = self.safe_value(response, 'data', {})
873
+ data = self.safe_dict(response, 'data', {})
715
874
  return self.safe_integer(data, 'server_time')
716
875
 
717
876
  async def fetch_status(self, params={}):
@@ -720,7 +879,7 @@ class bitmart(Exchange, ImplicitAPI):
720
879
  :param dict [params]: extra parameters specific to the exchange API endpoint
721
880
  :returns dict: a `status structure <https://docs.ccxt.com/#/?id=exchange-status-structure>`
722
881
  """
723
- options = self.safe_value(self.options, 'fetchStatus', {})
882
+ options = self.safe_dict(self.options, 'fetchStatus', {})
724
883
  defaultType = self.safe_string(self.options, 'defaultType')
725
884
  type = self.safe_string(options, 'type', defaultType)
726
885
  type = self.safe_string(params, 'type', type)
@@ -751,12 +910,12 @@ class bitmart(Exchange, ImplicitAPI):
751
910
  # }
752
911
  # }
753
912
  #
754
- data = self.safe_value(response, 'data', {})
755
- services = self.safe_value(data, 'service', [])
913
+ data = self.safe_dict(response, 'data', {})
914
+ services = self.safe_list(data, 'service', [])
756
915
  servicesByType = self.index_by(services, 'service_type')
757
916
  if type == 'swap':
758
917
  type = 'contract'
759
- service = self.safe_value(servicesByType, type)
918
+ service = self.safe_string(servicesByType, type)
760
919
  status = None
761
920
  eta = None
762
921
  if service is not None:
@@ -802,8 +961,8 @@ class bitmart(Exchange, ImplicitAPI):
802
961
  # }
803
962
  # }
804
963
  #
805
- data = self.safe_value(response, 'data', {})
806
- symbols = self.safe_value(data, 'symbols', [])
964
+ data = self.safe_dict(response, 'data', {})
965
+ symbols = self.safe_list(data, 'symbols', [])
807
966
  result = []
808
967
  for i in range(0, len(symbols)):
809
968
  market = symbols[i]
@@ -874,38 +1033,45 @@ class bitmart(Exchange, ImplicitAPI):
874
1033
  response = await self.publicGetContractPublicDetails(params)
875
1034
  #
876
1035
  # {
877
- # "code": 1000,
878
- # "message": "Ok",
879
- # "trace": "9b92a999-9463-4c96-91a4-93ad1cad0d72",
880
- # "data": {
881
- # "symbols": [{
882
- # "symbol": "BTCUSDT",
883
- # "product_type": 1,
884
- # "open_timestamp": 1594080000,
885
- # "expire_timestamp": 0,
886
- # "settle_timestamp": 0,
887
- # "base_currency": "BTC",
888
- # "quote_currency": "USDT",
889
- # "last_price": "23920",
890
- # "volume_24h": "18969368",
891
- # "turnover_24h": "458933659.7858",
892
- # "index_price": "23945.25191635",
893
- # "index_name": "BTCUSDT",
894
- # "contract_size": "0.001",
895
- # "min_leverage": "1",
896
- # "max_leverage": "100",
897
- # "price_precision": "0.1",
898
- # "vol_precision": "1",
899
- # "max_volume": "500000",
900
- # "min_volume": "1"
901
- # },
902
- # ...
903
- # ]
904
- # }
1036
+ # "code": 1000,
1037
+ # "message": "Ok",
1038
+ # "data": {
1039
+ # "symbols": [
1040
+ # {
1041
+ # "symbol": "BTCUSDT",
1042
+ # "product_type": 1,
1043
+ # "open_timestamp": 1645977600000,
1044
+ # "expire_timestamp": 0,
1045
+ # "settle_timestamp": 0,
1046
+ # "base_currency": "BTC",
1047
+ # "quote_currency": "USDT",
1048
+ # "last_price": "63547.4",
1049
+ # "volume_24h": "110938430",
1050
+ # "turnover_24h": "7004836342.6944",
1051
+ # "index_price": "63587.85404255",
1052
+ # "index_name": "BTCUSDT",
1053
+ # "contract_size": "0.001",
1054
+ # "min_leverage": "1",
1055
+ # "max_leverage": "100",
1056
+ # "price_precision": "0.1",
1057
+ # "vol_precision": "1",
1058
+ # "max_volume": "1000000",
1059
+ # "min_volume": "1",
1060
+ # "funding_rate": "0.0000801",
1061
+ # "expected_funding_rate": "-0.0000035",
1062
+ # "open_interest": "278214",
1063
+ # "open_interest_value": "17555316.9355496",
1064
+ # "high_24h": "64109.4",
1065
+ # "low_24h": "61857.6",
1066
+ # "change_24h": "0.0239264900886327",
1067
+ # "funding_time": 1726819200000
1068
+ # },
1069
+ # ]
1070
+ # }
905
1071
  # }
906
1072
  #
907
- data = self.safe_value(response, 'data', {})
908
- symbols = self.safe_value(data, 'symbols', [])
1073
+ data = self.safe_dict(response, 'data', {})
1074
+ symbols = self.safe_list(data, 'symbols', [])
909
1075
  result = []
910
1076
  for i in range(0, len(symbols)):
911
1077
  market = symbols[i]
@@ -975,17 +1141,22 @@ class bitmart(Exchange, ImplicitAPI):
975
1141
  })
976
1142
  return result
977
1143
 
978
- async def fetch_markets(self, params={}):
1144
+ async def fetch_markets(self, params={}) -> List[Market]:
979
1145
  """
1146
+
1147
+ https://developer-pro.bitmart.com/en/futuresv2/#get-contract-details
1148
+
980
1149
  retrieves data on all markets for bitmart
981
1150
  :param dict [params]: extra parameters specific to the exchange API endpoint
982
1151
  :returns dict[]: an array of objects representing market data
983
1152
  """
1153
+ if self.options['adjustForTimeDifference']:
1154
+ await self.load_time_difference()
984
1155
  spot = await self.fetch_spot_markets(params)
985
1156
  contract = await self.fetch_contract_markets(params)
986
1157
  return self.array_concat(spot, contract)
987
1158
 
988
- async def fetch_currencies(self, params={}):
1159
+ async def fetch_currencies(self, params={}) -> Currencies:
989
1160
  """
990
1161
  fetches all available currencies on an exchange
991
1162
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1006,16 +1177,16 @@ class bitmart(Exchange, ImplicitAPI):
1006
1177
  # }
1007
1178
  # }
1008
1179
  #
1009
- data = self.safe_value(response, 'data', {})
1010
- currencies = self.safe_value(data, 'currencies', [])
1011
- result = {}
1180
+ data = self.safe_dict(response, 'data', {})
1181
+ currencies = self.safe_list(data, 'currencies', [])
1182
+ result: dict = {}
1012
1183
  for i in range(0, len(currencies)):
1013
1184
  currency = currencies[i]
1014
1185
  id = self.safe_string(currency, 'id')
1015
1186
  code = self.safe_currency_code(id)
1016
1187
  name = self.safe_string(currency, 'name')
1017
- withdrawEnabled = self.safe_value(currency, 'withdraw_enabled')
1018
- depositEnabled = self.safe_value(currency, 'deposit_enabled')
1188
+ withdrawEnabled = self.safe_bool(currency, 'withdraw_enabled')
1189
+ depositEnabled = self.safe_bool(currency, 'deposit_enabled')
1019
1190
  active = withdrawEnabled and depositEnabled
1020
1191
  result[code] = {
1021
1192
  'id': id,
@@ -1036,7 +1207,7 @@ class bitmart(Exchange, ImplicitAPI):
1036
1207
 
1037
1208
  async def fetch_transaction_fee(self, code: str, params={}):
1038
1209
  """
1039
- * @deprecated
1210
+ @deprecated
1040
1211
  please use fetchDepositWithdrawFee instead
1041
1212
  :param str code: unified currency code
1042
1213
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1044,7 +1215,7 @@ class bitmart(Exchange, ImplicitAPI):
1044
1215
  """
1045
1216
  await self.load_markets()
1046
1217
  currency = self.currency(code)
1047
- request = {
1218
+ request: dict = {
1048
1219
  'currency': currency['id'],
1049
1220
  }
1050
1221
  response = await self.privateGetAccountV1WithdrawCharge(self.extend(request, params))
@@ -1062,7 +1233,7 @@ class bitmart(Exchange, ImplicitAPI):
1062
1233
  # }
1063
1234
  #
1064
1235
  data = response['data']
1065
- withdrawFees = {}
1236
+ withdrawFees: dict = {}
1066
1237
  withdrawFees[code] = self.safe_number(data, 'withdraw_fee')
1067
1238
  return {
1068
1239
  'info': response,
@@ -1101,7 +1272,7 @@ class bitmart(Exchange, ImplicitAPI):
1101
1272
  """
1102
1273
  await self.load_markets()
1103
1274
  currency = self.currency(code)
1104
- request = {
1275
+ request: dict = {
1105
1276
  'currency': currency['id'],
1106
1277
  }
1107
1278
  response = await self.privateGetAccountV1WithdrawCharge(self.extend(request, params))
@@ -1121,29 +1292,48 @@ class bitmart(Exchange, ImplicitAPI):
1121
1292
  data = response['data']
1122
1293
  return self.parse_deposit_withdraw_fee(data)
1123
1294
 
1124
- def parse_ticker(self, ticker, market: Market = None) -> Ticker:
1295
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
1125
1296
  #
1126
- # spot(REST)
1297
+ # spot(REST) fetchTickers
1127
1298
  #
1128
- # {
1129
- # "symbol": "SOLAR_USDT",
1130
- # "last_price": "0.020342",
1131
- # "quote_volume_24h": "56817.811802",
1132
- # "base_volume_24h": "2172060",
1133
- # "high_24h": "0.256000",
1134
- # "low_24h": "0.016980",
1135
- # "open_24h": "0.022309",
1136
- # "close_24h": "0.020342",
1137
- # "best_ask": "0.020389",
1138
- # "best_ask_size": "339.000000000000000000000000000000",
1139
- # "best_bid": "0.020342",
1140
- # "best_bid_size": "3369.000000000000000000000000000000",
1141
- # "fluctuation": "-0.0882",
1142
- # "url": "https://www.bitmart.com/trade?symbol=SOLAR_USDT",
1143
- # "timestamp": 1667403439367
1144
- # }
1299
+ # {
1300
+ # 'result': [
1301
+ # "AFIN_USDT", # symbol
1302
+ # "0.001047", # last
1303
+ # "11110", # v_24h
1304
+ # "11.632170", # qv_24h
1305
+ # "0.001048", # open_24h
1306
+ # "0.001048", # high_24h
1307
+ # "0.001047", # low_24h
1308
+ # "-0.00095", # price_change_24h
1309
+ # "0.001029", # bid_px
1310
+ # "5555", # bid_sz
1311
+ # "0.001041", # ask_px
1312
+ # "5297", # ask_sz
1313
+ # "1717122550482" # timestamp
1314
+ # ]
1315
+ # }
1316
+ #
1317
+ # spot(REST) fetchTicker
1318
+ #
1319
+ # {
1320
+ # "symbol": "BTC_USDT",
1321
+ # "last": "68500.00",
1322
+ # "v_24h": "10491.65490",
1323
+ # "qv_24h": "717178990.42",
1324
+ # "open_24h": "68149.75",
1325
+ # "high_24h": "69499.99",
1326
+ # "low_24h": "67132.40",
1327
+ # "fluctuation": "0.00514",
1328
+ # "bid_px": "68500",
1329
+ # "bid_sz": "0.00162",
1330
+ # "ask_px": "68500.01",
1331
+ # "ask_sz": "0.01722",
1332
+ # "ts": "1717131391671"
1333
+ # }
1145
1334
  #
1146
1335
  # spot(WS)
1336
+ #
1147
1337
  # {
1148
1338
  # "symbol":"BTC_USDT",
1149
1339
  # "last_price":"146.24",
@@ -1156,37 +1346,74 @@ class bitmart(Exchange, ImplicitAPI):
1156
1346
  #
1157
1347
  # swap
1158
1348
  #
1159
- # {
1160
- # "contract_symbol":"DOGEUSDT",
1161
- # "last_price":"0.130340",
1162
- # "index_price":"0.13048245",
1163
- # "last_funding_rate":"0.00002287",
1164
- # "price_change_percent_24h":"-2.074",
1165
- # "volume_24h":"113705028.59482228",
1166
- # "url":"https://futures.bitmart.com/en?symbol=DOGEUSDT",
1167
- # "high_price":"0.134520",
1168
- # "low_price":"0.128570",
1169
- # "legal_coin_price":"0.1302699"
1170
- # }
1349
+ # {
1350
+ # "symbol": "BTCUSDT",
1351
+ # "product_type": 1,
1352
+ # "open_timestamp": 1645977600000,
1353
+ # "expire_timestamp": 0,
1354
+ # "settle_timestamp": 0,
1355
+ # "base_currency": "BTC",
1356
+ # "quote_currency": "USDT",
1357
+ # "last_price": "63547.4",
1358
+ # "volume_24h": "110938430",
1359
+ # "turnover_24h": "7004836342.6944",
1360
+ # "index_price": "63587.85404255",
1361
+ # "index_name": "BTCUSDT",
1362
+ # "contract_size": "0.001",
1363
+ # "min_leverage": "1",
1364
+ # "max_leverage": "100",
1365
+ # "price_precision": "0.1",
1366
+ # "vol_precision": "1",
1367
+ # "max_volume": "1000000",
1368
+ # "min_volume": "1",
1369
+ # "funding_rate": "0.0000801",
1370
+ # "expected_funding_rate": "-0.0000035",
1371
+ # "open_interest": "278214",
1372
+ # "open_interest_value": "17555316.9355496",
1373
+ # "high_24h": "64109.4",
1374
+ # "low_24h": "61857.6",
1375
+ # "change_24h": "0.0239264900886327",
1376
+ # "funding_time": 1726819200000
1377
+ # }
1171
1378
  #
1172
- timestamp = self.safe_integer(ticker, 'timestamp')
1173
- if timestamp is None:
1174
- # ticker from WS has a different field(in seconds)
1175
- timestamp = self.safe_integer_product(ticker, 's_t', 1000)
1379
+ result = self.safe_list(ticker, 'result', [])
1380
+ average = self.safe_string_2(ticker, 'avg_price', 'index_price')
1176
1381
  marketId = self.safe_string_2(ticker, 'symbol', 'contract_symbol')
1382
+ timestamp = self.safe_integer_2(ticker, 'timestamp', 'ts')
1383
+ last = self.safe_string_2(ticker, 'last_price', 'last')
1384
+ percentage = self.safe_string_2(ticker, 'price_change_percent_24h', 'change_24h')
1385
+ change = self.safe_string(ticker, 'fluctuation')
1386
+ high = self.safe_string_2(ticker, 'high_24h', 'high_price')
1387
+ low = self.safe_string_2(ticker, 'low_24h', 'low_price')
1388
+ bid = self.safe_string_2(ticker, 'best_bid', 'bid_px')
1389
+ bidVolume = self.safe_string_2(ticker, 'best_bid_size', 'bid_sz')
1390
+ ask = self.safe_string_2(ticker, 'best_ask', 'ask_px')
1391
+ askVolume = self.safe_string_2(ticker, 'best_ask_size', 'ask_sz')
1392
+ open = self.safe_string(ticker, 'open_24h')
1393
+ baseVolume = self.safe_string_n(ticker, ['base_volume_24h', 'v_24h', 'volume_24h'])
1394
+ quoteVolume = self.safe_string_lower_n(ticker, ['quote_volume_24h', 'qv_24h', 'turnover_24h'])
1395
+ listMarketId = self.safe_string(result, 0)
1396
+ if listMarketId is not None:
1397
+ marketId = listMarketId
1398
+ timestamp = self.safe_integer(result, 12)
1399
+ high = self.safe_string(result, 5)
1400
+ low = self.safe_string(result, 6)
1401
+ bid = self.safe_string(result, 8)
1402
+ bidVolume = self.safe_string(result, 9)
1403
+ ask = self.safe_string(result, 10)
1404
+ askVolume = self.safe_string(result, 11)
1405
+ open = self.safe_string(result, 4)
1406
+ last = self.safe_string(result, 1)
1407
+ change = self.safe_string(result, 7)
1408
+ baseVolume = self.safe_string(result, 2)
1409
+ quoteVolume = self.safe_string_lower(result, 3)
1177
1410
  market = self.safe_market(marketId, market)
1178
1411
  symbol = market['symbol']
1179
- last = self.safe_string_2(ticker, 'close_24h', 'last_price')
1180
- percentage = self.safe_string(ticker, 'price_change_percent_24h')
1412
+ if timestamp is None:
1413
+ # ticker from WS has a different field(in seconds)
1414
+ timestamp = self.safe_integer_product(ticker, 's_t', 1000)
1181
1415
  if percentage is None:
1182
- percentageRaw = self.safe_string(ticker, 'fluctuation')
1183
- if (percentageRaw is not None) and (percentageRaw != '0'): # a few tickers show strictly '0' in fluctuation field
1184
- direction = percentageRaw[0]
1185
- percentage = direction + Precise.string_mul(percentageRaw.replace(direction, ''), '100')
1186
- elif percentageRaw == '0':
1187
- percentage = '0'
1188
- baseVolume = self.safe_string(ticker, 'base_volume_24h')
1189
- quoteVolume = self.safe_string(ticker, 'quote_volume_24h')
1416
+ percentage = Precise.string_mul(change, '100')
1190
1417
  if quoteVolume is None:
1191
1418
  if baseVolume is None:
1192
1419
  # self is swap
@@ -1196,21 +1423,18 @@ class bitmart(Exchange, ImplicitAPI):
1196
1423
  # contrary to name and documentation, base_volume_24h is actually the quote volume
1197
1424
  quoteVolume = baseVolume
1198
1425
  baseVolume = None
1199
- average = self.safe_string_2(ticker, 'avg_price', 'index_price')
1200
- high = self.safe_string_2(ticker, 'high_24h', 'high_price')
1201
- low = self.safe_string_2(ticker, 'low_24h', 'low_price')
1202
1426
  return self.safe_ticker({
1203
1427
  'symbol': symbol,
1204
1428
  'timestamp': timestamp,
1205
1429
  'datetime': self.iso8601(timestamp),
1206
1430
  'high': high,
1207
1431
  'low': low,
1208
- 'bid': self.safe_string(ticker, 'best_bid'),
1209
- 'bidVolume': self.safe_string(ticker, 'best_bid_size'),
1210
- 'ask': self.safe_string(ticker, 'best_ask'),
1211
- 'askVolume': self.safe_string(ticker, 'best_ask_size'),
1432
+ 'bid': bid,
1433
+ 'bidVolume': bidVolume,
1434
+ 'ask': ask,
1435
+ 'askVolume': askVolume,
1212
1436
  'vwap': None,
1213
- 'open': self.safe_string(ticker, 'open_24h'),
1437
+ 'open': open,
1214
1438
  'close': last,
1215
1439
  'last': last,
1216
1440
  'previousClose': None,
@@ -1219,96 +1443,112 @@ class bitmart(Exchange, ImplicitAPI):
1219
1443
  'average': average,
1220
1444
  'baseVolume': baseVolume,
1221
1445
  'quoteVolume': quoteVolume,
1446
+ 'indexPrice': self.safe_string(ticker, 'index_price'),
1222
1447
  'info': ticker,
1223
1448
  }, market)
1224
1449
 
1225
1450
  async def fetch_ticker(self, symbol: str, params={}) -> Ticker:
1226
1451
  """
1227
1452
  fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1453
+
1454
+ https://developer-pro.bitmart.com/en/spot/#get-ticker-of-a-trading-pair-v3
1455
+ https://developer-pro.bitmart.com/en/futuresv2/#get-contract-details
1456
+
1228
1457
  :param str symbol: unified symbol of the market to fetch the ticker for
1229
1458
  :param dict [params]: extra parameters specific to the exchange API endpoint
1230
1459
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1231
1460
  """
1232
1461
  await self.load_markets()
1233
1462
  market = self.market(symbol)
1234
- request = {}
1463
+ request: dict = {}
1235
1464
  response = None
1236
1465
  if market['swap']:
1237
- request['contract_symbol'] = market['id']
1238
- response = await self.publicGetContractV1Tickers(self.extend(request, params))
1466
+ request['symbol'] = market['id']
1467
+ response = await self.publicGetContractPublicDetails(self.extend(request, params))
1468
+ #
1469
+ # {
1470
+ # "code": 1000,
1471
+ # "message": "Ok",
1472
+ # "data": {
1473
+ # "symbols": [
1474
+ # {
1475
+ # "symbol": "BTCUSDT",
1476
+ # "product_type": 1,
1477
+ # "open_timestamp": 1645977600000,
1478
+ # "expire_timestamp": 0,
1479
+ # "settle_timestamp": 0,
1480
+ # "base_currency": "BTC",
1481
+ # "quote_currency": "USDT",
1482
+ # "last_price": "63547.4",
1483
+ # "volume_24h": "110938430",
1484
+ # "turnover_24h": "7004836342.6944",
1485
+ # "index_price": "63587.85404255",
1486
+ # "index_name": "BTCUSDT",
1487
+ # "contract_size": "0.001",
1488
+ # "min_leverage": "1",
1489
+ # "max_leverage": "100",
1490
+ # "price_precision": "0.1",
1491
+ # "vol_precision": "1",
1492
+ # "max_volume": "1000000",
1493
+ # "min_volume": "1",
1494
+ # "funding_rate": "0.0000801",
1495
+ # "expected_funding_rate": "-0.0000035",
1496
+ # "open_interest": "278214",
1497
+ # "open_interest_value": "17555316.9355496",
1498
+ # "high_24h": "64109.4",
1499
+ # "low_24h": "61857.6",
1500
+ # "change_24h": "0.0239264900886327",
1501
+ # "funding_time": 1726819200000
1502
+ # },
1503
+ # ]
1504
+ # }
1505
+ # }
1506
+ #
1239
1507
  elif market['spot']:
1240
1508
  request['symbol'] = market['id']
1241
- response = await self.publicGetSpotV1Ticker(self.extend(request, params))
1509
+ response = await self.publicGetSpotQuotationV3Ticker(self.extend(request, params))
1510
+ #
1511
+ # {
1512
+ # "code": 1000,
1513
+ # "trace": "f2194c2c202d2.99.1717535",
1514
+ # "message": "success",
1515
+ # "data": {
1516
+ # "symbol": "BTC_USDT",
1517
+ # "last": "68500.00",
1518
+ # "v_24h": "10491.65490",
1519
+ # "qv_24h": "717178990.42",
1520
+ # "open_24h": "68149.75",
1521
+ # "high_24h": "69499.99",
1522
+ # "low_24h": "67132.40",
1523
+ # "fluctuation": "0.00514",
1524
+ # "bid_px": "68500",
1525
+ # "bid_sz": "0.00162",
1526
+ # "ask_px": "68500.01",
1527
+ # "ask_sz": "0.01722",
1528
+ # "ts": "1717131391671"
1529
+ # }
1530
+ # }
1531
+ #
1242
1532
  else:
1243
1533
  raise NotSupported(self.id + ' fetchTicker() does not support ' + market['type'] + ' markets, only spot and swap markets are accepted')
1244
- #
1245
- # spot
1246
- #
1247
- # {
1248
- # "message":"OK",
1249
- # "code":1000,
1250
- # "trace":"6aa5b923-2f57-46e3-876d-feca190e0b82",
1251
- # "data":{
1252
- # "tickers":[
1253
- # {
1254
- # "symbol":"ETH_BTC",
1255
- # "last_price":"0.036037",
1256
- # "quote_volume_24h":"4380.6660000000",
1257
- # "base_volume_24h":"159.3582006712",
1258
- # "high_24h":"0.036972",
1259
- # "low_24h":"0.035524",
1260
- # "open_24h":"0.036561",
1261
- # "close_24h":"0.036037",
1262
- # "best_ask":"0.036077",
1263
- # "best_ask_size":"9.9500",
1264
- # "best_bid":"0.035983",
1265
- # "best_bid_size":"4.2792",
1266
- # "fluctuation":"-0.0143",
1267
- # "url":"https://www.bitmart.com/trade?symbol=ETH_BTC"
1268
- # }
1269
- # ]
1270
- # }
1271
- # }
1272
- #
1273
- # swap
1274
- #
1275
- # {
1276
- # "message":"OK",
1277
- # "code":1000,
1278
- # "trace":"4a0ebceb-d3f7-45a3-8feb-f61e230e24cd",
1279
- # "data":{
1280
- # "tickers":[
1281
- # {
1282
- # "contract_symbol":"DOGEUSDT",
1283
- # "last_price":"0.130180",
1284
- # "index_price":"0.13028635",
1285
- # "last_funding_rate":"0.00002025",
1286
- # "price_change_percent_24h":"-2.326",
1287
- # "volume_24h":"116789313.01797258",
1288
- # "url":"https://futures.bitmart.com/en?symbol=DOGEUSDT",
1289
- # "high_price":"0.134520",
1290
- # "low_price":"0.128570",
1291
- # "legal_coin_price":"0.13017401"
1292
- # }
1293
- # ]
1294
- # }
1295
- # }
1296
- #
1297
- data = self.safe_value(response, 'data', {})
1298
- tickers = self.safe_value(data, 'tickers', [])
1299
1534
  # fails in naming for contract tickers 'contract_symbol'
1300
- tickersById = None
1535
+ tickers = []
1536
+ ticker: dict = {}
1301
1537
  if market['spot']:
1302
- tickersById = self.index_by(tickers, 'symbol')
1303
- elif market['swap']:
1304
- tickersById = self.index_by(tickers, 'contract_symbol')
1305
- ticker = self.safe_value(tickersById, market['id'])
1538
+ ticker = self.safe_dict(response, 'data', {})
1539
+ else:
1540
+ data = self.safe_dict(response, 'data', {})
1541
+ tickers = self.safe_list(data, 'symbols', [])
1542
+ ticker = self.safe_dict(tickers, 0, {})
1306
1543
  return self.parse_ticker(ticker, market)
1307
1544
 
1308
1545
  async def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
1309
1546
  """
1310
1547
  fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1311
- :see: https://developer-pro.bitmart.com/en/spot/#get-ticker-of-all-pairs-v2
1548
+
1549
+ https://developer-pro.bitmart.com/en/spot/#get-ticker-of-all-pairs-v3
1550
+ https://developer-pro.bitmart.com/en/futuresv2/#get-contract-details
1551
+
1312
1552
  :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1313
1553
  :param dict [params]: extra parameters specific to the exchange API endpoint
1314
1554
  :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -1318,21 +1558,92 @@ class bitmart(Exchange, ImplicitAPI):
1318
1558
  type = None
1319
1559
  market = None
1320
1560
  if symbols is not None:
1321
- symbol = self.safe_value(symbols, 0)
1561
+ symbol = self.safe_string(symbols, 0)
1322
1562
  market = self.market(symbol)
1323
1563
  type, params = self.handle_market_type_and_params('fetchTickers', market, params)
1324
1564
  response = None
1325
1565
  if type == 'spot':
1326
- response = await self.publicGetSpotV2Ticker(params)
1566
+ response = await self.publicGetSpotQuotationV3Tickers(params)
1567
+ #
1568
+ # {
1569
+ # "code": 1000,
1570
+ # "trace": "17c5e5d9ac49f9b71efca2bed55f1a.105.171225637482393",
1571
+ # "message": "success",
1572
+ # "data": [
1573
+ # [
1574
+ # "AFIN_USDT",
1575
+ # "0.001047",
1576
+ # "11110",
1577
+ # "11.632170",
1578
+ # "0.001048",
1579
+ # "0.001048",
1580
+ # "0.001047",
1581
+ # "-0.00095",
1582
+ # "0.001029",
1583
+ # "5555",
1584
+ # "0.001041",
1585
+ # "5297",
1586
+ # "1717122550482"
1587
+ # ],
1588
+ # ]
1589
+ # }
1590
+ #
1327
1591
  elif type == 'swap':
1328
- response = await self.publicGetContractV1Tickers(params)
1592
+ response = await self.publicGetContractPublicDetails(params)
1593
+ #
1594
+ # {
1595
+ # "code": 1000,
1596
+ # "message": "Ok",
1597
+ # "data": {
1598
+ # "symbols": [
1599
+ # {
1600
+ # "symbol": "BTCUSDT",
1601
+ # "product_type": 1,
1602
+ # "open_timestamp": 1645977600000,
1603
+ # "expire_timestamp": 0,
1604
+ # "settle_timestamp": 0,
1605
+ # "base_currency": "BTC",
1606
+ # "quote_currency": "USDT",
1607
+ # "last_price": "63547.4",
1608
+ # "volume_24h": "110938430",
1609
+ # "turnover_24h": "7004836342.6944",
1610
+ # "index_price": "63587.85404255",
1611
+ # "index_name": "BTCUSDT",
1612
+ # "contract_size": "0.001",
1613
+ # "min_leverage": "1",
1614
+ # "max_leverage": "100",
1615
+ # "price_precision": "0.1",
1616
+ # "vol_precision": "1",
1617
+ # "max_volume": "1000000",
1618
+ # "min_volume": "1",
1619
+ # "funding_rate": "0.0000801",
1620
+ # "expected_funding_rate": "-0.0000035",
1621
+ # "open_interest": "278214",
1622
+ # "open_interest_value": "17555316.9355496",
1623
+ # "high_24h": "64109.4",
1624
+ # "low_24h": "61857.6",
1625
+ # "change_24h": "0.0239264900886327",
1626
+ # "funding_time": 1726819200000
1627
+ # },
1628
+ # ]
1629
+ # }
1630
+ # }
1631
+ #
1329
1632
  else:
1330
1633
  raise NotSupported(self.id + ' fetchTickers() does not support ' + type + ' markets, only spot and swap markets are accepted')
1331
- data = self.safe_value(response, 'data', {})
1332
- tickers = self.safe_value(data, 'tickers', [])
1333
- result = {}
1634
+ tickers = []
1635
+ if type == 'spot':
1636
+ tickers = self.safe_list(response, 'data', [])
1637
+ else:
1638
+ data = self.safe_dict(response, 'data', {})
1639
+ tickers = self.safe_list(data, 'symbols', [])
1640
+ result: dict = {}
1334
1641
  for i in range(0, len(tickers)):
1335
- ticker = self.parse_ticker(tickers[i])
1642
+ ticker: dict = {}
1643
+ if type == 'spot':
1644
+ ticker = self.parse_ticker({'result': tickers[i]})
1645
+ else:
1646
+ ticker = self.parse_ticker(tickers[i])
1336
1647
  symbol = ticker['symbol']
1337
1648
  result[symbol] = ticker
1338
1649
  return self.filter_by_array_tickers(result, 'symbol', symbols)
@@ -1340,8 +1651,11 @@ class bitmart(Exchange, ImplicitAPI):
1340
1651
  async def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
1341
1652
  """
1342
1653
  fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1343
- :see: https://developer-pro.bitmart.com/en/spot/#get-depth-v3
1344
- :see: https://developer-pro.bitmart.com/en/futures/#get-market-depth
1654
+
1655
+ https://developer-pro.bitmart.com/en/spot/#get-depth-v3
1656
+ https://developer-pro.bitmart.com/en/futures/#get-market-depth
1657
+ https://developer-pro.bitmart.com/en/futuresv2/#get-market-depth
1658
+
1345
1659
  :param str symbol: unified symbol of the market to fetch the order book for
1346
1660
  :param int [limit]: the maximum amount of order book entries to return
1347
1661
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1349,7 +1663,7 @@ class bitmart(Exchange, ImplicitAPI):
1349
1663
  """
1350
1664
  await self.load_markets()
1351
1665
  market = self.market(symbol)
1352
- request = {
1666
+ request: dict = {
1353
1667
  'symbol': market['id'],
1354
1668
  }
1355
1669
  response = None
@@ -1406,21 +1720,21 @@ class bitmart(Exchange, ImplicitAPI):
1406
1720
  # "trace": "4cad855074664097ac6ba5258c47305d.72.16952643834721135"
1407
1721
  # }
1408
1722
  #
1409
- data = self.safe_value(response, 'data', {})
1723
+ data = self.safe_dict(response, 'data', {})
1410
1724
  timestamp = self.safe_integer_2(data, 'ts', 'timestamp')
1411
1725
  return self.parse_order_book(data, market['symbol'], timestamp)
1412
1726
 
1413
- def parse_trade(self, trade, market: Market = None) -> Trade:
1727
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
1414
1728
  #
1415
1729
  # public fetchTrades spot( amount = count * price )
1416
1730
  #
1417
- # {
1418
- # "amount": "818.94",
1419
- # "order_time": "1637601839035", # ETH/USDT
1420
- # "price": "4221.99",
1421
- # "count": "0.19397",
1422
- # "type": "buy"
1423
- # }
1731
+ # [
1732
+ # "BTC_USDT", # symbol
1733
+ # "1717212457302", # timestamp
1734
+ # "67643.11", # price
1735
+ # "0.00106", # size
1736
+ # "sell" # side
1737
+ # ]
1424
1738
  #
1425
1739
  # spot: fetchMyTrades
1426
1740
  #
@@ -1467,22 +1781,23 @@ class bitmart(Exchange, ImplicitAPI):
1467
1781
  # 'lastTradeID': 6802340762
1468
1782
  # }
1469
1783
  #
1470
- timestamp = self.safe_integer_n(trade, ['order_time', 'createTime', 'create_time'])
1471
- isPublicTrade = ('order_time' in trade)
1784
+ timestamp = self.safe_integer_n(trade, ['createTime', 'create_time', 1])
1785
+ isPublic = self.safe_string(trade, 0)
1786
+ isPublicTrade = (isPublic is not None)
1472
1787
  amount = None
1473
1788
  cost = None
1474
1789
  type = None
1475
1790
  side = None
1476
1791
  if isPublicTrade:
1477
- amount = self.safe_string(trade, 'count')
1792
+ amount = self.safe_string_2(trade, 'count', 3)
1478
1793
  cost = self.safe_string(trade, 'amount')
1479
- side = self.safe_string(trade, 'type')
1794
+ side = self.safe_string_2(trade, 'type', 4)
1480
1795
  else:
1481
1796
  amount = self.safe_string_n(trade, ['size', 'vol', 'fillQty'])
1482
1797
  cost = self.safe_string(trade, 'notional')
1483
1798
  type = self.safe_string(trade, 'type')
1484
1799
  side = self.parse_order_side(self.safe_string(trade, 'side'))
1485
- marketId = self.safe_string(trade, 'symbol')
1800
+ marketId = self.safe_string_2(trade, 'symbol', 0)
1486
1801
  market = self.safe_market(marketId, market)
1487
1802
  feeCostString = self.safe_string_2(trade, 'fee', 'paid_fees')
1488
1803
  fee = None
@@ -1504,7 +1819,7 @@ class bitmart(Exchange, ImplicitAPI):
1504
1819
  'symbol': market['symbol'],
1505
1820
  'type': type,
1506
1821
  'side': side,
1507
- 'price': self.safe_string_2(trade, 'price', 'fillPrice'),
1822
+ 'price': self.safe_string_n(trade, ['price', 'fillPrice', 2]),
1508
1823
  'amount': amount,
1509
1824
  'cost': cost,
1510
1825
  'takerOrMaker': self.safe_string_lower_2(trade, 'tradeRole', 'exec_type'),
@@ -1513,10 +1828,13 @@ class bitmart(Exchange, ImplicitAPI):
1513
1828
 
1514
1829
  async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1515
1830
  """
1516
- get the list of most recent trades for a particular symbol
1831
+ get a list of the most recent trades for a particular symbol
1832
+
1833
+ https://developer-pro.bitmart.com/en/spot/#get-recent-trades-v3
1834
+
1517
1835
  :param str symbol: unified symbol of the market to fetch trades for
1518
1836
  :param int [since]: timestamp in ms of the earliest trade to fetch
1519
- :param int [limit]: the maximum amount of trades to fetch
1837
+ :param int [limit]: the maximum number of trades to fetch
1520
1838
  :param dict [params]: extra parameters specific to the exchange API endpoint
1521
1839
  :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
1522
1840
  """
@@ -1524,33 +1842,30 @@ class bitmart(Exchange, ImplicitAPI):
1524
1842
  market = self.market(symbol)
1525
1843
  if not market['spot']:
1526
1844
  raise NotSupported(self.id + ' fetchTrades() does not support ' + market['type'] + ' orders, only spot orders are accepted')
1527
- request = {
1845
+ request: dict = {
1528
1846
  'symbol': market['id'],
1529
1847
  }
1530
- response = await self.publicGetSpotV1SymbolsTrades(self.extend(request, params))
1531
- #
1532
- # spot
1848
+ if limit is not None:
1849
+ request['limit'] = limit
1850
+ response = await self.publicGetSpotQuotationV3Trades(self.extend(request, params))
1533
1851
  #
1534
1852
  # {
1535
- # "message":"OK",
1536
- # "code":1000,
1537
- # "trace":"222d74c0-8f6d-49d9-8e1b-98118c50eeba",
1538
- # "data":{
1539
- # "trades":[
1540
- # {
1541
- # "amount":"0.005703",
1542
- # "order_time":1599652045394,
1543
- # "price":"0.034029",
1544
- # "count":"0.1676",
1545
- # "type":"sell"
1546
- # },
1547
- # ]
1548
- # }
1853
+ # "code": 1000,
1854
+ # "trace": "58031f9a5bd.111.17117",
1855
+ # "message": "success",
1856
+ # "data": [
1857
+ # [
1858
+ # "BTC_USDT",
1859
+ # "1717212457302",
1860
+ # "67643.11",
1861
+ # "0.00106",
1862
+ # "sell"
1863
+ # ],
1864
+ # ]
1549
1865
  # }
1550
1866
  #
1551
- data = self.safe_value(response, 'data', {})
1552
- trades = self.safe_value(data, 'trades', [])
1553
- return self.parse_trades(trades, market, since, limit)
1867
+ data = self.safe_list(response, 'data', [])
1868
+ return self.parse_trades(data, market, since, limit)
1554
1869
 
1555
1870
  def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
1556
1871
  #
@@ -1617,8 +1932,10 @@ class bitmart(Exchange, ImplicitAPI):
1617
1932
  async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1618
1933
  """
1619
1934
  fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1620
- :see: https://developer-pro.bitmart.com/en/spot/#get-history-k-line-v3
1621
- :see: https://developer-pro.bitmart.com/en/futures/#get-k-line
1935
+
1936
+ https://developer-pro.bitmart.com/en/spot/#get-history-k-line-v3
1937
+ https://developer-pro.bitmart.com/en/futuresv2/#get-k-line
1938
+
1622
1939
  :param str symbol: unified symbol of the market to fetch OHLCV data for
1623
1940
  :param str timeframe: the length of time each candle represents
1624
1941
  :param int [since]: timestamp in ms of the earliest candle to fetch
@@ -1636,7 +1953,7 @@ class bitmart(Exchange, ImplicitAPI):
1636
1953
  market = self.market(symbol)
1637
1954
  duration = self.parse_timeframe(timeframe)
1638
1955
  parsedTimeframe = self.safe_integer(self.timeframes, timeframe)
1639
- request = {
1956
+ request: dict = {
1640
1957
  'symbol': market['id'],
1641
1958
  }
1642
1959
  if parsedTimeframe is not None:
@@ -1650,7 +1967,7 @@ class bitmart(Exchange, ImplicitAPI):
1650
1967
  if since is not None:
1651
1968
  request['after'] = self.parse_to_int((since / 1000)) - 1
1652
1969
  else:
1653
- maxLimit = 1200
1970
+ maxLimit = 500
1654
1971
  if limit is None:
1655
1972
  limit = maxLimit
1656
1973
  limit = min(maxLimit, limit)
@@ -1703,13 +2020,15 @@ class bitmart(Exchange, ImplicitAPI):
1703
2020
  # "trace": "96c989db-e0f5-46f5-bba6-60cfcbde699b"
1704
2021
  # }
1705
2022
  #
1706
- ohlcv = self.safe_value(response, 'data', [])
2023
+ ohlcv = self.safe_list(response, 'data', [])
1707
2024
  return self.parse_ohlcvs(ohlcv, market, timeframe, since, limit)
1708
2025
 
1709
2026
  async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1710
2027
  """
1711
- :see: https://developer-pro.bitmart.com/en/spot/#account-trade-list-v4-signed
1712
- :see: https://developer-pro.bitmart.com/en/futures/#get-order-trade-keyed
2028
+
2029
+ https://developer-pro.bitmart.com/en/spot/#account-trade-list-v4-signed
2030
+ https://developer-pro.bitmart.com/en/futures/#get-order-trade-keyed
2031
+
1713
2032
  fetch all trades made by the user
1714
2033
  :param str symbol: unified market symbol
1715
2034
  :param int [since]: the earliest time in ms to fetch trades for
@@ -1721,7 +2040,7 @@ class bitmart(Exchange, ImplicitAPI):
1721
2040
  """
1722
2041
  await self.load_markets()
1723
2042
  market = None
1724
- request = {}
2043
+ request: dict = {}
1725
2044
  if symbol is not None:
1726
2045
  market = self.market(symbol)
1727
2046
  request['symbol'] = market['id']
@@ -1735,11 +2054,12 @@ class bitmart(Exchange, ImplicitAPI):
1735
2054
  marginMode, params = self.handle_margin_mode_and_params('fetchMyTrades', params)
1736
2055
  if marginMode == 'isolated':
1737
2056
  request['orderMode'] = 'iso_margin'
1738
- options = self.safe_value(self.options, 'fetchMyTrades', {})
1739
- defaultLimit = self.safe_integer(options, 'limit', 200)
2057
+ options = self.safe_dict(self.options, 'fetchMyTrades', {})
2058
+ maxLimit = 200
2059
+ defaultLimit = self.safe_integer(options, 'limit', maxLimit)
1740
2060
  if limit is None:
1741
2061
  limit = defaultLimit
1742
- request['limit'] = limit
2062
+ request['limit'] = min(limit, maxLimit)
1743
2063
  if since is not None:
1744
2064
  request['startTime'] = since
1745
2065
  if until is not None:
@@ -1806,12 +2126,14 @@ class bitmart(Exchange, ImplicitAPI):
1806
2126
  # "trace": "4cad855074634097ac6ba5257c47305d.62.16959616054873723"
1807
2127
  # }
1808
2128
  #
1809
- data = self.safe_value(response, 'data', [])
2129
+ data = self.safe_list(response, 'data', [])
1810
2130
  return self.parse_trades(data, market, since, limit)
1811
2131
 
1812
2132
  async def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1813
2133
  """
1814
- :see: https://developer-pro.bitmart.com/en/spot/#order-trade-list-v4-signed
2134
+
2135
+ https://developer-pro.bitmart.com/en/spot/#order-trade-list-v4-signed
2136
+
1815
2137
  fetch all the trades made from a single order
1816
2138
  :param str id: order id
1817
2139
  :param str symbol: unified market symbol
@@ -1821,33 +2143,33 @@ class bitmart(Exchange, ImplicitAPI):
1821
2143
  :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1822
2144
  """
1823
2145
  await self.load_markets()
1824
- request = {
2146
+ request: dict = {
1825
2147
  'orderId': id,
1826
2148
  }
1827
2149
  response = await self.privatePostSpotV4QueryOrderTrades(self.extend(request, params))
1828
- data = self.safe_value(response, 'data', {})
2150
+ data = self.safe_list(response, 'data', [])
1829
2151
  return self.parse_trades(data, None, since, limit)
1830
2152
 
1831
2153
  def custom_parse_balance(self, response, marketType) -> Balances:
1832
- data = self.safe_value(response, 'data', {})
2154
+ data = self.safe_dict(response, 'data', {})
1833
2155
  wallet = None
1834
2156
  if marketType == 'swap':
1835
- wallet = self.safe_value(response, 'data', [])
2157
+ wallet = self.safe_list(response, 'data', [])
1836
2158
  elif marketType == 'margin':
1837
- wallet = self.safe_value(data, 'symbols', [])
2159
+ wallet = self.safe_list(data, 'symbols', [])
1838
2160
  else:
1839
- wallet = self.safe_value(data, 'wallet', [])
2161
+ wallet = self.safe_list(data, 'wallet', [])
1840
2162
  result = {'info': response}
1841
2163
  if marketType == 'margin':
1842
2164
  for i in range(0, len(wallet)):
1843
2165
  entry = wallet[i]
1844
2166
  marketId = self.safe_string(entry, 'symbol')
1845
2167
  symbol = self.safe_symbol(marketId, None, '_')
1846
- base = self.safe_value(entry, 'base', {})
1847
- quote = self.safe_value(entry, 'quote', {})
2168
+ base = self.safe_dict(entry, 'base', {})
2169
+ quote = self.safe_dict(entry, 'quote', {})
1848
2170
  baseCode = self.safe_currency_code(self.safe_string(base, 'currency'))
1849
2171
  quoteCode = self.safe_currency_code(self.safe_string(quote, 'currency'))
1850
- subResult = {}
2172
+ subResult: dict = {}
1851
2173
  subResult[baseCode] = self.parse_balance_helper(base)
1852
2174
  subResult[quoteCode] = self.parse_balance_helper(quote)
1853
2175
  result[symbol] = self.safe_balance(subResult)
@@ -1877,10 +2199,13 @@ class bitmart(Exchange, ImplicitAPI):
1877
2199
  async def fetch_balance(self, params={}) -> Balances:
1878
2200
  """
1879
2201
  query for balance and get the amount of funds available for trading or funds locked in orders
1880
- :see: https://developer-pro.bitmart.com/en/spot/#get-spot-wallet-balance
1881
- :see: https://developer-pro.bitmart.com/en/futures/#get-contract-assets-detail
1882
- :see: https://developer-pro.bitmart.com/en/spot/#get-account-balance
1883
- :see: https://developer-pro.bitmart.com/en/spot/#get-margin-account-details-isolated
2202
+
2203
+ https://developer-pro.bitmart.com/en/spot/#get-spot-wallet-balance
2204
+ https://developer-pro.bitmart.com/en/futures/#get-contract-assets-detail
2205
+ https://developer-pro.bitmart.com/en/futuresv2/#get-contract-assets-keyed
2206
+ https://developer-pro.bitmart.com/en/spot/#get-account-balance
2207
+ https://developer-pro.bitmart.com/en/spot/#get-margin-account-details-isolated
2208
+
1884
2209
  :param dict [params]: extra parameters specific to the exchange API endpoint
1885
2210
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1886
2211
  """
@@ -1999,7 +2324,7 @@ class bitmart(Exchange, ImplicitAPI):
1999
2324
  #
2000
2325
  return self.custom_parse_balance(response, marketType)
2001
2326
 
2002
- def parse_trading_fee(self, fee, market: Market = None):
2327
+ def parse_trading_fee(self, fee: dict, market: Market = None) -> TradingFeeInterface:
2003
2328
  #
2004
2329
  # {
2005
2330
  # "symbol": "ETH_USDT",
@@ -2014,9 +2339,11 @@ class bitmart(Exchange, ImplicitAPI):
2014
2339
  'symbol': symbol,
2015
2340
  'maker': self.safe_number(fee, 'maker_fee_rate'),
2016
2341
  'taker': self.safe_number(fee, 'taker_fee_rate'),
2342
+ 'percentage': None,
2343
+ 'tierBased': None,
2017
2344
  }
2018
2345
 
2019
- async def fetch_trading_fee(self, symbol: str, params={}):
2346
+ async def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
2020
2347
  """
2021
2348
  fetch the trading fees for a market
2022
2349
  :param str symbol: unified market symbol
@@ -2027,7 +2354,7 @@ class bitmart(Exchange, ImplicitAPI):
2027
2354
  market = self.market(symbol)
2028
2355
  if not market['spot']:
2029
2356
  raise NotSupported(self.id + ' fetchTradingFee() does not support ' + market['type'] + ' orders, only spot orders are accepted')
2030
- request = {
2357
+ request: dict = {
2031
2358
  'symbol': market['id'],
2032
2359
  }
2033
2360
  response = await self.privateGetSpotV1TradeFee(self.extend(request, params))
@@ -2043,12 +2370,12 @@ class bitmart(Exchange, ImplicitAPI):
2043
2370
  # }
2044
2371
  # }
2045
2372
  #
2046
- data = self.safe_value(response, 'data')
2373
+ data = self.safe_dict(response, 'data', {})
2047
2374
  return self.parse_trading_fee(data)
2048
2375
 
2049
- def parse_order(self, order, market: Market = None) -> Order:
2376
+ def parse_order(self, order: dict, market: Market = None) -> Order:
2050
2377
  #
2051
- # createOrder
2378
+ # createOrder, editOrder
2052
2379
  #
2053
2380
  # {
2054
2381
  # "order_id": 2707217580
@@ -2148,7 +2475,7 @@ class bitmart(Exchange, ImplicitAPI):
2148
2475
  trailingActivationPrice = self.safe_number(order, 'activation_price')
2149
2476
  return self.safe_order({
2150
2477
  'id': id,
2151
- 'clientOrderId': self.safe_string(order, 'client_order_id'),
2478
+ 'clientOrderId': self.safe_string_2(order, 'client_order_id', 'clientOrderId'),
2152
2479
  'info': order,
2153
2480
  'timestamp': timestamp,
2154
2481
  'datetime': self.iso8601(timestamp),
@@ -2159,7 +2486,6 @@ class bitmart(Exchange, ImplicitAPI):
2159
2486
  'postOnly': postOnly,
2160
2487
  'side': self.parse_order_side(self.safe_string(order, 'side')),
2161
2488
  'price': self.omit_zero(priceString),
2162
- 'stopPrice': trailingActivationPrice,
2163
2489
  'triggerPrice': trailingActivationPrice,
2164
2490
  'amount': self.omit_zero(self.safe_string(order, 'size')),
2165
2491
  'cost': self.safe_string_2(order, 'filled_notional', 'filledNotional'),
@@ -2172,7 +2498,7 @@ class bitmart(Exchange, ImplicitAPI):
2172
2498
  }, market)
2173
2499
 
2174
2500
  def parse_order_side(self, side):
2175
- sides = {
2501
+ sides: dict = {
2176
2502
  '1': 'buy',
2177
2503
  '2': 'buy',
2178
2504
  '3': 'sell',
@@ -2181,7 +2507,7 @@ class bitmart(Exchange, ImplicitAPI):
2181
2507
  return self.safe_string(sides, side, side)
2182
2508
 
2183
2509
  def parse_order_status_by_type(self, type, status):
2184
- statusesByType = {
2510
+ statusesByType: dict = {
2185
2511
  'spot': {
2186
2512
  '1': 'rejected', # Order failure
2187
2513
  '2': 'open', # Placing order
@@ -2202,13 +2528,15 @@ class bitmart(Exchange, ImplicitAPI):
2202
2528
  '4': 'closed', # Completed
2203
2529
  },
2204
2530
  }
2205
- statuses = self.safe_value(statusesByType, type, {})
2531
+ statuses = self.safe_dict(statusesByType, type, {})
2206
2532
  return self.safe_string(statuses, status, status)
2207
2533
 
2208
2534
  async def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
2209
2535
  """
2210
2536
  create a market buy order by providing the symbol and cost
2211
- :see: https://developer-pro.bitmart.com/en/spot/#new-order-v2-signed
2537
+
2538
+ https://developer-pro.bitmart.com/en/spot/#new-order-v2-signed
2539
+
2212
2540
  :param str symbol: unified symbol of the market to create an order in
2213
2541
  :param float cost: how much you want to trade in units of the quote currency
2214
2542
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2224,15 +2552,19 @@ class bitmart(Exchange, ImplicitAPI):
2224
2552
  async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
2225
2553
  """
2226
2554
  create a trade order
2227
- :see: https://developer-pro.bitmart.com/en/spot/#new-order-v2-signed
2228
- :see: https://developer-pro.bitmart.com/en/spot/#place-margin-order
2229
- :see: https://developer-pro.bitmart.com/en/futures/#submit-order-signed
2230
- :see: https://developer-pro.bitmart.com/en/futures/#submit-plan-order-signed
2555
+
2556
+ https://developer-pro.bitmart.com/en/spot/#new-order-v2-signed
2557
+ https://developer-pro.bitmart.com/en/spot/#place-margin-order
2558
+ https://developer-pro.bitmart.com/en/futures/#submit-order-signed
2559
+ https://developer-pro.bitmart.com/en/futures/#submit-plan-order-signed
2560
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-plan-order-signed
2561
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-tp-or-sl-order-signed
2562
+
2231
2563
  :param str symbol: unified symbol of the market to create an order in
2232
2564
  :param str type: 'market', 'limit' or 'trailing' for swap markets only
2233
2565
  :param str side: 'buy' or 'sell'
2234
2566
  :param float amount: how much of currency you want to trade in units of base currency
2235
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2567
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2236
2568
  :param dict [params]: extra parameters specific to the exchange API endpoint
2237
2569
  :param str [params.marginMode]: 'cross' or 'isolated'
2238
2570
  :param str [params.leverage]: *swap only* leverage level
@@ -2245,6 +2577,9 @@ class bitmart(Exchange, ImplicitAPI):
2245
2577
  :param int [params.activation_price_type]: *swap trailing order only* 1: last price, 2: fair price, default is 1
2246
2578
  :param str [params.trailingPercent]: *swap only* the percent to trail away from the current market price, min 0.1 max 5
2247
2579
  :param str [params.trailingTriggerPrice]: *swap only* the price to trigger a trailing order, default uses the price argument
2580
+ :param str [params.stopLossPrice]: *swap only* the price to trigger a stop-loss order
2581
+ :param str [params.takeProfitPrice]: *swap only* the price to trigger a take-profit order
2582
+ :param int [params.plan_category]: *swap tp/sl only* 1: tp/sl, 2: position tp/sl, default is 1
2248
2583
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2249
2584
  """
2250
2585
  await self.load_markets()
@@ -2252,6 +2587,10 @@ class bitmart(Exchange, ImplicitAPI):
2252
2587
  result = self.handle_margin_mode_and_params('createOrder', params)
2253
2588
  marginMode = self.safe_string(result, 0)
2254
2589
  triggerPrice = self.safe_string_n(params, ['triggerPrice', 'stopPrice', 'trigger_price'])
2590
+ stopLossPrice = self.safe_string(params, 'stopLossPrice')
2591
+ takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
2592
+ isStopLoss = stopLossPrice is not None
2593
+ isTakeProfit = takeProfitPrice is not None
2255
2594
  isTriggerOrder = triggerPrice is not None
2256
2595
  response = None
2257
2596
  if market['spot']:
@@ -2264,6 +2603,8 @@ class bitmart(Exchange, ImplicitAPI):
2264
2603
  swapRequest = self.create_swap_order_request(symbol, type, side, amount, price, params)
2265
2604
  if isTriggerOrder:
2266
2605
  response = await self.privatePostContractPrivateSubmitPlanOrder(swapRequest)
2606
+ elif isStopLoss or isTakeProfit:
2607
+ response = await self.privatePostContractPrivateSubmitTpSlOrder(swapRequest)
2267
2608
  else:
2268
2609
  response = await self.privatePostContractPrivateSubmitOrder(swapRequest)
2269
2610
  #
@@ -2281,7 +2622,7 @@ class bitmart(Exchange, ImplicitAPI):
2281
2622
  # swap
2282
2623
  # {"code":1000,"message":"Ok","data":{"order_id":231116359426639,"price":"market price"},"trace":"7f9c94e10f9d4513bc08a7bfc2a5559a.62.16996369620521911"}
2283
2624
  #
2284
- data = self.safe_value(response, 'data', {})
2625
+ data = self.safe_dict(response, 'data', {})
2285
2626
  order = self.parse_order(data, market)
2286
2627
  order['type'] = type
2287
2628
  order['side'] = side
@@ -2289,17 +2630,82 @@ class bitmart(Exchange, ImplicitAPI):
2289
2630
  order['price'] = price
2290
2631
  return order
2291
2632
 
2633
+ async def create_orders(self, orders: List[OrderRequest], params={}):
2634
+ """
2635
+ create a list of trade orders
2636
+
2637
+ https://developer-pro.bitmart.com/en/spot/#new-batch-order-v4-signed
2638
+
2639
+ :param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
2640
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2641
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2642
+ """
2643
+ await self.load_markets()
2644
+ ordersRequests = []
2645
+ symbol = None
2646
+ market = None
2647
+ for i in range(0, len(orders)):
2648
+ rawOrder = orders[i]
2649
+ marketId = self.safe_string(rawOrder, 'symbol')
2650
+ market = self.market(marketId)
2651
+ if not market['spot']:
2652
+ raise NotSupported(self.id + ' createOrders() supports spot orders only')
2653
+ if symbol is None:
2654
+ symbol = marketId
2655
+ else:
2656
+ if symbol != marketId:
2657
+ raise BadRequest(self.id + ' createOrders() requires all orders to have the same symbol')
2658
+ type = self.safe_string(rawOrder, 'type')
2659
+ side = self.safe_string(rawOrder, 'side')
2660
+ amount = self.safe_value(rawOrder, 'amount')
2661
+ price = self.safe_value(rawOrder, 'price')
2662
+ orderParams = self.safe_dict(rawOrder, 'params', {})
2663
+ orderRequest = self.create_spot_order_request(marketId, type, side, amount, price, orderParams)
2664
+ orderRequest = self.omit(orderRequest, ['symbol']) # not needed because it goes in the outter object
2665
+ ordersRequests.append(orderRequest)
2666
+ request: dict = {
2667
+ 'symbol': market['id'],
2668
+ 'orderParams': ordersRequests,
2669
+ }
2670
+ response = await self.privatePostSpotV4BatchOrders(request)
2671
+ #
2672
+ # {
2673
+ # "message": "OK",
2674
+ # "code": 1000,
2675
+ # "trace": "5fc697fb817a4b5396284786a9b2609a.263.17022620476480263",
2676
+ # "data": {
2677
+ # "code": 0,
2678
+ # "msg": "success",
2679
+ # "data": {
2680
+ # "orderIds": [
2681
+ # "212751308355553320"
2682
+ # ]
2683
+ # }
2684
+ # }
2685
+ # }
2686
+ #
2687
+ data = self.safe_dict(response, 'data', {})
2688
+ innderData = self.safe_dict(data, 'data', {})
2689
+ orderIds = self.safe_list(innderData, 'orderIds', [])
2690
+ parsedOrders = []
2691
+ for i in range(0, len(orderIds)):
2692
+ orderId = orderIds[i]
2693
+ order = self.safe_order({'id': orderId}, market)
2694
+ parsedOrders.append(order)
2695
+ return parsedOrders
2696
+
2292
2697
  def create_swap_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
2293
2698
  """
2294
- * @ignore
2699
+ @ignore
2295
2700
  create a trade order
2296
- :see: https://developer-pro.bitmart.com/en/futures/#submit-order-signed
2297
- :see: https://developer-pro.bitmart.com/en/futures/#submit-plan-order-signed
2701
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-order-signed
2702
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-plan-order-signed
2703
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-tp-or-sl-order-signed
2298
2704
  :param str symbol: unified symbol of the market to create an order in
2299
- :param str type: 'market', 'limit' or 'trailing'
2705
+ :param str type: 'market', 'limit', 'trailing', 'stop_loss', or 'take_profit'
2300
2706
  :param str side: 'buy' or 'sell'
2301
2707
  :param float amount: how much of currency you want to trade in units of base currency
2302
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2708
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2303
2709
  :param dict [params]: extra parameters specific to the exchange API endpoint
2304
2710
  :param int [params.leverage]: leverage level
2305
2711
  :param boolean [params.reduceOnly]: *swap only* reduce only
@@ -2311,10 +2717,21 @@ class bitmart(Exchange, ImplicitAPI):
2311
2717
  :param int [params.activation_price_type]: *swap trailing order only* 1: last price, 2: fair price, default is 1
2312
2718
  :param str [params.trailingPercent]: *swap only* the percent to trail away from the current market price, min 0.1 max 5
2313
2719
  :param str [params.trailingTriggerPrice]: *swap only* the price to trigger a trailing order, default uses the price argument
2720
+ :param str [params.stopLossPrice]: *swap only* the price to trigger a stop-loss order
2721
+ :param str [params.takeProfitPrice]: *swap only* the price to trigger a take-profit order
2722
+ :param int [params.plan_category]: *swap tp/sl only* 1: tp/sl, 2: position tp/sl, default is 1
2314
2723
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2315
2724
  """
2316
2725
  market = self.market(symbol)
2317
- request = {
2726
+ stopLossPrice = self.safe_string(params, 'stopLossPrice')
2727
+ takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
2728
+ isStopLoss = stopLossPrice is not None
2729
+ isTakeProfit = takeProfitPrice is not None
2730
+ if isStopLoss:
2731
+ type = 'stop_loss'
2732
+ elif isTakeProfit:
2733
+ type = 'take_profit'
2734
+ request: dict = {
2318
2735
  'symbol': market['id'],
2319
2736
  'type': type,
2320
2737
  'size': int(self.amount_to_precision(symbol, amount)),
@@ -2323,7 +2740,7 @@ class bitmart(Exchange, ImplicitAPI):
2323
2740
  mode = self.safe_integer(params, 'mode') # only for swap
2324
2741
  isMarketOrder = type == 'market'
2325
2742
  postOnly = None
2326
- reduceOnly = self.safe_value(params, 'reduceOnly')
2743
+ reduceOnly = self.safe_bool(params, 'reduceOnly')
2327
2744
  isExchangeSpecificPo = (mode == 4)
2328
2745
  postOnly, params = self.handle_post_only(isMarketOrder, isExchangeSpecificPo, params)
2329
2746
  ioc = ((timeInForce == 'IOC') or (mode == 3))
@@ -2348,7 +2765,8 @@ class bitmart(Exchange, ImplicitAPI):
2348
2765
  request['activation_price'] = self.price_to_precision(symbol, trailingTriggerPrice)
2349
2766
  request['activation_price_type'] = self.safe_integer(params, 'activation_price_type', 1)
2350
2767
  if isTriggerOrder:
2351
- request['executive_price'] = self.price_to_precision(symbol, price)
2768
+ if isLimitOrder or price is not None:
2769
+ request['executive_price'] = self.price_to_precision(symbol, price)
2352
2770
  request['trigger_price'] = self.price_to_precision(symbol, triggerPrice)
2353
2771
  request['price_type'] = self.safe_integer(params, 'price_type', 1)
2354
2772
  if side == 'buy':
@@ -2361,6 +2779,18 @@ class bitmart(Exchange, ImplicitAPI):
2361
2779
  request['price_way'] = 1
2362
2780
  else:
2363
2781
  request['price_way'] = 2
2782
+ marginMode = None
2783
+ marginMode, params = self.handle_margin_mode_and_params('createOrder', params, 'cross')
2784
+ if isStopLoss or isTakeProfit:
2785
+ reduceOnly = True
2786
+ request['price_type'] = self.safe_integer(params, 'price_type', 1)
2787
+ request['executive_price'] = self.price_to_precision(symbol, price)
2788
+ if isStopLoss:
2789
+ request['trigger_price'] = self.price_to_precision(symbol, stopLossPrice)
2790
+ else:
2791
+ request['trigger_price'] = self.price_to_precision(symbol, takeProfitPrice)
2792
+ else:
2793
+ request['open_type'] = marginMode
2364
2794
  if side == 'buy':
2365
2795
  if reduceOnly:
2366
2796
  request['side'] = 2 # buy close short
@@ -2371,35 +2801,35 @@ class bitmart(Exchange, ImplicitAPI):
2371
2801
  request['side'] = 3 # sell close long
2372
2802
  else:
2373
2803
  request['side'] = 4 # sell open short
2374
- marginMode = None
2375
- marginMode, params = self.handle_margin_mode_and_params('createOrder', params, 'cross')
2376
- request['open_type'] = marginMode
2377
2804
  clientOrderId = self.safe_string(params, 'clientOrderId')
2378
2805
  if clientOrderId is not None:
2379
2806
  params = self.omit(params, 'clientOrderId')
2380
2807
  request['client_order_id'] = clientOrderId
2381
- leverage = self.safe_integer(params, 'leverage', 1)
2382
- params = self.omit(params, ['timeInForce', 'postOnly', 'reduceOnly', 'leverage', 'trailingTriggerPrice', 'trailingPercent', 'triggerPrice', 'stopPrice'])
2383
- request['leverage'] = self.number_to_string(leverage)
2808
+ leverage = self.safe_integer(params, 'leverage')
2809
+ params = self.omit(params, ['timeInForce', 'postOnly', 'reduceOnly', 'leverage', 'trailingTriggerPrice', 'trailingPercent', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice'])
2810
+ if leverage is not None:
2811
+ request['leverage'] = self.number_to_string(leverage)
2812
+ elif isTriggerOrder:
2813
+ request['leverage'] = '1' # for plan orders leverage is required, if not available default to 1
2384
2814
  return self.extend(request, params)
2385
2815
 
2386
2816
  def create_spot_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
2387
2817
  """
2388
- * @ignore
2818
+ @ignore
2389
2819
  create a spot order request
2390
- :see: https://developer-pro.bitmart.com/en/spot/#place-spot-order
2391
- :see: https://developer-pro.bitmart.com/en/spot/#place-margin-order
2820
+ https://developer-pro.bitmart.com/en/spot/#place-spot-order
2821
+ https://developer-pro.bitmart.com/en/spot/#place-margin-order
2392
2822
  :param str symbol: unified symbol of the market to create an order in
2393
2823
  :param str type: 'market' or 'limit'
2394
2824
  :param str side: 'buy' or 'sell'
2395
2825
  :param float amount: how much of currency you want to trade in units of base currency
2396
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2826
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2397
2827
  :param dict [params]: extra parameters specific to the exchange API endpoint
2398
2828
  :param str [params.marginMode]: 'cross' or 'isolated'
2399
2829
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2400
2830
  """
2401
2831
  market = self.market(symbol)
2402
- request = {
2832
+ request: dict = {
2403
2833
  'symbol': market['id'],
2404
2834
  'side': side,
2405
2835
  'type': type,
@@ -2422,7 +2852,7 @@ class bitmart(Exchange, ImplicitAPI):
2422
2852
  elif isMarketOrder:
2423
2853
  # for market buy it requires the amount of quote currency to spend
2424
2854
  if side == 'buy':
2425
- notional = self.safe_number_2(params, 'cost', 'notional')
2855
+ notional = self.safe_string_2(params, 'cost', 'notional')
2426
2856
  params = self.omit(params, 'cost')
2427
2857
  createMarketBuyOrderRequiresPrice = True
2428
2858
  createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
@@ -2432,9 +2862,9 @@ class bitmart(Exchange, ImplicitAPI):
2432
2862
  else:
2433
2863
  amountString = self.number_to_string(amount)
2434
2864
  priceString = self.number_to_string(price)
2435
- notional = self.parse_number(Precise.string_mul(amountString, priceString))
2865
+ notional = Precise.string_mul(amountString, priceString)
2436
2866
  else:
2437
- notional = amount if (notional is None) else notional
2867
+ notional = self.number_to_string(amount) if (notional is None) else notional
2438
2868
  request['notional'] = self.decimal_to_precision(notional, TRUNCATE, market['precision']['price'], self.precisionMode)
2439
2869
  elif side == 'sell':
2440
2870
  request['size'] = self.amount_to_precision(symbol, amount)
@@ -2442,27 +2872,35 @@ class bitmart(Exchange, ImplicitAPI):
2442
2872
  request['type'] = 'limit_maker'
2443
2873
  if ioc:
2444
2874
  request['type'] = 'ioc'
2875
+ clientOrderId = self.safe_string(params, 'clientOrderId')
2876
+ if clientOrderId is not None:
2877
+ params = self.omit(params, 'clientOrderId')
2878
+ request['client_order_id'] = clientOrderId
2445
2879
  return self.extend(request, params)
2446
2880
 
2447
2881
  async def cancel_order(self, id: str, symbol: Str = None, params={}):
2448
2882
  """
2449
2883
  cancels an open order
2450
- :see: https://developer-pro.bitmart.com/en/futures/#cancel-order-signed
2451
- :see: https://developer-pro.bitmart.com/en/spot/#cancel-order-v3-signed
2452
- :see: https://developer-pro.bitmart.com/en/futures/#cancel-plan-order-signed
2453
- :see: https://developer-pro.bitmart.com/en/futures/#cancel-plan-order-signed
2884
+
2885
+ https://developer-pro.bitmart.com/en/futures/#cancel-order-signed
2886
+ https://developer-pro.bitmart.com/en/spot/#cancel-order-v3-signed
2887
+ https://developer-pro.bitmart.com/en/futures/#cancel-plan-order-signed
2888
+ https://developer-pro.bitmart.com/en/futures/#cancel-plan-order-signed
2889
+ https://developer-pro.bitmart.com/en/futures/#cancel-order-signed
2890
+ https://developer-pro.bitmart.com/en/futures/#cancel-plan-order-signed
2891
+
2454
2892
  :param str id: order id
2455
2893
  :param str symbol: unified symbol of the market the order was made in
2456
2894
  :param dict [params]: extra parameters specific to the exchange API endpoint
2457
2895
  :param str [params.clientOrderId]: *spot only* the client order id of the order to cancel
2458
- :param boolean [params.stop]: *swap only* whether the order is a stop order
2896
+ :param boolean [params.trigger]: *swap only* whether the order is a trigger order
2459
2897
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2460
2898
  """
2461
2899
  if symbol is None:
2462
2900
  raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol argument')
2463
2901
  await self.load_markets()
2464
2902
  market = self.market(symbol)
2465
- request = {
2903
+ request: dict = {
2466
2904
  'symbol': market['id'],
2467
2905
  }
2468
2906
  clientOrderId = self.safe_string_2(params, 'clientOrderId', 'client_order_id')
@@ -2475,9 +2913,9 @@ class bitmart(Exchange, ImplicitAPI):
2475
2913
  if market['spot']:
2476
2914
  response = await self.privatePostSpotV3CancelOrder(self.extend(request, params))
2477
2915
  else:
2478
- stop = self.safe_value_2(params, 'stop', 'trigger')
2916
+ trigger = self.safe_bool_2(params, 'stop', 'trigger')
2479
2917
  params = self.omit(params, ['stop', 'trigger'])
2480
- if not stop:
2918
+ if not trigger:
2481
2919
  response = await self.privatePostContractPrivateCancelOrder(self.extend(request, params))
2482
2920
  else:
2483
2921
  response = await self.privatePostContractPrivateCancelPlanOrder(self.extend(request, params))
@@ -2508,7 +2946,7 @@ class bitmart(Exchange, ImplicitAPI):
2508
2946
  return response
2509
2947
  data = self.safe_value(response, 'data')
2510
2948
  if data is True:
2511
- return self.parse_order(id, market)
2949
+ return self.safe_order({'id': id}, market)
2512
2950
  succeeded = self.safe_value(data, 'succeed')
2513
2951
  if succeeded is not None:
2514
2952
  id = self.safe_string(succeeded, 0)
@@ -2518,21 +2956,81 @@ class bitmart(Exchange, ImplicitAPI):
2518
2956
  result = self.safe_value(data, 'result')
2519
2957
  if not result:
2520
2958
  raise InvalidOrder(self.id + ' cancelOrder() ' + symbol + ' order id ' + id + ' is filled or canceled')
2521
- order = self.parse_order(id, market)
2522
- return self.extend(order, {'id': id})
2959
+ order = self.safe_order({'id': id, 'symbol': market['symbol'], 'info': {}}, market)
2960
+ return order
2961
+
2962
+ async def cancel_orders(self, ids: List[str], symbol: Str = None, params={}):
2963
+ """
2964
+ cancel multiple orders
2965
+
2966
+ https://developer-pro.bitmart.com/en/spot/#cancel-batch-order-v4-signed
2967
+
2968
+ :param str[] ids: order ids
2969
+ :param str symbol: unified symbol of the market the order was made in
2970
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2971
+ :param str[] [params.clientOrderIds]: client order ids
2972
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2973
+ """
2974
+ if symbol is None:
2975
+ raise ArgumentsRequired(self.id + ' cancelOrders() requires a symbol argument')
2976
+ await self.load_markets()
2977
+ market = self.market(symbol)
2978
+ if not market['spot']:
2979
+ raise NotSupported(self.id + ' cancelOrders() does not support ' + market['type'] + ' orders, only spot orders are accepted')
2980
+ clientOrderIds = self.safe_list(params, 'clientOrderIds')
2981
+ params = self.omit(params, ['clientOrderIds'])
2982
+ request: dict = {
2983
+ 'symbol': market['id'],
2984
+ }
2985
+ if clientOrderIds is not None:
2986
+ request['clientOrderIds'] = clientOrderIds
2987
+ else:
2988
+ request['orderIds'] = ids
2989
+ response = await self.privatePostSpotV4CancelOrders(self.extend(request, params))
2990
+ #
2991
+ # {
2992
+ # "message": "OK",
2993
+ # "code": 1000,
2994
+ # "trace": "c4edbce860164203954f7c3c81d60fc6.309.17022669632770001",
2995
+ # "data": {
2996
+ # "successIds": [
2997
+ # "213055379155243012"
2998
+ # ],
2999
+ # "failIds": [],
3000
+ # "totalCount": 1,
3001
+ # "successCount": 1,
3002
+ # "failedCount": 0
3003
+ # }
3004
+ # }
3005
+ #
3006
+ data = self.safe_dict(response, 'data', {})
3007
+ allOrders = []
3008
+ successIds = self.safe_list(data, 'successIds', [])
3009
+ for i in range(0, len(successIds)):
3010
+ id = successIds[i]
3011
+ allOrders.append(self.safe_order({'id': id, 'status': 'canceled'}, market))
3012
+ failIds = self.safe_list(data, 'failIds', [])
3013
+ for i in range(0, len(failIds)):
3014
+ id = failIds[i]
3015
+ allOrders.append(self.safe_order({'id': id, 'status': 'failed'}, market))
3016
+ return allOrders
2523
3017
 
2524
3018
  async def cancel_all_orders(self, symbol: Str = None, params={}):
2525
3019
  """
2526
3020
  cancel all open orders in a market
2527
- :see: https://developer-pro.bitmart.com/en/spot/#cancel-all-orders
2528
- :see: https://developer-pro.bitmart.com/en/futures/#cancel-all-orders-signed
3021
+
3022
+ https://developer-pro.bitmart.com/en/spot/#cancel-all-orders
3023
+ https://developer-pro.bitmart.com/en/spot/#new-batch-order-v4-signed
3024
+ https://developer-pro.bitmart.com/en/futures/#cancel-all-orders-signed
3025
+ https://developer-pro.bitmart.com/en/futuresv2/#cancel-all-orders-signed
3026
+
2529
3027
  :param str symbol: unified market symbol of the market to cancel orders in
2530
3028
  :param dict [params]: extra parameters specific to the exchange API endpoint
2531
3029
  :param str [params.side]: *spot only* 'buy' or 'sell'
2532
3030
  :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2533
3031
  """
2534
3032
  await self.load_markets()
2535
- request = {}
3033
+ request: dict = {}
2536
3034
  market = None
2537
3035
  if symbol is not None:
2538
3036
  market = self.market(symbol)
@@ -2541,7 +3039,7 @@ class bitmart(Exchange, ImplicitAPI):
2541
3039
  type = None
2542
3040
  type, params = self.handle_market_type_and_params('cancelAllOrders', market, params)
2543
3041
  if type == 'spot':
2544
- response = await self.privatePostSpotV1CancelOrders(self.extend(request, params))
3042
+ response = await self.privatePostSpotV4CancelAll(self.extend(request, params))
2545
3043
  elif type == 'swap':
2546
3044
  if symbol is None:
2547
3045
  raise ArgumentsRequired(self.id + ' cancelAllOrders() requires a symbol argument')
@@ -2573,7 +3071,7 @@ class bitmart(Exchange, ImplicitAPI):
2573
3071
  market = self.market(symbol)
2574
3072
  if not market['spot']:
2575
3073
  raise NotSupported(self.id + ' fetchOrdersByStatus() does not support ' + market['type'] + ' orders, only spot orders are accepted')
2576
- request = {
3074
+ request: dict = {
2577
3075
  'symbol': market['id'],
2578
3076
  'offset': 1, # max offset * limit < 500
2579
3077
  'N': 100, # max limit is 100
@@ -2615,15 +3113,17 @@ class bitmart(Exchange, ImplicitAPI):
2615
3113
  # }
2616
3114
  # }
2617
3115
  #
2618
- data = self.safe_value(response, 'data', {})
2619
- orders = self.safe_value(data, 'orders', [])
3116
+ data = self.safe_dict(response, 'data', {})
3117
+ orders = self.safe_list(data, 'orders', [])
2620
3118
  return self.parse_orders(orders, market, since, limit)
2621
3119
 
2622
3120
  async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2623
3121
  """
2624
- :see: https://developer-pro.bitmart.com/en/spot/#current-open-orders-v4-signed
2625
- :see: https://developer-pro.bitmart.com/en/futures/#get-all-open-orders-keyed
2626
- :see: https://developer-pro.bitmart.com/en/futures/#get-all-current-plan-orders-keyed
3122
+
3123
+ https://developer-pro.bitmart.com/en/spot/#current-open-orders-v4-signed
3124
+ https://developer-pro.bitmart.com/en/futures/#get-all-open-orders-keyed
3125
+ https://developer-pro.bitmart.com/en/futures/#get-all-current-plan-orders-keyed
3126
+
2627
3127
  fetch all unfilled currently open orders
2628
3128
  :param str symbol: unified market symbol
2629
3129
  :param int [since]: the earliest time in ms to fetch open orders for
@@ -2640,16 +3140,16 @@ class bitmart(Exchange, ImplicitAPI):
2640
3140
  """
2641
3141
  await self.load_markets()
2642
3142
  market = None
2643
- request = {}
3143
+ request: dict = {}
2644
3144
  if symbol is not None:
2645
3145
  market = self.market(symbol)
2646
3146
  request['symbol'] = market['id']
2647
- if limit is not None:
2648
- request['limit'] = limit
2649
3147
  type = None
2650
3148
  response = None
2651
3149
  type, params = self.handle_market_type_and_params('fetchOpenOrders', market, params)
2652
3150
  if type == 'spot':
3151
+ if limit is not None:
3152
+ request['limit'] = min(limit, 200)
2653
3153
  marginMode = None
2654
3154
  marginMode, params = self.handle_margin_mode_and_params('fetchOpenOrders', params)
2655
3155
  if marginMode == 'isolated':
@@ -2662,9 +3162,11 @@ class bitmart(Exchange, ImplicitAPI):
2662
3162
  request['endTime'] = until
2663
3163
  response = await self.privatePostSpotV4QueryOpenOrders(self.extend(request, params))
2664
3164
  elif type == 'swap':
2665
- isStop = self.safe_value_2(params, 'stop', 'trigger')
3165
+ if limit is not None:
3166
+ request['limit'] = min(limit, 100)
3167
+ isTrigger = self.safe_bool_2(params, 'stop', 'trigger')
2666
3168
  params = self.omit(params, ['stop', 'trigger'])
2667
- if isStop:
3169
+ if isTrigger:
2668
3170
  response = await self.privateGetContractPrivateCurrentPlanOrder(self.extend(request, params))
2669
3171
  else:
2670
3172
  trailing = self.safe_bool(params, 'trailing', False)
@@ -2731,13 +3233,16 @@ class bitmart(Exchange, ImplicitAPI):
2731
3233
  # "trace": "7f9d94g10f9d4513bc08a7rfc3a5559a.71.16957022303515933"
2732
3234
  # }
2733
3235
  #
2734
- data = self.safe_value(response, 'data', [])
3236
+ data = self.safe_list(response, 'data', [])
2735
3237
  return self.parse_orders(data, market, since, limit)
2736
3238
 
2737
3239
  async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2738
3240
  """
2739
- :see: https://developer-pro.bitmart.com/en/spot/#account-orders-v4-signed
2740
- :see: https://developer-pro.bitmart.com/en/futures/#get-order-history-keyed
3241
+
3242
+ https://developer-pro.bitmart.com/en/spot/#account-orders-v4-signed
3243
+ https://developer-pro.bitmart.com/en/futures/#get-order-history-keyed
3244
+ https://developer-pro.bitmart.com/en/futuresv2/#get-order-history-keyed
3245
+
2741
3246
  fetches information on multiple closed orders made by the user
2742
3247
  :param str symbol: unified market symbol of the market orders were made in
2743
3248
  :param int [since]: the earliest time in ms to fetch orders for
@@ -2749,7 +3254,7 @@ class bitmart(Exchange, ImplicitAPI):
2749
3254
  """
2750
3255
  await self.load_markets()
2751
3256
  market = None
2752
- request = {}
3257
+ request: dict = {}
2753
3258
  if symbol is not None:
2754
3259
  market = self.market(symbol)
2755
3260
  request['symbol'] = market['id']
@@ -2758,12 +3263,8 @@ class bitmart(Exchange, ImplicitAPI):
2758
3263
  if type != 'spot':
2759
3264
  if symbol is None:
2760
3265
  raise ArgumentsRequired(self.id + ' fetchClosedOrders() requires a symbol argument')
2761
- marginMode = None
2762
- marginMode, params = self.handle_margin_mode_and_params('fetchClosedOrders', params)
2763
- if marginMode == 'isolated':
2764
- request['orderMode'] = 'iso_margin'
2765
- startTimeKey = 'startTime' if (type == 'spot') else 'start_time'
2766
3266
  if since is not None:
3267
+ startTimeKey = 'startTime' if (type == 'spot') else 'start_time'
2767
3268
  request[startTimeKey] = since
2768
3269
  endTimeKey = 'endTime' if (type == 'spot') else 'end_time'
2769
3270
  until = self.safe_integer_2(params, 'until', endTimeKey)
@@ -2772,10 +3273,14 @@ class bitmart(Exchange, ImplicitAPI):
2772
3273
  request[endTimeKey] = until
2773
3274
  response = None
2774
3275
  if type == 'spot':
3276
+ marginMode = None
3277
+ marginMode, params = self.handle_margin_mode_and_params('fetchClosedOrders', params)
3278
+ if marginMode == 'isolated':
3279
+ request['orderMode'] = 'iso_margin'
2775
3280
  response = await self.privatePostSpotV4QueryHistoryOrders(self.extend(request, params))
2776
3281
  else:
2777
3282
  response = await self.privateGetContractPrivateOrderHistory(self.extend(request, params))
2778
- data = self.safe_value(response, 'data', [])
3283
+ data = self.safe_list(response, 'data', [])
2779
3284
  return self.parse_orders(data, market, since, limit)
2780
3285
 
2781
3286
  async def fetch_canceled_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
@@ -2792,9 +3297,12 @@ class bitmart(Exchange, ImplicitAPI):
2792
3297
  async def fetch_order(self, id: str, symbol: Str = None, params={}):
2793
3298
  """
2794
3299
  fetches information on an order made by the user
2795
- :see: https://developer-pro.bitmart.com/en/spot/#query-order-by-id-v4-signed
2796
- :see: https://developer-pro.bitmart.com/en/spot/#query-order-by-clientorderid-v4-signed
2797
- :see: https://developer-pro.bitmart.com/en/futures/#get-order-detail-keyed
3300
+
3301
+ https://developer-pro.bitmart.com/en/spot/#query-order-by-id-v4-signed
3302
+ https://developer-pro.bitmart.com/en/spot/#query-order-by-clientorderid-v4-signed
3303
+ https://developer-pro.bitmart.com/en/futures/#get-order-detail-keyed
3304
+ https://developer-pro.bitmart.com/en/futuresv2/#get-order-detail-keyed
3305
+
2798
3306
  :param str id: the id of the order
2799
3307
  :param str symbol: unified symbol of the market the order was made in
2800
3308
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2804,7 +3312,7 @@ class bitmart(Exchange, ImplicitAPI):
2804
3312
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2805
3313
  """
2806
3314
  await self.load_markets()
2807
- request = {}
3315
+ request: dict = {}
2808
3316
  type = None
2809
3317
  market = None
2810
3318
  response = None
@@ -2882,26 +3390,28 @@ class bitmart(Exchange, ImplicitAPI):
2882
3390
  # "trace": "4cad855075664097af6ba5257c47605d.63.14957831547451715"
2883
3391
  # }
2884
3392
  #
2885
- data = self.safe_value(response, 'data', {})
3393
+ data = self.safe_dict(response, 'data', {})
2886
3394
  return self.parse_order(data, market)
2887
3395
 
2888
- async def fetch_deposit_address(self, code: str, params={}):
3396
+ async def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
2889
3397
  """
2890
3398
  fetch the deposit address for a currency associated with self account
2891
- :see: https://developer-pro.bitmart.com/en/spot/#deposit-address-keyed
3399
+
3400
+ https://developer-pro.bitmart.com/en/spot/#deposit-address-keyed
3401
+
2892
3402
  :param str code: unified currency code
2893
3403
  :param dict [params]: extra parameters specific to the exchange API endpoint
2894
3404
  :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
2895
3405
  """
2896
3406
  await self.load_markets()
2897
3407
  currency = self.currency(code)
2898
- request = {
3408
+ request: dict = {
2899
3409
  'currency': currency['id'],
2900
3410
  }
2901
3411
  if code == 'USDT':
2902
3412
  defaultNetworks = self.safe_value(self.options, 'defaultNetworks')
2903
3413
  defaultNetwork = self.safe_string_upper(defaultNetworks, code)
2904
- networks = self.safe_value(self.options, 'networks', {})
3414
+ networks = self.safe_dict(self.options, 'networks', {})
2905
3415
  networkInner = self.safe_string_upper(params, 'network', defaultNetwork) # self line allows the user to specify either ERC20 or ETH
2906
3416
  networkInner = self.safe_string(networks, networkInner, networkInner) # handle ERC20>ETH alias
2907
3417
  if networkInner is not None:
@@ -2921,10 +3431,10 @@ class bitmart(Exchange, ImplicitAPI):
2921
3431
  # }
2922
3432
  # }
2923
3433
  #
2924
- data = self.safe_value(response, 'data', {})
3434
+ data = self.safe_dict(response, 'data', {})
2925
3435
  return self.parse_deposit_address(data, currency)
2926
3436
 
2927
- def parse_deposit_address(self, depositAddress, currency=None):
3437
+ def parse_deposit_address(self, depositAddress, currency=None) -> DepositAddress:
2928
3438
  #
2929
3439
  # {
2930
3440
  # currency: 'ETH',
@@ -2942,24 +3452,20 @@ class bitmart(Exchange, ImplicitAPI):
2942
3452
  parts = chain.split('-')
2943
3453
  partsLength = len(parts)
2944
3454
  networkId = self.safe_string(parts, partsLength - 1)
2945
- network = self.safe_network_code(networkId, currency)
3455
+ if networkId == self.safe_string(currency, 'name'):
3456
+ network = self.safe_string(currency, 'code')
3457
+ else:
3458
+ network = self.network_id_to_code(networkId)
2946
3459
  self.check_address(address)
2947
3460
  return {
2948
3461
  'info': depositAddress,
2949
3462
  'currency': self.safe_string(currency, 'code'),
3463
+ 'network': network,
2950
3464
  'address': address,
2951
3465
  'tag': self.safe_string(depositAddress, 'address_memo'),
2952
- 'network': network,
2953
3466
  }
2954
3467
 
2955
- def safe_network_code(self, networkId, currency=None):
2956
- name = self.safe_string(currency, 'name')
2957
- if networkId == name:
2958
- code = self.safe_string(currency, 'code')
2959
- return code
2960
- return self.network_id_to_code(networkId)
2961
-
2962
- async def withdraw(self, code: str, amount: float, address, tag=None, params={}):
3468
+ async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}) -> Transaction:
2963
3469
  """
2964
3470
  make a withdrawal
2965
3471
  :param str code: unified currency code
@@ -2973,7 +3479,7 @@ class bitmart(Exchange, ImplicitAPI):
2973
3479
  self.check_address(address)
2974
3480
  await self.load_markets()
2975
3481
  currency = self.currency(code)
2976
- request = {
3482
+ request: dict = {
2977
3483
  'currency': currency['id'],
2978
3484
  'amount': amount,
2979
3485
  'destination': 'To Digital Address', # To Digital Address, To Binance, To OKEX
@@ -2984,7 +3490,7 @@ class bitmart(Exchange, ImplicitAPI):
2984
3490
  if code == 'USDT':
2985
3491
  defaultNetworks = self.safe_value(self.options, 'defaultNetworks')
2986
3492
  defaultNetwork = self.safe_string_upper(defaultNetworks, code)
2987
- networks = self.safe_value(self.options, 'networks', {})
3493
+ networks = self.safe_dict(self.options, 'networks', {})
2988
3494
  network = self.safe_string_upper(params, 'network', defaultNetwork) # self line allows the user to specify either ERC20 or ETH
2989
3495
  network = self.safe_string(networks, network, network) # handle ERC20>ETH alias
2990
3496
  if network is not None:
@@ -3001,7 +3507,7 @@ class bitmart(Exchange, ImplicitAPI):
3001
3507
  # }
3002
3508
  # }
3003
3509
  #
3004
- data = self.safe_value(response, 'data')
3510
+ data = self.safe_dict(response, 'data', {})
3005
3511
  transaction = self.parse_transaction(data, currency)
3006
3512
  return self.extend(transaction, {
3007
3513
  'code': code,
@@ -3013,7 +3519,7 @@ class bitmart(Exchange, ImplicitAPI):
3013
3519
  await self.load_markets()
3014
3520
  if limit is None:
3015
3521
  limit = 50 # max 50
3016
- request = {
3522
+ request: dict = {
3017
3523
  'operation_type': type, # deposit or withdraw
3018
3524
  'offset': 1,
3019
3525
  'N': limit,
@@ -3025,7 +3531,7 @@ class bitmart(Exchange, ImplicitAPI):
3025
3531
  if code == 'USDT':
3026
3532
  defaultNetworks = self.safe_value(self.options, 'defaultNetworks')
3027
3533
  defaultNetwork = self.safe_string_upper(defaultNetworks, code)
3028
- networks = self.safe_value(self.options, 'networks', {})
3534
+ networks = self.safe_dict(self.options, 'networks', {})
3029
3535
  network = self.safe_string_upper(params, 'network', defaultNetwork) # self line allows the user to specify either ERC20 or ETH
3030
3536
  network = self.safe_string(networks, network, network) # handle ERC20>ETH alias
3031
3537
  if network is not None:
@@ -3057,8 +3563,8 @@ class bitmart(Exchange, ImplicitAPI):
3057
3563
  # }
3058
3564
  # }
3059
3565
  #
3060
- data = self.safe_value(response, 'data', {})
3061
- records = self.safe_value(data, 'records', [])
3566
+ data = self.safe_dict(response, 'data', {})
3567
+ records = self.safe_list(data, 'records', [])
3062
3568
  return self.parse_transactions(records, currency, since, limit)
3063
3569
 
3064
3570
  async def fetch_deposit(self, id: str, code: Str = None, params={}):
@@ -3070,7 +3576,7 @@ class bitmart(Exchange, ImplicitAPI):
3070
3576
  :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
3071
3577
  """
3072
3578
  await self.load_markets()
3073
- request = {
3579
+ request: dict = {
3074
3580
  'id': id,
3075
3581
  }
3076
3582
  response = await self.privateGetAccountV1DepositWithdrawDetail(self.extend(request, params))
@@ -3096,8 +3602,8 @@ class bitmart(Exchange, ImplicitAPI):
3096
3602
  # }
3097
3603
  # }
3098
3604
  #
3099
- data = self.safe_value(response, 'data', {})
3100
- record = self.safe_value(data, 'record', {})
3605
+ data = self.safe_dict(response, 'data', {})
3606
+ record = self.safe_dict(data, 'record', {})
3101
3607
  return self.parse_transaction(record)
3102
3608
 
3103
3609
  async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
@@ -3120,7 +3626,7 @@ class bitmart(Exchange, ImplicitAPI):
3120
3626
  :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
3121
3627
  """
3122
3628
  await self.load_markets()
3123
- request = {
3629
+ request: dict = {
3124
3630
  'id': id,
3125
3631
  }
3126
3632
  response = await self.privateGetAccountV1DepositWithdrawDetail(self.extend(request, params))
@@ -3146,8 +3652,8 @@ class bitmart(Exchange, ImplicitAPI):
3146
3652
  # }
3147
3653
  # }
3148
3654
  #
3149
- data = self.safe_value(response, 'data', {})
3150
- record = self.safe_value(data, 'record', {})
3655
+ data = self.safe_dict(response, 'data', {})
3656
+ record = self.safe_dict(data, 'record', {})
3151
3657
  return self.parse_transaction(record)
3152
3658
 
3153
3659
  async def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
@@ -3161,8 +3667,8 @@ class bitmart(Exchange, ImplicitAPI):
3161
3667
  """
3162
3668
  return await self.fetch_transactions_by_type('withdraw', code, since, limit, params)
3163
3669
 
3164
- def parse_transaction_status(self, status):
3165
- statuses = {
3670
+ def parse_transaction_status(self, status: Str):
3671
+ statuses: dict = {
3166
3672
  '0': 'pending', # Create
3167
3673
  '1': 'pending', # Submitted, waiting for withdrawal
3168
3674
  '2': 'pending', # Processing
@@ -3172,7 +3678,7 @@ class bitmart(Exchange, ImplicitAPI):
3172
3678
  }
3173
3679
  return self.safe_string(statuses, status, status)
3174
3680
 
3175
- def parse_transaction(self, transaction, currency: Currency = None) -> Transaction:
3681
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
3176
3682
  #
3177
3683
  # withdraw
3178
3684
  #
@@ -3247,7 +3753,9 @@ class bitmart(Exchange, ImplicitAPI):
3247
3753
  async def repay_isolated_margin(self, symbol: str, code: str, amount, params={}):
3248
3754
  """
3249
3755
  repay borrowed margin and interest
3250
- :see: https://developer-pro.bitmart.com/en/spot/#margin-repay-isolated
3756
+
3757
+ https://developer-pro.bitmart.com/en/spot/#margin-repay-isolated
3758
+
3251
3759
  :param str symbol: unified market symbol
3252
3760
  :param str code: unified currency code of the currency to repay
3253
3761
  :param str amount: the amount to repay
@@ -3257,7 +3765,7 @@ class bitmart(Exchange, ImplicitAPI):
3257
3765
  await self.load_markets()
3258
3766
  market = self.market(symbol)
3259
3767
  currency = self.currency(code)
3260
- request = {
3768
+ request: dict = {
3261
3769
  'symbol': market['id'],
3262
3770
  'currency': currency['id'],
3263
3771
  'amount': self.currency_to_precision(code, amount),
@@ -3273,7 +3781,7 @@ class bitmart(Exchange, ImplicitAPI):
3273
3781
  # }
3274
3782
  # }
3275
3783
  #
3276
- data = self.safe_value(response, 'data', {})
3784
+ data = self.safe_dict(response, 'data', {})
3277
3785
  transaction = self.parse_margin_loan(data, currency)
3278
3786
  return self.extend(transaction, {
3279
3787
  'amount': amount,
@@ -3283,7 +3791,9 @@ class bitmart(Exchange, ImplicitAPI):
3283
3791
  async def borrow_isolated_margin(self, symbol: str, code: str, amount: float, params={}):
3284
3792
  """
3285
3793
  create a loan to borrow margin
3286
- :see: https://developer-pro.bitmart.com/en/spot/#margin-borrow-isolated
3794
+
3795
+ https://developer-pro.bitmart.com/en/spot/#margin-borrow-isolated
3796
+
3287
3797
  :param str symbol: unified market symbol
3288
3798
  :param str code: unified currency code of the currency to borrow
3289
3799
  :param str amount: the amount to borrow
@@ -3293,7 +3803,7 @@ class bitmart(Exchange, ImplicitAPI):
3293
3803
  await self.load_markets()
3294
3804
  market = self.market(symbol)
3295
3805
  currency = self.currency(code)
3296
- request = {
3806
+ request: dict = {
3297
3807
  'symbol': market['id'],
3298
3808
  'currency': currency['id'],
3299
3809
  'amount': self.currency_to_precision(code, amount),
@@ -3309,7 +3819,7 @@ class bitmart(Exchange, ImplicitAPI):
3309
3819
  # }
3310
3820
  # }
3311
3821
  #
3312
- data = self.safe_value(response, 'data', {})
3822
+ data = self.safe_dict(response, 'data', {})
3313
3823
  transaction = self.parse_margin_loan(data, currency)
3314
3824
  return self.extend(transaction, {
3315
3825
  'amount': amount,
@@ -3340,17 +3850,19 @@ class bitmart(Exchange, ImplicitAPI):
3340
3850
  'info': info,
3341
3851
  }
3342
3852
 
3343
- async def fetch_isolated_borrow_rate(self, symbol: str, params={}):
3853
+ async def fetch_isolated_borrow_rate(self, symbol: str, params={}) -> IsolatedBorrowRate:
3344
3854
  """
3345
3855
  fetch the rate of interest to borrow a currency for margin trading
3346
- :see: https://developer-pro.bitmart.com/en/spot/#get-trading-pair-borrowing-rate-and-amount-keyed
3856
+
3857
+ https://developer-pro.bitmart.com/en/spot/#get-trading-pair-borrowing-rate-and-amount-keyed
3858
+
3347
3859
  :param str symbol: unified symbol of the market to fetch the borrow rate for
3348
3860
  :param dict [params]: extra parameters specific to the exchange API endpoint
3349
3861
  :returns dict: an `isolated borrow rate structure <https://github.com/ccxt/ccxt/wiki/Manual#isolated-borrow-rate-structure>`
3350
3862
  """
3351
3863
  await self.load_markets()
3352
3864
  market = self.market(symbol)
3353
- request = {
3865
+ request: dict = {
3354
3866
  'symbol': market['id'],
3355
3867
  }
3356
3868
  response = await self.privateGetSpotV1MarginIsolatedPairs(self.extend(request, params))
@@ -3386,12 +3898,12 @@ class bitmart(Exchange, ImplicitAPI):
3386
3898
  # }
3387
3899
  # }
3388
3900
  #
3389
- data = self.safe_value(response, 'data', {})
3390
- symbols = self.safe_value(data, 'symbols', [])
3391
- borrowRate = self.safe_value(symbols, 0)
3901
+ data = self.safe_dict(response, 'data', {})
3902
+ symbols = self.safe_list(data, 'symbols', [])
3903
+ borrowRate = self.safe_dict(symbols, 0, [])
3392
3904
  return self.parse_isolated_borrow_rate(borrowRate, market)
3393
3905
 
3394
- def parse_isolated_borrow_rate(self, info, market: Market = None):
3906
+ def parse_isolated_borrow_rate(self, info: dict, market: Market = None) -> IsolatedBorrowRate:
3395
3907
  #
3396
3908
  # {
3397
3909
  # "symbol": "BTC_USDT",
@@ -3417,8 +3929,8 @@ class bitmart(Exchange, ImplicitAPI):
3417
3929
  #
3418
3930
  marketId = self.safe_string(info, 'symbol')
3419
3931
  symbol = self.safe_symbol(marketId, market)
3420
- baseData = self.safe_value(info, 'base', {})
3421
- quoteData = self.safe_value(info, 'quote', {})
3932
+ baseData = self.safe_dict(info, 'base', {})
3933
+ quoteData = self.safe_dict(info, 'quote', {})
3422
3934
  baseId = self.safe_string(baseData, 'currency')
3423
3935
  quoteId = self.safe_string(quoteData, 'currency')
3424
3936
  return {
@@ -3433,10 +3945,12 @@ class bitmart(Exchange, ImplicitAPI):
3433
3945
  'info': info,
3434
3946
  }
3435
3947
 
3436
- async def fetch_isolated_borrow_rates(self, params={}):
3948
+ async def fetch_isolated_borrow_rates(self, params={}) -> IsolatedBorrowRates:
3437
3949
  """
3438
3950
  fetch the borrow interest rates of all currencies, currently only works for isolated margin
3439
- :see: https://developer-pro.bitmart.com/en/spot/#get-trading-pair-borrowing-rate-and-amount-keyed
3951
+
3952
+ https://developer-pro.bitmart.com/en/spot/#get-trading-pair-borrowing-rate-and-amount-keyed
3953
+
3440
3954
  :param dict [params]: extra parameters specific to the exchange API endpoint
3441
3955
  :returns dict: a list of `isolated borrow rate structures <https://docs.ccxt.com/#/?id=isolated-borrow-rate-structure>`
3442
3956
  """
@@ -3474,19 +3988,18 @@ class bitmart(Exchange, ImplicitAPI):
3474
3988
  # }
3475
3989
  # }
3476
3990
  #
3477
- data = self.safe_value(response, 'data', {})
3478
- symbols = self.safe_value(data, 'symbols', [])
3479
- result = []
3480
- for i in range(0, len(symbols)):
3481
- symbol = self.safe_value(symbols, i)
3482
- result.append(self.parse_isolated_borrow_rate(symbol))
3483
- return result
3991
+ data = self.safe_dict(response, 'data', {})
3992
+ symbols = self.safe_list(data, 'symbols', [])
3993
+ return self.parse_isolated_borrow_rates(symbols)
3484
3994
 
3485
3995
  async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
3486
3996
  """
3487
3997
  transfer currency internally between wallets on the same account, currently only supports transfer between spot and margin
3488
- :see: https://developer-pro.bitmart.com/en/spot/#margin-asset-transfer-signed
3489
- :see: https://developer-pro.bitmart.com/en/futures/#transfer-signed
3998
+
3999
+ https://developer-pro.bitmart.com/en/spot/#margin-asset-transfer-signed
4000
+ https://developer-pro.bitmart.com/en/futures/#transfer-signed
4001
+ https://developer-pro.bitmart.com/en/futuresv2/#transfer-signed
4002
+
3490
4003
  :param str code: unified currency code
3491
4004
  :param float amount: amount to transfer
3492
4005
  :param str fromAccount: account to transfer from
@@ -3497,7 +4010,7 @@ class bitmart(Exchange, ImplicitAPI):
3497
4010
  await self.load_markets()
3498
4011
  currency = self.currency(code)
3499
4012
  amountToPrecision = self.currency_to_precision(code, amount)
3500
- request = {
4013
+ request: dict = {
3501
4014
  'amount': amountToPrecision,
3502
4015
  'currency': currency['id'],
3503
4016
  }
@@ -3546,13 +4059,13 @@ class bitmart(Exchange, ImplicitAPI):
3546
4059
  # }
3547
4060
  # }
3548
4061
  #
3549
- data = self.safe_value(response, 'data', {})
4062
+ data = self.safe_dict(response, 'data', {})
3550
4063
  return self.extend(self.parse_transfer(data, currency), {
3551
4064
  'status': self.parse_transfer_status(self.safe_string_2(response, 'code', 'message')),
3552
4065
  })
3553
4066
 
3554
- def parse_transfer_status(self, status):
3555
- statuses = {
4067
+ def parse_transfer_status(self, status: Str) -> Str:
4068
+ statuses: dict = {
3556
4069
  '1000': 'ok',
3557
4070
  'OK': 'ok',
3558
4071
  'FINISHED': 'ok',
@@ -3560,20 +4073,20 @@ class bitmart(Exchange, ImplicitAPI):
3560
4073
  return self.safe_string(statuses, status, status)
3561
4074
 
3562
4075
  def parse_transfer_to_account(self, type):
3563
- types = {
4076
+ types: dict = {
3564
4077
  'contract_to_spot': 'spot',
3565
4078
  'spot_to_contract': 'swap',
3566
4079
  }
3567
4080
  return self.safe_string(types, type, type)
3568
4081
 
3569
4082
  def parse_transfer_from_account(self, type):
3570
- types = {
4083
+ types: dict = {
3571
4084
  'contract_to_spot': 'swap',
3572
4085
  'spot_to_contract': 'spot',
3573
4086
  }
3574
4087
  return self.safe_string(types, type, type)
3575
4088
 
3576
- def parse_transfer(self, transfer, currency: Currency = None):
4089
+ def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
3577
4090
  #
3578
4091
  # margin
3579
4092
  #
@@ -3612,10 +4125,12 @@ class bitmart(Exchange, ImplicitAPI):
3612
4125
  'status': self.parse_transfer_status(self.safe_string(transfer, 'state')),
3613
4126
  }
3614
4127
 
3615
- async def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
4128
+ async def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[TransferEntry]:
3616
4129
  """
3617
4130
  fetch a history of internal transfers made on an account, only transfers between spot and swap are supported
3618
- :see: https://developer-pro.bitmart.com/en/futures/#get-transfer-list-signed
4131
+
4132
+ https://developer-pro.bitmart.com/en/futures/#get-transfer-list-signed
4133
+
3619
4134
  :param str code: unified currency code of the currency transferred
3620
4135
  :param int [since]: the earliest time in ms to fetch transfers for
3621
4136
  :param int [limit]: the maximum number of transfer structures to retrieve
@@ -3627,7 +4142,7 @@ class bitmart(Exchange, ImplicitAPI):
3627
4142
  await self.load_markets()
3628
4143
  if limit is None:
3629
4144
  limit = 10
3630
- request = {
4145
+ request: dict = {
3631
4146
  'page': self.safe_integer(params, 'page', 1), # default is 1, max is 1000
3632
4147
  'limit': limit, # default is 10, max is 100
3633
4148
  }
@@ -3639,9 +4154,9 @@ class bitmart(Exchange, ImplicitAPI):
3639
4154
  request['time_start'] = since
3640
4155
  if limit is not None:
3641
4156
  request['limit'] = limit
3642
- until = self.safe_integer_2(params, 'until', 'till') # unified in milliseconds
4157
+ until = self.safe_integer(params, 'until') # unified in milliseconds
3643
4158
  endTime = self.safe_integer(params, 'time_end', until) # exchange-specific in milliseconds
3644
- params = self.omit(params, ['till', 'until'])
4159
+ params = self.omit(params, ['until'])
3645
4160
  if endTime is not None:
3646
4161
  request['time_end'] = endTime
3647
4162
  response = await self.privatePostAccountV1TransferContractList(self.extend(request, params))
@@ -3664,14 +4179,16 @@ class bitmart(Exchange, ImplicitAPI):
3664
4179
  # }
3665
4180
  # }
3666
4181
  #
3667
- data = self.safe_value(response, 'data', {})
3668
- records = self.safe_value(data, 'records', [])
4182
+ data = self.safe_dict(response, 'data', {})
4183
+ records = self.safe_list(data, 'records', [])
3669
4184
  return self.parse_transfers(records, currency, since, limit)
3670
4185
 
3671
- async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4186
+ async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[BorrowInterest]:
3672
4187
  """
3673
4188
  fetch the interest owed by the user for borrowing currency for margin trading
3674
- :see: https://developer-pro.bitmart.com/en/spot/#get-borrow-record-isolated
4189
+
4190
+ https://developer-pro.bitmart.com/en/spot/#get-borrow-record-isolated
4191
+
3675
4192
  :param str code: unified currency code
3676
4193
  :param str symbol: unified market symbol when fetch interest in isolated markets
3677
4194
  :param int [since]: the earliest time in ms to fetch borrrow interest for
@@ -3683,7 +4200,7 @@ class bitmart(Exchange, ImplicitAPI):
3683
4200
  raise ArgumentsRequired(self.id + ' fetchBorrowInterest() requires a symbol argument')
3684
4201
  await self.load_markets()
3685
4202
  market = self.market(symbol)
3686
- request = {
4203
+ request: dict = {
3687
4204
  'symbol': market['id'],
3688
4205
  }
3689
4206
  if limit is not None:
@@ -3712,12 +4229,12 @@ class bitmart(Exchange, ImplicitAPI):
3712
4229
  # }
3713
4230
  # }
3714
4231
  #
3715
- data = self.safe_value(response, 'data', {})
3716
- rows = self.safe_value(data, 'records', [])
4232
+ data = self.safe_dict(response, 'data', {})
4233
+ rows = self.safe_list(data, 'records', [])
3717
4234
  interest = self.parse_borrow_interests(rows, market)
3718
4235
  return self.filter_by_currency_since_limit(interest, code, since, limit)
3719
4236
 
3720
- def parse_borrow_interest(self, info, market: Market = None):
4237
+ def parse_borrow_interest(self, info: dict, market: Market = None) -> BorrowInterest:
3721
4238
  #
3722
4239
  # {
3723
4240
  # "borrow_id": "1657664327844Lk5eJJugXmdHHZoe",
@@ -3734,21 +4251,23 @@ class bitmart(Exchange, ImplicitAPI):
3734
4251
  market = self.safe_market(marketId, market)
3735
4252
  timestamp = self.safe_integer(info, 'create_time')
3736
4253
  return {
4254
+ 'info': info,
3737
4255
  'symbol': self.safe_string(market, 'symbol'),
3738
- 'marginMode': 'isolated',
3739
4256
  'currency': self.safe_currency_code(self.safe_string(info, 'currency')),
3740
4257
  'interest': self.safe_number(info, 'interest_amount'),
3741
4258
  'interestRate': self.safe_number(info, 'hourly_interest'),
3742
4259
  'amountBorrowed': self.safe_number(info, 'borrow_amount'),
4260
+ 'marginMode': 'isolated',
3743
4261
  'timestamp': timestamp, # borrow creation time
3744
4262
  'datetime': self.iso8601(timestamp),
3745
- 'info': info,
3746
4263
  }
3747
4264
 
3748
4265
  async def fetch_open_interest(self, symbol: str, params={}):
3749
4266
  """
3750
4267
  Retrieves the open interest of a currency
3751
- :see: https://developer-pro.bitmart.com/en/futures/#get-futures-openinterest
4268
+
4269
+ https://developer-pro.bitmart.com/en/futuresv2/#get-futures-openinterest
4270
+
3752
4271
  :param str symbol: Unified CCXT market symbol
3753
4272
  :param dict [params]: exchange specific parameters
3754
4273
  :returns dict} an open interest structure{@link https://docs.ccxt.com/#/?id=open-interest-structure:
@@ -3757,7 +4276,7 @@ class bitmart(Exchange, ImplicitAPI):
3757
4276
  market = self.market(symbol)
3758
4277
  if not market['contract']:
3759
4278
  raise BadRequest(self.id + ' fetchOpenInterest() supports contract markets only')
3760
- request = {
4279
+ request: dict = {
3761
4280
  'symbol': market['id'],
3762
4281
  }
3763
4282
  response = await self.publicGetContractPublicOpenInterest(self.extend(request, params))
@@ -3774,7 +4293,7 @@ class bitmart(Exchange, ImplicitAPI):
3774
4293
  # "trace": "7f9c94e10f9d4513bc08a7bfc2a5559a.72.16946575108274991"
3775
4294
  # }
3776
4295
  #
3777
- data = self.safe_value(response, 'data', {})
4296
+ data = self.safe_dict(response, 'data', {})
3778
4297
  return self.parse_open_interest(data, market)
3779
4298
 
3780
4299
  def parse_open_interest(self, interest, market: Market = None):
@@ -3800,7 +4319,10 @@ class bitmart(Exchange, ImplicitAPI):
3800
4319
  async def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
3801
4320
  """
3802
4321
  set the level of leverage for a market
3803
- :see: https://developer-pro.bitmart.com/en/futures/#submit-leverage-signed
4322
+
4323
+ https://developer-pro.bitmart.com/en/futures/#submit-leverage-signed
4324
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-leverage-signed
4325
+
3804
4326
  :param float leverage: the rate of leverage
3805
4327
  :param str symbol: unified market symbol
3806
4328
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -3816,17 +4338,19 @@ class bitmart(Exchange, ImplicitAPI):
3816
4338
  market = self.market(symbol)
3817
4339
  if not market['swap']:
3818
4340
  raise BadSymbol(self.id + ' setLeverage() supports swap contracts only')
3819
- request = {
4341
+ request: dict = {
3820
4342
  'symbol': market['id'],
3821
4343
  'leverage': str(leverage),
3822
4344
  'open_type': marginMode,
3823
4345
  }
3824
4346
  return await self.privatePostContractPrivateSubmitLeverage(self.extend(request, params))
3825
4347
 
3826
- async def fetch_funding_rate(self, symbol: str, params={}):
4348
+ async def fetch_funding_rate(self, symbol: str, params={}) -> FundingRate:
3827
4349
  """
3828
4350
  fetch the current funding rate
3829
- :see: https://developer-pro.bitmart.com/en/futures/#get-current-funding-rate
4351
+
4352
+ https://developer-pro.bitmart.com/en/futuresv2/#get-current-funding-rate
4353
+
3830
4354
  :param str symbol: unified market symbol
3831
4355
  :param dict [params]: extra parameters specific to the exchange API endpoint
3832
4356
  :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
@@ -3835,7 +4359,7 @@ class bitmart(Exchange, ImplicitAPI):
3835
4359
  market = self.market(symbol)
3836
4360
  if not market['swap']:
3837
4361
  raise BadSymbol(self.id + ' fetchFundingRate() supports swap contracts only')
3838
- request = {
4362
+ request: dict = {
3839
4363
  'symbol': market['id'],
3840
4364
  }
3841
4365
  response = await self.publicGetContractPublicFundingRate(self.extend(request, params))
@@ -3852,10 +4376,66 @@ class bitmart(Exchange, ImplicitAPI):
3852
4376
  # "trace": "4cad855074654097ac7ba5257c47305d.54.16951844206655589"
3853
4377
  # }
3854
4378
  #
3855
- data = self.safe_value(response, 'data', {})
4379
+ data = self.safe_dict(response, 'data', {})
3856
4380
  return self.parse_funding_rate(data, market)
3857
4381
 
3858
- def parse_funding_rate(self, contract, market: Market = None):
4382
+ async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4383
+ """
4384
+ fetches historical funding rate prices
4385
+
4386
+ https://developer-pro.bitmart.com/en/futuresv2/#get-funding-rate-history
4387
+
4388
+ :param str symbol: unified symbol of the market to fetch the funding rate history for
4389
+ :param int [since]: timestamp in ms of the earliest funding rate to fetch
4390
+ :param int [limit]: the maximum amount of funding rate structures to fetch
4391
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4392
+ :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
4393
+ """
4394
+ if symbol is None:
4395
+ raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
4396
+ await self.load_markets()
4397
+ market = self.market(symbol)
4398
+ request: dict = {
4399
+ 'symbol': market['id'],
4400
+ }
4401
+ if limit is not None:
4402
+ request['limit'] = limit
4403
+ response = await self.publicGetContractPublicFundingRateHistory(self.extend(request, params))
4404
+ #
4405
+ # {
4406
+ # "code": 1000,
4407
+ # "message": "Ok",
4408
+ # "data": {
4409
+ # "list": [
4410
+ # {
4411
+ # "symbol": "BTCUSDT",
4412
+ # "funding_rate": "0.000091412174",
4413
+ # "funding_time": "1734336000000"
4414
+ # },
4415
+ # ]
4416
+ # },
4417
+ # "trace": "fg73d949fgfdf6a40c8fc7f5ae6738.54.345345345345"
4418
+ # }
4419
+ #
4420
+ data = self.safe_dict(response, 'data', {})
4421
+ result = self.safe_list(data, 'list', [])
4422
+ rates = []
4423
+ for i in range(0, len(result)):
4424
+ entry = result[i]
4425
+ marketId = self.safe_string(entry, 'symbol')
4426
+ symbolInner = self.safe_symbol(marketId, market, '-', 'swap')
4427
+ timestamp = self.safe_integer(entry, 'funding_time')
4428
+ rates.append({
4429
+ 'info': entry,
4430
+ 'symbol': symbolInner,
4431
+ 'fundingRate': self.safe_number(entry, 'funding_rate'),
4432
+ 'timestamp': timestamp,
4433
+ 'datetime': self.iso8601(timestamp),
4434
+ })
4435
+ sorted = self.sort_by(rates, 'timestamp')
4436
+ return self.filter_by_symbol_since_limit(sorted, market['symbol'], since, limit)
4437
+
4438
+ def parse_funding_rate(self, contract, market: Market = None) -> FundingRate:
3859
4439
  #
3860
4440
  # {
3861
4441
  # "timestamp": 1695184410697,
@@ -3884,19 +4464,23 @@ class bitmart(Exchange, ImplicitAPI):
3884
4464
  'previousFundingRate': self.safe_number(contract, 'rate_value'),
3885
4465
  'previousFundingTimestamp': None,
3886
4466
  'previousFundingDatetime': None,
4467
+ 'interval': None,
3887
4468
  }
3888
4469
 
3889
4470
  async def fetch_position(self, symbol: str, params={}):
3890
4471
  """
3891
4472
  fetch data on a single open contract trade position
3892
- :see: https://developer-pro.bitmart.com/en/futures/#get-current-position-keyed
4473
+
4474
+ https://developer-pro.bitmart.com/en/futures/#get-current-position-keyed
4475
+ https://developer-pro.bitmart.com/en/futuresv2/#get-current-position-risk-details-keyed
4476
+
3893
4477
  :param str symbol: unified market symbol of the market the position is held in
3894
4478
  :param dict [params]: extra parameters specific to the exchange API endpoint
3895
4479
  :returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
3896
4480
  """
3897
4481
  await self.load_markets()
3898
4482
  market = self.market(symbol)
3899
- request = {
4483
+ request: dict = {
3900
4484
  'symbol': market['id'],
3901
4485
  }
3902
4486
  response = await self.privateGetContractPrivatePosition(self.extend(request, params))
@@ -3929,14 +4513,17 @@ class bitmart(Exchange, ImplicitAPI):
3929
4513
  # "trace":"4cad855074664097ac5ba5257c47305d.67.16963925142065945"
3930
4514
  # }
3931
4515
  #
3932
- data = self.safe_value(response, 'data', [])
3933
- first = self.safe_value(data, 0, {})
4516
+ data = self.safe_list(response, 'data', [])
4517
+ first = self.safe_dict(data, 0, {})
3934
4518
  return self.parse_position(first, market)
3935
4519
 
3936
4520
  async def fetch_positions(self, symbols: Strings = None, params={}):
3937
4521
  """
3938
4522
  fetch all open contract positions
3939
- :see: https://developer-pro.bitmart.com/en/futures/#get-current-position-keyed
4523
+
4524
+ https://developer-pro.bitmart.com/en/futures/#get-current-position-keyed
4525
+ https://developer-pro.bitmart.com/en/futuresv2/#get-current-position-risk-details-keyed
4526
+
3940
4527
  :param str[]|None symbols: list of unified market symbols
3941
4528
  :param dict [params]: extra parameters specific to the exchange API endpoint
3942
4529
  :returns dict[]: a list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
@@ -3948,7 +4535,7 @@ class bitmart(Exchange, ImplicitAPI):
3948
4535
  symbolsLength = len(symbols)
3949
4536
  first = self.safe_string(symbols, 0)
3950
4537
  market = self.market(first)
3951
- request = {}
4538
+ request: dict = {}
3952
4539
  if symbolsLength == 1:
3953
4540
  # only supports symbols or sending one symbol
3954
4541
  request['symbol'] = market['id']
@@ -3982,14 +4569,14 @@ class bitmart(Exchange, ImplicitAPI):
3982
4569
  # "trace":"4cad855074664097ac5ba5257c47305d.67.16963925142065945"
3983
4570
  # }
3984
4571
  #
3985
- positions = self.safe_value(response, 'data', [])
4572
+ positions = self.safe_list(response, 'data', [])
3986
4573
  result = []
3987
4574
  for i in range(0, len(positions)):
3988
4575
  result.append(self.parse_position(positions[i]))
3989
4576
  symbols = self.market_symbols(symbols)
3990
4577
  return self.filter_by_array_positions(result, 'symbol', symbols, False)
3991
4578
 
3992
- def parse_position(self, position, market: Market = None):
4579
+ def parse_position(self, position: dict, market: Market = None):
3993
4580
  #
3994
4581
  # {
3995
4582
  # "symbol": "BTCUSDT",
@@ -4056,7 +4643,9 @@ class bitmart(Exchange, ImplicitAPI):
4056
4643
  async def fetch_my_liquidations(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4057
4644
  """
4058
4645
  retrieves the users liquidated positions
4059
- :see: https://developer-pro.bitmart.com/en/futures/#get-order-history-keyed
4646
+
4647
+ https://developer-pro.bitmart.com/en/futures/#get-order-history-keyed
4648
+
4060
4649
  :param str symbol: unified CCXT market symbol
4061
4650
  :param int [since]: the earliest time in ms to fetch liquidations for
4062
4651
  :param int [limit]: the maximum number of liquidation structures to retrieve
@@ -4070,7 +4659,7 @@ class bitmart(Exchange, ImplicitAPI):
4070
4659
  market = self.market(symbol)
4071
4660
  if not market['swap']:
4072
4661
  raise NotSupported(self.id + ' fetchMyLiquidations() supports swap markets only')
4073
- request = {
4662
+ request: dict = {
4074
4663
  'symbol': market['id'],
4075
4664
  }
4076
4665
  if since is not None:
@@ -4102,7 +4691,7 @@ class bitmart(Exchange, ImplicitAPI):
4102
4691
  # "trace": "4cad855074664097ac6ba4257c47305d.71.16965658195443021"
4103
4692
  # }
4104
4693
  #
4105
- data = self.safe_value(response, 'data', [])
4694
+ data = self.safe_list(response, 'data', [])
4106
4695
  result = []
4107
4696
  for i in range(0, len(data)):
4108
4697
  entry = data[i]
@@ -4149,11 +4738,307 @@ class bitmart(Exchange, ImplicitAPI):
4149
4738
  'datetime': self.iso8601(timestamp),
4150
4739
  })
4151
4740
 
4741
+ async def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}) -> Order:
4742
+ """
4743
+ edits an open order
4744
+
4745
+ https://developer-pro.bitmart.com/en/futuresv2/#modify-plan-order-signed
4746
+ https://developer-pro.bitmart.com/en/futuresv2/#modify-tp-sl-order-signed
4747
+ https://developer-pro.bitmart.com/en/futuresv2/#modify-preset-plan-order-signed
4748
+
4749
+ :param str id: order id
4750
+ :param str symbol: unified symbol of the market to edit an order in
4751
+ :param str type: 'market' or 'limit'
4752
+ :param str side: 'buy' or 'sell'
4753
+ :param float [amount]: how much you want to trade in units of the base currency
4754
+ :param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
4755
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4756
+ :param str [params.triggerPrice]: *swap only* the price to trigger a stop order
4757
+ :param str [params.stopLossPrice]: *swap only* the price to trigger a stop-loss order
4758
+ :param str [params.takeProfitPrice]: *swap only* the price to trigger a take-profit order
4759
+ :param str [params.stopLoss.triggerPrice]: *swap only* the price to trigger a preset stop-loss order
4760
+ :param str [params.takeProfit.triggerPrice]: *swap only* the price to trigger a preset take-profit order
4761
+ :param str [params.clientOrderId]: client order id of the order
4762
+ :param int [params.price_type]: *swap only* 1: last price, 2: fair price, default is 1
4763
+ :param int [params.plan_category]: *swap tp/sl only* 1: tp/sl, 2: position tp/sl, default is 1
4764
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
4765
+ """
4766
+ await self.load_markets()
4767
+ market = self.market(symbol)
4768
+ if not market['swap']:
4769
+ raise NotSupported(self.id + ' editOrder() does not support ' + market['type'] + ' markets, only swap markets are supported')
4770
+ stopLossPrice = self.safe_string(params, 'stopLossPrice')
4771
+ takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
4772
+ triggerPrice = self.safe_string_n(params, ['triggerPrice', 'stopPrice', 'trigger_price'])
4773
+ stopLoss = self.safe_dict(params, 'stopLoss', {})
4774
+ takeProfit = self.safe_dict(params, 'takeProfit', {})
4775
+ presetStopLoss = self.safe_string(stopLoss, 'triggerPrice')
4776
+ presetTakeProfit = self.safe_string(takeProfit, 'triggerPrice')
4777
+ isTriggerOrder = triggerPrice is not None
4778
+ isStopLoss = stopLossPrice is not None
4779
+ isTakeProfit = takeProfitPrice is not None
4780
+ isPresetStopLoss = presetStopLoss is not None
4781
+ isPresetTakeProfit = presetTakeProfit is not None
4782
+ request: dict = {
4783
+ 'symbol': market['id'],
4784
+ }
4785
+ clientOrderId = self.safe_string(params, 'clientOrderId')
4786
+ if clientOrderId is not None:
4787
+ params = self.omit(params, 'clientOrderId')
4788
+ request['client_order_id'] = clientOrderId
4789
+ if id is not None:
4790
+ request['order_id'] = id
4791
+ params = self.omit(params, ['triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'stopLoss', 'takeProfit'])
4792
+ response = None
4793
+ if isTriggerOrder or isStopLoss or isTakeProfit:
4794
+ request['price_type'] = self.safe_integer(params, 'price_type', 1)
4795
+ if price is not None:
4796
+ request['executive_price'] = self.price_to_precision(symbol, price)
4797
+ if isTriggerOrder:
4798
+ request['type'] = type
4799
+ request['trigger_price'] = self.price_to_precision(symbol, triggerPrice)
4800
+ response = await self.privatePostContractPrivateModifyPlanOrder(self.extend(request, params))
4801
+ #
4802
+ # {
4803
+ # "code": 1000,
4804
+ # "message": "Ok",
4805
+ # "data": {
4806
+ # "order_id": "3000023150003503"
4807
+ # },
4808
+ # "trace": "324523453245.108.1734567125596324575"
4809
+ # }
4810
+ #
4811
+ elif isStopLoss or isTakeProfit:
4812
+ request['category'] = type
4813
+ if isStopLoss:
4814
+ request['trigger_price'] = self.price_to_precision(symbol, stopLossPrice)
4815
+ else:
4816
+ request['trigger_price'] = self.price_to_precision(symbol, takeProfitPrice)
4817
+ response = await self.privatePostContractPrivateModifyTpSlOrder(self.extend(request, params))
4818
+ #
4819
+ # {
4820
+ # "code": 1000,
4821
+ # "message": "Ok",
4822
+ # "data": {
4823
+ # "order_id": "3000023150003480"
4824
+ # },
4825
+ # "trace": "23452345.104.1724536582682345459"
4826
+ # }
4827
+ #
4828
+ elif isPresetStopLoss or isPresetTakeProfit:
4829
+ if isPresetStopLoss:
4830
+ request['preset_stop_loss_price_type'] = self.safe_integer(params, 'price_type', 1)
4831
+ request['preset_stop_loss_price'] = self.price_to_precision(symbol, presetStopLoss)
4832
+ else:
4833
+ request['preset_take_profit_price_type'] = self.safe_integer(params, 'price_type', 1)
4834
+ request['preset_take_profit_price'] = self.price_to_precision(symbol, presetTakeProfit)
4835
+ response = await self.privatePostContractPrivateModifyPresetPlanOrder(self.extend(request, params))
4836
+ #
4837
+ # {
4838
+ # "code": 1000,
4839
+ # "message": "Ok",
4840
+ # "data": {
4841
+ # "order_id": "3000023150003496"
4842
+ # },
4843
+ # "trace": "a5c3234534534a836bc476a203.123452.172716624359200197"
4844
+ # }
4845
+ #
4846
+ else:
4847
+ raise NotSupported(self.id + ' editOrder() only supports trigger, stop loss and take profit orders')
4848
+ data = self.safe_dict(response, 'data', {})
4849
+ return self.parse_order(data, market)
4850
+
4851
+ async def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LedgerEntry]:
4852
+ """
4853
+ fetch the history of changes, actions done by the user or operations that altered the balance of the user
4854
+
4855
+ https://developer-pro.bitmart.com/en/futuresv2/#get-transaction-history-keyed
4856
+
4857
+ :param str [code]: unified currency code
4858
+ :param int [since]: timestamp in ms of the earliest ledger entry
4859
+ :param int [limit]: max number of ledger entries to return
4860
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4861
+ :param int [params.until]: timestamp in ms of the latest ledger entry
4862
+ :returns dict[]: a list of `ledger structures <https://docs.ccxt.com/#/?id=ledger>`
4863
+ """
4864
+ await self.load_markets()
4865
+ currency = None
4866
+ if code is not None:
4867
+ currency = self.currency(code)
4868
+ request: dict = {}
4869
+ request, params = self.handle_until_option('end_time', request, params)
4870
+ transactionsRequest = self.fetch_transactions_request(0, None, since, limit, params)
4871
+ response = await self.privateGetContractPrivateTransactionHistory(transactionsRequest)
4872
+ #
4873
+ # {
4874
+ # "code": 1000,
4875
+ # "message": "Ok",
4876
+ # "data": [
4877
+ # {
4878
+ # "time": "1734422402121",
4879
+ # "type": "Funding Fee",
4880
+ # "amount": "-0.00008253",
4881
+ # "asset": "USDT",
4882
+ # "symbol": "LTCUSDT",
4883
+ # "tran_id": "1734422402121",
4884
+ # "flow_type": 3
4885
+ # },
4886
+ # ],
4887
+ # "trace": "4cd11f83c71egfhfgh842790f07241e.23.173442343427772866"
4888
+ # }
4889
+ #
4890
+ data = self.safe_list(response, 'data', [])
4891
+ return self.parse_ledger(data, currency, since, limit)
4892
+
4893
+ def parse_ledger_entry(self, item: dict, currency: Currency = None) -> LedgerEntry:
4894
+ #
4895
+ # {
4896
+ # "time": "1734422402121",
4897
+ # "type": "Funding Fee",
4898
+ # "amount": "-0.00008253",
4899
+ # "asset": "USDT",
4900
+ # "symbol": "LTCUSDT",
4901
+ # "tran_id": "1734422402121",
4902
+ # "flow_type": 3
4903
+ # }
4904
+ #
4905
+ amount = self.safe_string(item, 'amount')
4906
+ direction = None
4907
+ if Precise.string_le(amount, '0'):
4908
+ direction = 'out'
4909
+ amount = Precise.string_mul('-1', amount)
4910
+ else:
4911
+ direction = 'in'
4912
+ currencyId = self.safe_string(item, 'asset')
4913
+ timestamp = self.safe_integer(item, 'time')
4914
+ type = self.safe_string(item, 'type')
4915
+ return self.safe_ledger_entry({
4916
+ 'info': item,
4917
+ 'id': self.safe_string(item, 'tran_id'),
4918
+ 'direction': direction,
4919
+ 'account': None,
4920
+ 'referenceAccount': None,
4921
+ 'referenceId': self.safe_string(item, 'tradeId'),
4922
+ 'type': self.parse_ledger_entry_type(type),
4923
+ 'currency': self.safe_currency_code(currencyId, currency),
4924
+ 'amount': self.parse_number(amount),
4925
+ 'timestamp': timestamp,
4926
+ 'datetime': self.iso8601(timestamp),
4927
+ 'before': None,
4928
+ 'after': None,
4929
+ 'status': None,
4930
+ 'fee': None,
4931
+ }, currency)
4932
+
4933
+ def parse_ledger_entry_type(self, type):
4934
+ ledgerType: dict = {
4935
+ 'Commission Fee': 'fee',
4936
+ 'Funding Fee': 'fee',
4937
+ 'Realized PNL': 'trade',
4938
+ 'Transfer': 'transfer',
4939
+ 'Liquidation Clearance': 'settlement',
4940
+ }
4941
+ return self.safe_string(ledgerType, type, type)
4942
+
4943
+ def fetch_transactions_request(self, flowType: Int = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4944
+ request: dict = {}
4945
+ if flowType is not None:
4946
+ request['flow_type'] = flowType
4947
+ market = None
4948
+ if symbol is not None:
4949
+ market = self.market(symbol)
4950
+ request['symbol'] = market['id']
4951
+ if since is not None:
4952
+ request['start_time'] = since
4953
+ if limit is not None:
4954
+ request['page_size'] = limit
4955
+ request, params = self.handle_until_option('end_time', request, params)
4956
+ return self.extend(request, params)
4957
+
4958
+ async def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[FundingHistory]:
4959
+ """
4960
+ fetch the history of funding payments paid and received on self account
4961
+
4962
+ https://developer-pro.bitmart.com/en/futuresv2/#get-transaction-history-keyed
4963
+
4964
+ :param str [symbol]: unified market symbol
4965
+ :param int [since]: the starting timestamp in milliseconds
4966
+ :param int [limit]: the number of entries to return
4967
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4968
+ :param int [params.until]: the latest time in ms to fetch funding history for
4969
+ :returns dict[]: a list of `funding history structures <https://docs.ccxt.com/#/?id=funding-history-structure>`
4970
+ """
4971
+ await self.load_markets()
4972
+ market = None
4973
+ if symbol is not None:
4974
+ market = self.market(symbol)
4975
+ request: dict = {}
4976
+ request, params = self.handle_until_option('end_time', request, params)
4977
+ transactionsRequest = self.fetch_transactions_request(3, symbol, since, limit, params)
4978
+ response = await self.privateGetContractPrivateTransactionHistory(transactionsRequest)
4979
+ #
4980
+ # {
4981
+ # "code": 1000,
4982
+ # "message": "Ok",
4983
+ # "data": [
4984
+ # {
4985
+ # "time": "1734422402121",
4986
+ # "type": "Funding Fee",
4987
+ # "amount": "-0.00008253",
4988
+ # "asset": "USDT",
4989
+ # "symbol": "LTCUSDT",
4990
+ # "tran_id": "1734422402121",
4991
+ # "flow_type": 3
4992
+ # },
4993
+ # ],
4994
+ # "trace": "4cd11f83c71egfhfgh842790f07241e.23.173442343427772866"
4995
+ # }
4996
+ #
4997
+ data = self.safe_list(response, 'data', [])
4998
+ return self.parse_funding_histories(data, market, since, limit)
4999
+
5000
+ def parse_funding_history(self, contract, market: Market = None):
5001
+ #
5002
+ # {
5003
+ # "time": "1734422402121",
5004
+ # "type": "Funding Fee",
5005
+ # "amount": "-0.00008253",
5006
+ # "asset": "USDT",
5007
+ # "symbol": "LTCUSDT",
5008
+ # "tran_id": "1734422402121",
5009
+ # "flow_type": 3
5010
+ # }
5011
+ #
5012
+ marketId = self.safe_string(contract, 'symbol')
5013
+ currencyId = self.safe_string(contract, 'asset')
5014
+ timestamp = self.safe_integer(contract, 'time')
5015
+ return {
5016
+ 'info': contract,
5017
+ 'symbol': self.safe_symbol(marketId, market, None, 'swap'),
5018
+ 'code': self.safe_currency_code(currencyId),
5019
+ 'timestamp': timestamp,
5020
+ 'datetime': self.iso8601(timestamp),
5021
+ 'id': self.safe_string(contract, 'tran_id'),
5022
+ 'amount': self.safe_number(contract, 'amount'),
5023
+ }
5024
+
5025
+ def parse_funding_histories(self, contracts, market=None, since: Int = None, limit: Int = None) -> List[FundingHistory]:
5026
+ result = []
5027
+ for i in range(0, len(contracts)):
5028
+ contract = contracts[i]
5029
+ result.append(self.parse_funding_history(contract, market))
5030
+ sorted = self.sort_by(result, 'timestamp')
5031
+ return self.filter_by_since_limit(sorted, since, limit)
5032
+
4152
5033
  def nonce(self):
4153
- return self.milliseconds()
5034
+ return self.milliseconds() - self.options['timeDifference']
4154
5035
 
4155
5036
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
4156
- baseUrl = self.implode_hostname(self.urls['api']['rest'])
5037
+ parts = path.split('/')
5038
+ # to do: refactor api endpoints with spot/swap sections
5039
+ category = self.safe_string(parts, 0, 'spot')
5040
+ market = 'spot' if (category == 'spot' or category == 'account') else 'swap'
5041
+ baseUrl = self.implode_hostname(self.urls['api'][market])
4157
5042
  url = baseUrl + '/' + self.implode_params(path, params)
4158
5043
  query = self.omit(params, self.extract_params(path))
4159
5044
  queryString = ''
@@ -4164,7 +5049,7 @@ class bitmart(Exchange, ImplicitAPI):
4164
5049
  url += '?' + queryString
4165
5050
  if api == 'private':
4166
5051
  self.check_required_credentials()
4167
- timestamp = str(self.milliseconds())
5052
+ timestamp = str(self.nonce())
4168
5053
  brokerId = self.safe_string(self.options, 'brokerId', 'CCXTxBitmart000')
4169
5054
  headers = {
4170
5055
  'X-BM-KEY': self.apiKey,
@@ -4180,7 +5065,7 @@ class bitmart(Exchange, ImplicitAPI):
4180
5065
  headers['X-BM-SIGN'] = signature
4181
5066
  return {'url': url, 'method': method, 'body': body, 'headers': headers}
4182
5067
 
4183
- def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
5068
+ def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
4184
5069
  if response is None:
4185
5070
  return None
4186
5071
  #