ccxt-ir 4.3.46.0.3__py2.py3-none-any.whl → 4.5.1__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 (529) hide show
  1. ccxt/__init__.py +39 -35
  2. ccxt/abantether.py +8 -8
  3. ccxt/abstract/alpaca.py +4 -0
  4. ccxt/abstract/apex.py +31 -0
  5. ccxt/abstract/bigone.py +1 -1
  6. ccxt/abstract/binance.py +106 -48
  7. ccxt/abstract/binancecoinm.py +106 -48
  8. ccxt/abstract/binanceus.py +141 -83
  9. ccxt/abstract/binanceusdm.py +106 -48
  10. ccxt/abstract/bingx.py +50 -1
  11. ccxt/abstract/bitbank.py +5 -0
  12. ccxt/abstract/bitfinex.py +136 -65
  13. ccxt/abstract/bitflyer.py +1 -0
  14. ccxt/abstract/bitget.py +67 -0
  15. ccxt/abstract/bitmart.py +19 -1
  16. ccxt/abstract/bitopro.py +1 -0
  17. ccxt/abstract/bitrue.py +68 -68
  18. ccxt/abstract/bitstamp.py +1 -0
  19. ccxt/abstract/blofin.py +30 -0
  20. ccxt/abstract/btcbox.py +2 -0
  21. ccxt/abstract/bybit.py +28 -13
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbaseexchange.py +1 -0
  24. ccxt/abstract/coinbaseinternational.py +1 -1
  25. ccxt/abstract/cryptocom.py +16 -0
  26. ccxt/abstract/cryptomus.py +20 -0
  27. ccxt/abstract/defx.py +69 -0
  28. ccxt/abstract/deribit.py +1 -0
  29. ccxt/abstract/derive.py +117 -0
  30. ccxt/abstract/digifinex.py +1 -0
  31. ccxt/abstract/ellipx.py +25 -0
  32. ccxt/abstract/foxbit.py +26 -0
  33. ccxt/abstract/gate.py +19 -0
  34. ccxt/abstract/gateio.py +19 -0
  35. ccxt/abstract/gemini.py +1 -0
  36. ccxt/abstract/hibachi.py +26 -0
  37. ccxt/abstract/hyperliquid.py +1 -1
  38. ccxt/abstract/independentreserve.py +6 -0
  39. ccxt/abstract/kraken.py +1 -0
  40. ccxt/abstract/krakenfutures.py +4 -0
  41. ccxt/abstract/kucoin.py +10 -0
  42. ccxt/abstract/kucoinfutures.py +18 -0
  43. ccxt/abstract/lbank.py +2 -1
  44. ccxt/abstract/luno.py +1 -0
  45. ccxt/abstract/mexc.py +2 -0
  46. ccxt/abstract/modetrade.py +119 -0
  47. ccxt/abstract/myokx.py +349 -0
  48. ccxt/abstract/oceanex.py +5 -0
  49. ccxt/abstract/okx.py +25 -0
  50. ccxt/abstract/okxus.py +349 -0
  51. ccxt/abstract/onetrading.py +0 -12
  52. ccxt/abstract/paradex.py +23 -0
  53. ccxt/abstract/phemex.py +2 -0
  54. ccxt/abstract/poloniex.py +36 -0
  55. ccxt/abstract/tradeogre.py +3 -1
  56. ccxt/abstract/upbit.py +51 -34
  57. ccxt/abstract/whitebit.py +16 -0
  58. ccxt/abstract/woo.py +64 -6
  59. ccxt/abstract/xt.py +10 -5
  60. ccxt/afratether.py +8 -8
  61. ccxt/alpaca.py +828 -51
  62. ccxt/apex.py +1875 -0
  63. ccxt/arzinja.py +7 -7
  64. ccxt/arzplus.py +9 -9
  65. ccxt/ascendex.py +501 -306
  66. ccxt/async_support/__init__.py +39 -35
  67. ccxt/async_support/abantether.py +8 -8
  68. ccxt/async_support/afratether.py +10 -10
  69. ccxt/async_support/alpaca.py +828 -51
  70. ccxt/async_support/apex.py +1875 -0
  71. ccxt/async_support/arzinja.py +10 -10
  72. ccxt/async_support/arzplus.py +12 -12
  73. ccxt/async_support/ascendex.py +502 -306
  74. ccxt/async_support/base/exchange.py +303 -89
  75. ccxt/async_support/base/ws/cache.py +9 -3
  76. ccxt/async_support/base/ws/client.py +173 -38
  77. ccxt/async_support/base/ws/future.py +25 -37
  78. ccxt/async_support/bequant.py +5 -3
  79. ccxt/async_support/bigone.py +279 -144
  80. ccxt/async_support/binance.py +2347 -1158
  81. ccxt/async_support/binancecoinm.py +9 -3
  82. ccxt/async_support/binanceus.py +17 -3
  83. ccxt/async_support/binanceusdm.py +9 -4
  84. ccxt/async_support/bingx.py +2962 -920
  85. ccxt/async_support/bit2c.py +147 -27
  86. ccxt/async_support/bitbank.py +151 -23
  87. ccxt/async_support/bitbns.py +104 -30
  88. ccxt/async_support/bitfinex.py +3291 -1113
  89. ccxt/async_support/bitflyer.py +202 -27
  90. ccxt/async_support/bitget.py +3683 -1538
  91. ccxt/async_support/bithumb.py +195 -38
  92. ccxt/async_support/bitimen.py +12 -12
  93. ccxt/async_support/bitir.py +38 -38
  94. ccxt/async_support/bitmart.py +1288 -350
  95. ccxt/async_support/bitmex.py +260 -75
  96. ccxt/async_support/bitopro.py +262 -62
  97. ccxt/async_support/bitpin.py +17 -16
  98. ccxt/async_support/bitrue.py +459 -290
  99. ccxt/async_support/bitso.py +199 -54
  100. ccxt/async_support/bitstamp.py +230 -96
  101. ccxt/async_support/bitteam.py +167 -25
  102. ccxt/async_support/{huobijp.py → bittrade.py} +158 -30
  103. ccxt/async_support/bitvavo.py +213 -49
  104. ccxt/async_support/blockchaincom.py +160 -46
  105. ccxt/async_support/blofin.py +502 -120
  106. ccxt/async_support/btcalpha.py +169 -31
  107. ccxt/async_support/btcbox.py +292 -23
  108. ccxt/async_support/btcmarkets.py +211 -58
  109. ccxt/async_support/btcturk.py +161 -38
  110. ccxt/async_support/bybit.py +1775 -1030
  111. ccxt/async_support/cex.py +1440 -1303
  112. ccxt/async_support/coinbase.py +724 -212
  113. ccxt/async_support/coinbaseadvanced.py +2 -1
  114. ccxt/async_support/coinbaseexchange.py +388 -89
  115. ccxt/async_support/coinbaseinternational.py +412 -57
  116. ccxt/async_support/coincatch.py +177 -78
  117. ccxt/async_support/coincheck.py +135 -19
  118. ccxt/async_support/coinex.py +606 -232
  119. ccxt/async_support/coinmate.py +189 -63
  120. ccxt/async_support/coinmetro.py +195 -54
  121. ccxt/async_support/coinone.py +158 -51
  122. ccxt/async_support/coinsph.py +336 -61
  123. ccxt/async_support/coinspot.py +151 -52
  124. ccxt/async_support/cryptocom.py +661 -111
  125. ccxt/async_support/cryptomus.py +1137 -0
  126. ccxt/async_support/defx.py +2071 -0
  127. ccxt/async_support/delta.py +299 -99
  128. ccxt/async_support/deribit.py +348 -126
  129. ccxt/async_support/derive.py +2572 -0
  130. ccxt/async_support/digifinex.py +430 -214
  131. ccxt/async_support/ellipx.py +2029 -0
  132. ccxt/async_support/eterex.py +10 -10
  133. ccxt/async_support/excoino.py +31 -31
  134. ccxt/async_support/exir.py +14 -14
  135. ccxt/async_support/exmo.py +344 -131
  136. ccxt/async_support/exnovin.py +10 -10
  137. ccxt/async_support/farhadexchange.py +12 -12
  138. ccxt/async_support/fmfwio.py +2 -1
  139. ccxt/async_support/foxbit.py +1935 -0
  140. ccxt/async_support/gate.py +1351 -529
  141. ccxt/async_support/gateio.py +2 -1
  142. ccxt/async_support/gemini.py +144 -39
  143. ccxt/async_support/hashkey.py +152 -109
  144. ccxt/async_support/hibachi.py +2080 -0
  145. ccxt/async_support/hitbtc.py +395 -167
  146. ccxt/async_support/hitobit.py +12 -12
  147. ccxt/async_support/hollaex.py +307 -119
  148. ccxt/async_support/htx.py +851 -383
  149. ccxt/async_support/huobi.py +2 -1
  150. ccxt/async_support/hyperliquid.py +1848 -536
  151. ccxt/async_support/independentreserve.py +288 -15
  152. ccxt/async_support/indodax.py +190 -33
  153. ccxt/async_support/jibitex.py +12 -12
  154. ccxt/async_support/kraken.py +795 -351
  155. ccxt/async_support/krakenfutures.py +214 -62
  156. ccxt/async_support/kucoin.py +715 -396
  157. ccxt/async_support/kucoinfutures.py +652 -89
  158. ccxt/async_support/latoken.py +217 -113
  159. ccxt/async_support/lbank.py +425 -97
  160. ccxt/async_support/luno.py +382 -35
  161. ccxt/async_support/mercado.py +113 -6
  162. ccxt/async_support/mexc.py +874 -437
  163. ccxt/async_support/modetrade.py +2818 -0
  164. ccxt/async_support/myokx.py +54 -0
  165. ccxt/async_support/ndax.py +221 -64
  166. ccxt/async_support/nobitex.py +32 -38
  167. ccxt/async_support/novadax.py +190 -34
  168. ccxt/async_support/oceanex.py +217 -28
  169. ccxt/async_support/okcoin.py +253 -145
  170. ccxt/async_support/okexchange.py +11 -11
  171. ccxt/async_support/okx.py +1088 -351
  172. ccxt/async_support/okxus.py +54 -0
  173. ccxt/async_support/ompfinex.py +32 -27
  174. ccxt/async_support/onetrading.py +213 -392
  175. ccxt/async_support/oxfun.py +245 -166
  176. ccxt/async_support/p2b.py +151 -29
  177. ccxt/async_support/paradex.py +562 -49
  178. ccxt/async_support/paymium.py +82 -19
  179. ccxt/async_support/phemex.py +713 -172
  180. ccxt/async_support/poloniex.py +1602 -283
  181. ccxt/async_support/probit.py +224 -95
  182. ccxt/async_support/ramzinex.py +34 -30
  183. ccxt/async_support/sarmayex.py +9 -9
  184. ccxt/async_support/sarrafex.py +13 -13
  185. ccxt/async_support/tabdeal.py +15 -14
  186. ccxt/async_support/tetherland.py +9 -9
  187. ccxt/async_support/timex.py +210 -51
  188. ccxt/async_support/tokocrypto.py +167 -47
  189. ccxt/async_support/tradeogre.py +266 -31
  190. ccxt/async_support/twox.py +9 -9
  191. ccxt/async_support/ubitex.py +12 -12
  192. ccxt/async_support/upbit.py +568 -165
  193. ccxt/async_support/vertex.py +160 -32
  194. ccxt/async_support/wallex.py +12 -12
  195. ccxt/async_support/wavesexchange.py +165 -30
  196. ccxt/async_support/whitebit.py +975 -127
  197. ccxt/async_support/woo.py +1918 -1016
  198. ccxt/async_support/woofipro.py +433 -141
  199. ccxt/async_support/xt.py +649 -193
  200. ccxt/async_support/yobit.py +195 -70
  201. ccxt/async_support/zaif.py +91 -15
  202. ccxt/async_support/zonda.py +151 -36
  203. ccxt/base/decimal_to_precision.py +14 -10
  204. ccxt/base/errors.py +49 -18
  205. ccxt/base/exchange.py +1556 -450
  206. ccxt/base/precise.py +10 -0
  207. ccxt/base/types.py +114 -6
  208. ccxt/bequant.py +5 -3
  209. ccxt/bigone.py +279 -144
  210. ccxt/binance.py +2347 -1158
  211. ccxt/binancecoinm.py +9 -3
  212. ccxt/binanceus.py +17 -3
  213. ccxt/binanceusdm.py +9 -4
  214. ccxt/bingx.py +2962 -920
  215. ccxt/bit2c.py +147 -27
  216. ccxt/bitbank.py +151 -23
  217. ccxt/bitbns.py +104 -30
  218. ccxt/bitfinex.py +3290 -1113
  219. ccxt/bitflyer.py +202 -27
  220. ccxt/bitget.py +3683 -1538
  221. ccxt/bithumb.py +194 -38
  222. ccxt/bitimen.py +9 -9
  223. ccxt/bitir.py +35 -35
  224. ccxt/bitmart.py +1288 -350
  225. ccxt/bitmex.py +260 -75
  226. ccxt/bitopro.py +262 -62
  227. ccxt/bitpin.py +15 -14
  228. ccxt/bitrue.py +459 -290
  229. ccxt/bitso.py +199 -54
  230. ccxt/bitstamp.py +230 -96
  231. ccxt/bitteam.py +167 -25
  232. ccxt/{huobijp.py → bittrade.py} +158 -30
  233. ccxt/bitvavo.py +213 -49
  234. ccxt/blockchaincom.py +160 -46
  235. ccxt/blofin.py +502 -120
  236. ccxt/btcalpha.py +169 -31
  237. ccxt/btcbox.py +291 -23
  238. ccxt/btcmarkets.py +211 -58
  239. ccxt/btcturk.py +161 -38
  240. ccxt/bybit.py +1775 -1030
  241. ccxt/cex.py +1439 -1303
  242. ccxt/coinbase.py +724 -212
  243. ccxt/coinbaseadvanced.py +2 -1
  244. ccxt/coinbaseexchange.py +388 -89
  245. ccxt/coinbaseinternational.py +412 -57
  246. ccxt/coincatch.py +177 -78
  247. ccxt/coincheck.py +135 -19
  248. ccxt/coinex.py +606 -232
  249. ccxt/coinmate.py +189 -63
  250. ccxt/coinmetro.py +194 -54
  251. ccxt/coinone.py +158 -51
  252. ccxt/coinsph.py +336 -61
  253. ccxt/coinspot.py +151 -52
  254. ccxt/cryptocom.py +661 -111
  255. ccxt/cryptomus.py +1137 -0
  256. ccxt/defx.py +2070 -0
  257. ccxt/delta.py +299 -99
  258. ccxt/deribit.py +348 -126
  259. ccxt/derive.py +2571 -0
  260. ccxt/digifinex.py +430 -214
  261. ccxt/ellipx.py +2029 -0
  262. ccxt/eterex.py +7 -7
  263. ccxt/excoino.py +29 -29
  264. ccxt/exir.py +11 -11
  265. ccxt/exmo.py +343 -131
  266. ccxt/exnovin.py +8 -8
  267. ccxt/farhadexchange.py +10 -10
  268. ccxt/fmfwio.py +2 -1
  269. ccxt/foxbit.py +1935 -0
  270. ccxt/gate.py +1351 -529
  271. ccxt/gateio.py +2 -1
  272. ccxt/gemini.py +144 -39
  273. ccxt/hashkey.py +152 -109
  274. ccxt/hibachi.py +2079 -0
  275. ccxt/hitbtc.py +395 -167
  276. ccxt/hitobit.py +9 -9
  277. ccxt/hollaex.py +307 -119
  278. ccxt/htx.py +851 -383
  279. ccxt/huobi.py +2 -1
  280. ccxt/hyperliquid.py +1848 -536
  281. ccxt/independentreserve.py +287 -15
  282. ccxt/indodax.py +190 -33
  283. ccxt/jibitex.py +9 -9
  284. ccxt/kraken.py +794 -351
  285. ccxt/krakenfutures.py +214 -62
  286. ccxt/kucoin.py +715 -396
  287. ccxt/kucoinfutures.py +652 -89
  288. ccxt/latoken.py +217 -113
  289. ccxt/lbank.py +425 -97
  290. ccxt/luno.py +382 -35
  291. ccxt/mercado.py +113 -6
  292. ccxt/mexc.py +873 -437
  293. ccxt/modetrade.py +2818 -0
  294. ccxt/myokx.py +54 -0
  295. ccxt/ndax.py +221 -64
  296. ccxt/nobitex.py +30 -36
  297. ccxt/novadax.py +190 -34
  298. ccxt/oceanex.py +217 -28
  299. ccxt/okcoin.py +253 -145
  300. ccxt/okexchange.py +9 -9
  301. ccxt/okx.py +1088 -351
  302. ccxt/okxus.py +54 -0
  303. ccxt/ompfinex.py +29 -24
  304. ccxt/onetrading.py +213 -392
  305. ccxt/oxfun.py +245 -166
  306. ccxt/p2b.py +151 -29
  307. ccxt/paradex.py +562 -49
  308. ccxt/paymium.py +82 -19
  309. ccxt/phemex.py +712 -172
  310. ccxt/poloniex.py +1601 -283
  311. ccxt/pro/__init__.py +76 -17
  312. ccxt/pro/alpaca.py +21 -6
  313. ccxt/pro/apex.py +984 -0
  314. ccxt/pro/ascendex.py +58 -10
  315. ccxt/pro/bequant.py +6 -1
  316. ccxt/pro/binance.py +728 -156
  317. ccxt/pro/binancecoinm.py +6 -2
  318. ccxt/pro/binanceus.py +8 -4
  319. ccxt/pro/binanceusdm.py +7 -2
  320. ccxt/pro/bingx.py +333 -142
  321. ccxt/pro/bitfinex.py +727 -262
  322. ccxt/pro/bitget.py +570 -79
  323. ccxt/pro/bithumb.py +20 -6
  324. ccxt/pro/bitmart.py +216 -87
  325. ccxt/pro/bitmex.py +47 -9
  326. ccxt/pro/bitopro.py +26 -14
  327. ccxt/pro/bitrue.py +22 -22
  328. ccxt/pro/bitstamp.py +54 -21
  329. ccxt/pro/{huobijp.py → bittrade.py} +7 -6
  330. ccxt/pro/bitvavo.py +191 -67
  331. ccxt/pro/blockchaincom.py +21 -8
  332. ccxt/pro/blofin.py +9 -1
  333. ccxt/pro/bybit.py +632 -245
  334. ccxt/pro/cex.py +59 -24
  335. ccxt/pro/coinbase.py +102 -73
  336. ccxt/pro/coinbaseadvanced.py +2 -1
  337. ccxt/pro/coinbaseexchange.py +8 -8
  338. ccxt/pro/coinbaseinternational.py +181 -25
  339. ccxt/pro/coincatch.py +6 -7
  340. ccxt/pro/coincheck.py +11 -6
  341. ccxt/pro/coinex.py +967 -665
  342. ccxt/pro/coinone.py +16 -9
  343. ccxt/pro/cryptocom.py +448 -45
  344. ccxt/pro/defx.py +831 -0
  345. ccxt/pro/deribit.py +150 -14
  346. ccxt/pro/derive.py +704 -0
  347. ccxt/pro/exmo.py +239 -6
  348. ccxt/pro/gate.py +623 -65
  349. ccxt/pro/gateio.py +2 -1
  350. ccxt/pro/gemini.py +27 -11
  351. ccxt/pro/hashkey.py +2 -2
  352. ccxt/pro/hitbtc.py +196 -91
  353. ccxt/pro/hollaex.py +23 -7
  354. ccxt/pro/htx.py +51 -14
  355. ccxt/pro/huobi.py +2 -1
  356. ccxt/pro/hyperliquid.py +591 -27
  357. ccxt/pro/independentreserve.py +9 -6
  358. ccxt/pro/kraken.py +640 -320
  359. ccxt/pro/krakenfutures.py +62 -35
  360. ccxt/pro/kucoin.py +267 -46
  361. ccxt/pro/kucoinfutures.py +165 -21
  362. ccxt/pro/lbank.py +102 -21
  363. ccxt/pro/luno.py +12 -8
  364. ccxt/pro/mexc.py +877 -111
  365. ccxt/pro/modetrade.py +1271 -0
  366. ccxt/pro/myokx.py +38 -0
  367. ccxt/pro/ndax.py +15 -2
  368. ccxt/pro/okcoin.py +23 -4
  369. ccxt/pro/okx.py +573 -98
  370. ccxt/pro/okxus.py +38 -0
  371. ccxt/pro/onetrading.py +30 -13
  372. ccxt/pro/oxfun.py +131 -27
  373. ccxt/pro/p2b.py +88 -22
  374. ccxt/pro/paradex.py +3 -3
  375. ccxt/pro/phemex.py +75 -21
  376. ccxt/pro/poloniex.py +124 -41
  377. ccxt/pro/probit.py +87 -80
  378. ccxt/pro/tradeogre.py +272 -0
  379. ccxt/pro/upbit.py +152 -12
  380. ccxt/pro/vertex.py +8 -3
  381. ccxt/pro/whitebit.py +58 -5
  382. ccxt/pro/woo.py +228 -37
  383. ccxt/pro/woofipro.py +106 -18
  384. ccxt/pro/xt.py +111 -5
  385. ccxt/probit.py +224 -95
  386. ccxt/protobuf/__init__.py +0 -0
  387. ccxt/protobuf/mexc/PrivateAccountV3Api_pb2.py +37 -0
  388. ccxt/protobuf/mexc/PrivateDealsV3Api_pb2.py +37 -0
  389. ccxt/protobuf/mexc/PrivateOrdersV3Api_pb2.py +37 -0
  390. ccxt/protobuf/mexc/PublicAggreBookTickerV3Api_pb2.py +37 -0
  391. ccxt/protobuf/mexc/PublicAggreDealsV3Api_pb2.py +39 -0
  392. ccxt/protobuf/mexc/PublicAggreDepthsV3Api_pb2.py +39 -0
  393. ccxt/protobuf/mexc/PublicBookTickerBatchV3Api_pb2.py +38 -0
  394. ccxt/protobuf/mexc/PublicBookTickerV3Api_pb2.py +37 -0
  395. ccxt/protobuf/mexc/PublicDealsV3Api_pb2.py +39 -0
  396. ccxt/protobuf/mexc/PublicIncreaseDepthsBatchV3Api_pb2.py +38 -0
  397. ccxt/protobuf/mexc/PublicIncreaseDepthsV3Api_pb2.py +39 -0
  398. ccxt/protobuf/mexc/PublicLimitDepthsV3Api_pb2.py +39 -0
  399. ccxt/protobuf/mexc/PublicMiniTickerV3Api_pb2.py +37 -0
  400. ccxt/protobuf/mexc/PublicMiniTickersV3Api_pb2.py +38 -0
  401. ccxt/protobuf/mexc/PublicSpotKlineV3Api_pb2.py +37 -0
  402. ccxt/protobuf/mexc/PushDataV3ApiWrapper_pb2.py +52 -0
  403. ccxt/protobuf/mexc/__init__.py +0 -0
  404. ccxt/ramzinex.py +32 -28
  405. ccxt/sarmayex.py +7 -7
  406. ccxt/sarrafex.py +10 -10
  407. ccxt/static_dependencies/__init__.py +1 -1
  408. ccxt/static_dependencies/lark/py.typed +0 -0
  409. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  410. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  411. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  412. ccxt/tabdeal.py +13 -12
  413. ccxt/test/tests_async.py +261 -57
  414. ccxt/test/tests_helpers.py +1 -3
  415. ccxt/test/tests_init.py +4 -3
  416. ccxt/test/tests_sync.py +261 -57
  417. ccxt/tetherland.py +7 -7
  418. ccxt/timex.py +210 -51
  419. ccxt/tokocrypto.py +167 -47
  420. ccxt/tradeogre.py +266 -31
  421. ccxt/twox.py +7 -7
  422. ccxt/ubitex.py +9 -9
  423. ccxt/upbit.py +568 -165
  424. ccxt/vertex.py +160 -32
  425. ccxt/wallex.py +9 -9
  426. ccxt/wavesexchange.py +165 -30
  427. ccxt/whitebit.py +975 -127
  428. ccxt/woo.py +1917 -1016
  429. ccxt/woofipro.py +432 -141
  430. ccxt/xt.py +649 -193
  431. ccxt/yobit.py +194 -70
  432. ccxt/zaif.py +91 -15
  433. ccxt/zonda.py +151 -36
  434. {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.1.dist-info}/METADATA +225 -73
  435. ccxt_ir-4.5.1.dist-info/RECORD +743 -0
  436. {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.1.dist-info}/WHEEL +1 -1
  437. ccxt/__test__.py +0 -7
  438. ccxt/abstract/ace.py +0 -15
  439. ccxt/abstract/bitbay.py +0 -53
  440. ccxt/abstract/bitcoincom.py +0 -115
  441. ccxt/abstract/bitfinex2.py +0 -139
  442. ccxt/abstract/bitpanda.py +0 -35
  443. ccxt/abstract/bl3p.py +0 -19
  444. ccxt/abstract/coinlist.py +0 -54
  445. ccxt/abstract/currencycom.py +0 -68
  446. ccxt/abstract/hitbtc3.py +0 -115
  447. ccxt/abstract/idex.py +0 -26
  448. ccxt/abstract/kuna.py +0 -182
  449. ccxt/abstract/lykke.py +0 -29
  450. ccxt/abstract/poloniexfutures.py +0 -48
  451. ccxt/abstract/wazirx.py +0 -30
  452. ccxt/ace.py +0 -1012
  453. ccxt/async_support/ace.py +0 -1012
  454. ccxt/async_support/base/ws/aiohttp_client.py +0 -125
  455. ccxt/async_support/base/ws/fast_client.py +0 -96
  456. ccxt/async_support/bitbay.py +0 -17
  457. ccxt/async_support/bitcoincom.py +0 -17
  458. ccxt/async_support/bitfinex2.py +0 -3552
  459. ccxt/async_support/bitpanda.py +0 -16
  460. ccxt/async_support/bl3p.py +0 -485
  461. ccxt/async_support/coinlist.py +0 -2243
  462. ccxt/async_support/currencycom.py +0 -1950
  463. ccxt/async_support/hitbtc3.py +0 -16
  464. ccxt/async_support/idex.py +0 -1766
  465. ccxt/async_support/kuna.py +0 -1841
  466. ccxt/async_support/lykke.py +0 -1270
  467. ccxt/async_support/poloniexfutures.py +0 -1717
  468. ccxt/async_support/wazirx.py +0 -1224
  469. ccxt/bitbay.py +0 -17
  470. ccxt/bitcoincom.py +0 -17
  471. ccxt/bitfinex2.py +0 -3552
  472. ccxt/bitpanda.py +0 -16
  473. ccxt/bl3p.py +0 -485
  474. ccxt/coinlist.py +0 -2243
  475. ccxt/currencycom.py +0 -1950
  476. ccxt/hitbtc3.py +0 -16
  477. ccxt/idex.py +0 -1766
  478. ccxt/kuna.py +0 -1841
  479. ccxt/lykke.py +0 -1270
  480. ccxt/poloniexfutures.py +0 -1717
  481. ccxt/pro/bitcoincom.py +0 -34
  482. ccxt/pro/bitfinex2.py +0 -1083
  483. ccxt/pro/bitpanda.py +0 -15
  484. ccxt/pro/currencycom.py +0 -536
  485. ccxt/pro/idex.py +0 -672
  486. ccxt/pro/poloniexfutures.py +0 -990
  487. ccxt/pro/wazirx.py +0 -749
  488. ccxt/test/base/__init__.py +0 -29
  489. ccxt/test/base/test_account.py +0 -26
  490. ccxt/test/base/test_balance.py +0 -56
  491. ccxt/test/base/test_borrow_interest.py +0 -35
  492. ccxt/test/base/test_borrow_rate.py +0 -32
  493. ccxt/test/base/test_calculate_fee.py +0 -51
  494. ccxt/test/base/test_crypto.py +0 -127
  495. ccxt/test/base/test_currency.py +0 -76
  496. ccxt/test/base/test_datetime.py +0 -109
  497. ccxt/test/base/test_decimal_to_precision.py +0 -392
  498. ccxt/test/base/test_deep_extend.py +0 -68
  499. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  500. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  501. ccxt/test/base/test_funding_rate_history.py +0 -29
  502. ccxt/test/base/test_last_price.py +0 -31
  503. ccxt/test/base/test_ledger_entry.py +0 -45
  504. ccxt/test/base/test_ledger_item.py +0 -48
  505. ccxt/test/base/test_leverage_tier.py +0 -33
  506. ccxt/test/base/test_liquidation.py +0 -50
  507. ccxt/test/base/test_margin_mode.py +0 -24
  508. ccxt/test/base/test_margin_modification.py +0 -35
  509. ccxt/test/base/test_market.py +0 -193
  510. ccxt/test/base/test_number.py +0 -411
  511. ccxt/test/base/test_ohlcv.py +0 -33
  512. ccxt/test/base/test_open_interest.py +0 -32
  513. ccxt/test/base/test_order.py +0 -64
  514. ccxt/test/base/test_order_book.py +0 -69
  515. ccxt/test/base/test_position.py +0 -60
  516. ccxt/test/base/test_shared_methods.py +0 -353
  517. ccxt/test/base/test_status.py +0 -24
  518. ccxt/test/base/test_throttle.py +0 -126
  519. ccxt/test/base/test_ticker.py +0 -92
  520. ccxt/test/base/test_trade.py +0 -47
  521. ccxt/test/base/test_trading_fee.py +0 -26
  522. ccxt/test/base/test_transaction.py +0 -39
  523. ccxt/test/test_async.py +0 -1649
  524. ccxt/test/test_sync.py +0 -1648
  525. ccxt/wazirx.py +0 -1224
  526. ccxt_ir-4.3.46.0.3.dist-info/RECORD +0 -773
  527. /ccxt/abstract/{huobijp.py → bittrade.py} +0 -0
  528. {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.1.dist-info/licenses}/LICENSE.txt +0 -0
  529. {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.1.dist-info}/top_level.txt +0 -0
@@ -6,7 +6,7 @@
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, Currencies, Currency, Int, IsolatedBorrowRate, IsolatedBorrowRates, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, Transaction, TransferEntry, TransferEntries
9
+ from ccxt.base.types import Any, Balances, BorrowInterest, Currencies, Currency, DepositAddress, FundingHistory, Int, IsolatedBorrowRate, IsolatedBorrowRates, LedgerEntry, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFeeInterface, Transaction, MarketInterface, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import AuthenticationError
@@ -32,7 +32,7 @@ from ccxt.base.precise import Precise
32
32
 
33
33
  class bitmart(Exchange, ImplicitAPI):
34
34
 
35
- def describe(self):
35
+ def describe(self) -> Any:
36
36
  return self.deep_extend(super(bitmart, self).describe(), {
37
37
  'id': 'bitmart',
38
38
  'name': 'BitMart',
@@ -61,6 +61,7 @@ class bitmart(Exchange, ImplicitAPI):
61
61
  'createOrder': True,
62
62
  'createOrders': True,
63
63
  'createPostOnlyOrder': True,
64
+ 'createReduceOnlyOrder': True,
64
65
  'createStopLimitOrder': False,
65
66
  'createStopMarketOrder': False,
66
67
  'createStopOrder': False,
@@ -81,15 +82,17 @@ class bitmart(Exchange, ImplicitAPI):
81
82
  'fetchDeposits': True,
82
83
  'fetchDepositWithdrawFee': True,
83
84
  'fetchDepositWithdrawFees': False,
84
- 'fetchFundingHistory': None,
85
+ 'fetchFundingHistory': True,
85
86
  'fetchFundingRate': True,
86
87
  'fetchFundingRateHistory': False,
87
88
  'fetchFundingRates': False,
88
89
  'fetchIsolatedBorrowRate': True,
89
90
  'fetchIsolatedBorrowRates': True,
91
+ 'fetchLedger': True,
90
92
  'fetchLiquidations': False,
91
93
  'fetchMarginMode': False,
92
94
  'fetchMarkets': True,
95
+ 'fetchMarkOHLCV': True,
93
96
  'fetchMyLiquidations': True,
94
97
  'fetchMyTrades': True,
95
98
  'fetchOHLCV': True,
@@ -101,7 +104,7 @@ class bitmart(Exchange, ImplicitAPI):
101
104
  'fetchOrders': False,
102
105
  'fetchOrderTrades': True,
103
106
  'fetchPosition': True,
104
- 'fetchPositionMode': False,
107
+ 'fetchPositionMode': True,
105
108
  'fetchPositions': True,
106
109
  'fetchStatus': True,
107
110
  'fetchTicker': True,
@@ -114,6 +117,7 @@ class bitmart(Exchange, ImplicitAPI):
114
117
  'fetchTransactionFees': False,
115
118
  'fetchTransfer': False,
116
119
  'fetchTransfers': True,
120
+ 'fetchWithdrawAddresses': True,
117
121
  'fetchWithdrawAddressesByNetwork': False,
118
122
  'fetchWithdrawal': True,
119
123
  'fetchWithdrawals': True,
@@ -122,14 +126,16 @@ class bitmart(Exchange, ImplicitAPI):
122
126
  'repayIsolatedMargin': True,
123
127
  'setLeverage': True,
124
128
  'setMarginMode': False,
129
+ 'setPositionMode': True,
125
130
  'transfer': True,
126
131
  'withdraw': True,
127
132
  },
128
133
  'hostname': 'bitmart.com', # bitmart.info, bitmart.news for Hong Kong users
129
134
  'urls': {
130
- 'logo': 'https://user-images.githubusercontent.com/1294454/129991357-8f47464b-d0f4-41d6-8a82-34122f0d1398.jpg',
135
+ 'logo': 'https://github.com/user-attachments/assets/0623e9c4-f50e-48c9-82bd-65c3908c3a14',
131
136
  'api': {
132
- 'rest': 'https://api-cloud.{hostname}', # bitmart.info for Hong Kong users
137
+ 'spot': 'https://api-cloud.{hostname}',
138
+ 'swap': 'https://api-cloud-v2.{hostname}', # bitmart.info for Hong Kong users
133
139
  },
134
140
  'www': 'https://www.bitmart.com/',
135
141
  'doc': 'https://developer-pro.bitmart.com/',
@@ -172,8 +178,10 @@ class bitmart(Exchange, ImplicitAPI):
172
178
  'contract/public/depth': 5,
173
179
  'contract/public/open-interest': 30,
174
180
  'contract/public/funding-rate': 30,
181
+ 'contract/public/funding-rate-history': 30,
175
182
  'contract/public/kline': 6, # should be 5 but errors
176
183
  'account/v1/currencies': 30,
184
+ 'contract/public/markprice-kline': 5, # 6 times per 1 second
177
185
  },
178
186
  },
179
187
  'private': {
@@ -194,6 +202,7 @@ class bitmart(Exchange, ImplicitAPI):
194
202
  'account/v1/withdraw/charge': 32, # should be 30 but errors
195
203
  'account/v2/deposit-withdraw/history': 7.5,
196
204
  'account/v1/deposit-withdraw/detail': 7.5,
205
+ 'account/v1/withdraw/address/list': 30, # 2 times per 2 seconds
197
206
  # order
198
207
  'spot/v1/order_detail': 1,
199
208
  'spot/v2/orders': 5,
@@ -216,9 +225,15 @@ class bitmart(Exchange, ImplicitAPI):
216
225
  'contract/private/order': 1.2,
217
226
  'contract/private/order-history': 10,
218
227
  'contract/private/position': 10,
228
+ 'contract/private/position-v2': 10,
219
229
  'contract/private/get-open-orders': 1.2,
220
230
  'contract/private/current-plan-order': 1.2,
221
231
  'contract/private/trades': 10,
232
+ 'contract/private/position-risk': 10,
233
+ 'contract/private/affilate/rebate-list': 10,
234
+ 'contract/private/affilate/trade-list': 10,
235
+ 'contract/private/transaction-history': 10,
236
+ 'contract/private/get-position-mode': 1,
222
237
  },
223
238
  'post': {
224
239
  # sub-account endpoints
@@ -244,13 +259,14 @@ class bitmart(Exchange, ImplicitAPI):
244
259
  'spot/v4/query/trades': 5, # 12 times/2 sec = 6/s => 30/6 = 5
245
260
  'spot/v4/query/order-trades': 5, # 12 times/2 sec = 6/s => 30/6 = 5
246
261
  'spot/v4/cancel_orders': 3,
262
+ 'spot/v4/cancel_all': 90,
247
263
  'spot/v4/batch_orders': 3,
248
264
  # newer endpoint
249
265
  'spot/v3/cancel_order': 1,
250
266
  'spot/v2/batch_orders': 1,
251
267
  'spot/v2/submit_order': 1,
252
268
  # margin
253
- 'spot/v1/margin/submit_order': 1,
269
+ 'spot/v1/margin/submit_order': 1.5, # 20 times per second
254
270
  'spot/v1/margin/isolated/borrow': 30,
255
271
  'spot/v1/margin/isolated/repay': 30,
256
272
  'spot/v1/margin/isolated/transfer': 30,
@@ -263,6 +279,14 @@ class bitmart(Exchange, ImplicitAPI):
263
279
  'contract/private/submit-plan-order': 2.5,
264
280
  'contract/private/cancel-plan-order': 1.5,
265
281
  'contract/private/submit-leverage': 2.5,
282
+ 'contract/private/submit-tp-sl-order': 2.5,
283
+ 'contract/private/modify-plan-order': 2.5,
284
+ 'contract/private/modify-preset-plan-order': 2.5,
285
+ 'contract/private/modify-limit-order': 2.5,
286
+ 'contract/private/modify-tp-sl-order': 2.5,
287
+ 'contract/private/submit-trail-order': 2.5, # weight is not provided by the exchange, is set order
288
+ 'contract/private/cancel-trail-order': 1.5, # weight is not provided by the exchange, is set order
289
+ 'contract/private/set-position-mode': 1,
266
290
  },
267
291
  },
268
292
  },
@@ -512,11 +536,14 @@ class bitmart(Exchange, ImplicitAPI):
512
536
  '40045': InvalidOrder, # 400, The order open type is invalid
513
537
  '40046': PermissionDenied, # 403, The account is not opened futures
514
538
  '40047': PermissionDenied, # 403, Services is not available in you countries and areas
515
- '40048': BadRequest, # 403, ClientOrderId only allows a combination of numbers and letters
516
- '40049': BadRequest, # 403, The maximum length of clientOrderId cannot exceed 32
539
+ '40048': InvalidOrder, # 403, ClientOrderId only allows a combination of numbers and letters
540
+ '40049': InvalidOrder, # 403, The maximum length of clientOrderId cannot exceed 32
517
541
  '40050': InvalidOrder, # 403, Client OrderId duplicated with existing orders
518
542
  },
519
- 'broad': {},
543
+ 'broad': {
544
+ 'You contract account available balance not enough': InsufficientFunds,
545
+ 'you contract account available balance not enough': InsufficientFunds,
546
+ },
520
547
  },
521
548
  'commonCurrencies': {
522
549
  '$GM': 'GOLDMINER',
@@ -529,10 +556,13 @@ class bitmart(Exchange, ImplicitAPI):
529
556
  'TRU': 'Truebit', # conflict with TrueFi
530
557
  },
531
558
  'options': {
532
- 'defaultNetwork': 'ERC20',
533
559
  'defaultNetworks': {
534
- 'USDT': 'ERC20',
560
+ 'USDT': 'TRC20',
561
+ 'BTC': 'BTC',
562
+ 'ETH': 'ERC20',
535
563
  },
564
+ 'timeDifference': 0, # the difference between system clock and exchange clock
565
+ 'adjustForTimeDifference': False, # controls the adjustment logic upon instantiation
536
566
  'networks': {
537
567
  'ERC20': 'ERC20',
538
568
  'SOL': 'SOL',
@@ -571,7 +601,7 @@ class bitmart(Exchange, ImplicitAPI):
571
601
  'KSM': 'KSM',
572
602
  'ZEC': 'ZEC',
573
603
  'NAS': 'NAS',
574
- # 'POLYGON': ['MATIC', 'Polygon', 'POLYGON'], # todo: after unification
604
+ 'POLYGON': 'MATIC',
575
605
  'HRC20': 'HECO',
576
606
  'XDC': 'XDC',
577
607
  'ONE': 'ONE',
@@ -580,7 +610,7 @@ class bitmart(Exchange, ImplicitAPI):
580
610
  'ICP': 'Computer',
581
611
  'XTZ': 'XTZ',
582
612
  'MINA': 'MINA',
583
- # 'BEP20': ['BEP20', 'BSC_BNB', 'bep20'], # todo: after unification
613
+ 'BEP20': 'BSC_BNB',
584
614
  'THETA': 'THETA',
585
615
  'AKT': 'AKT',
586
616
  'AR': 'AR',
@@ -684,6 +714,12 @@ class bitmart(Exchange, ImplicitAPI):
684
714
  # undetermined chains:
685
715
  # LEX(for LexThum), TAYCAN(for TRICE), SFL(probably TAYCAN), OMNIA(for APEX), NAC(for NAC), KAG(Kinesis), CEM(crypto emergency), XVM(for Venidium), NEVM(for NEVM), IGT20(for IGNITE), FILM(FILMCredits), CC(CloudCoin), MERGE(MERGE), LTNM(Bitcoin latinum), PLUGCN( PlugChain), DINGO(dingo), LED(LEDGIS), AVAT(AVAT), VSOL(Vsolidus), EPIC(EPIC cash), NFC(netflowcoin), mrx(Metrix Coin), Idena(idena network), PKT(PKT Cash), BondDex(BondDex), XBN(XBN), KALAM(Kalamint), REV(RChain), KRC20(MyDeFiPet), ARC20(Hurricane Token), GMD(Coop network), BERS(Berith), ZEBI(Zebi), BRC(Baer Chain), DAPS(DAPS Coin), APL(Gold Secured Currency), NDAU(NDAU), WICC(WICC), UPG(Unipay God), TSL(TreasureSL), MXW(Maxonrow), CLC(Cifculation), SMH(SMH Coin), XIN(CPCoin), RDD(ReddCoin), OK(Okcash), KAR(KAR), CCX(ConcealNetwork),
686
716
  },
717
+ 'networksById': {
718
+ 'ETH': 'ERC20',
719
+ 'Ethereum': 'ERC20',
720
+ 'USDT': 'OMNI', # the default USDT network for bitmart is OMNI
721
+ 'Bitcoin': 'BTC',
722
+ },
687
723
  'defaultType': 'spot', # 'spot', 'swap'
688
724
  'fetchBalance': {
689
725
  'type': 'spot', # 'spot', 'swap', 'account'
@@ -695,11 +731,160 @@ class bitmart(Exchange, ImplicitAPI):
695
731
  'createMarketBuyOrderRequiresPrice': True,
696
732
  'brokerId': 'CCXTxBitmart000',
697
733
  },
734
+ 'features': {
735
+ 'default': {
736
+ 'sandbox': False,
737
+ 'createOrder': {
738
+ 'marginMode': True,
739
+ 'triggerPrice': False,
740
+ 'triggerPriceType': None,
741
+ 'triggerDirection': False,
742
+ 'stopLossPrice': False,
743
+ 'takeProfitPrice': False,
744
+ 'attachedStopLossTakeProfit': None,
745
+ 'timeInForce': {
746
+ 'IOC': True,
747
+ 'FOK': False,
748
+ 'PO': True,
749
+ 'GTD': False,
750
+ },
751
+ 'hedged': False,
752
+ 'trailing': False,
753
+ 'marketBuyRequiresPrice': False, # todo: https://developer-pro.bitmart.com/en/spot/#new-order-v2-signed
754
+ 'marketBuyByCost': True,
755
+ 'leverage': True, # todo: implement
756
+ 'selfTradePrevention': False,
757
+ 'iceberg': False,
758
+ },
759
+ 'createOrders': {
760
+ 'max': 10,
761
+ },
762
+ 'fetchMyTrades': {
763
+ 'marginMode': True,
764
+ 'limit': 200,
765
+ 'daysBack': None,
766
+ 'untilDays': 99999,
767
+ 'symbolRequired': False,
768
+ },
769
+ 'fetchOrder': {
770
+ 'marginMode': False,
771
+ 'trigger': False,
772
+ 'trailing': False,
773
+ 'symbolRequired': False,
774
+ },
775
+ 'fetchOpenOrders': {
776
+ 'marginMode': True,
777
+ 'limit': 200,
778
+ 'trigger': False,
779
+ 'trailing': False,
780
+ 'symbolRequired': False,
781
+ },
782
+ 'fetchOrders': None,
783
+ 'fetchClosedOrders': {
784
+ 'marginMode': True,
785
+ 'limit': 200,
786
+ 'daysBack': None,
787
+ 'daysBackCanceled': None,
788
+ 'untilDays': None,
789
+ 'trigger': False,
790
+ 'trailing': False,
791
+ 'symbolRequired': False,
792
+ },
793
+ 'fetchOHLCV': {
794
+ 'limit': 1000, # variable timespans for recent endpoint, 200 for historical
795
+ },
796
+ },
797
+ 'forDerivatives': {
798
+ 'extends': 'default',
799
+ 'createOrder': {
800
+ 'marginMode': True,
801
+ 'triggerPrice': True,
802
+ 'triggerPriceType': {
803
+ 'last': True,
804
+ 'mark': True,
805
+ 'index': False,
806
+ },
807
+ 'triggerDirection': True, # todo: implementation broken
808
+ 'stopLossPrice': True,
809
+ 'takeProfitPrice': True,
810
+ 'attachedStopLossTakeProfit': {
811
+ 'triggerPriceType': {
812
+ 'last': True,
813
+ 'mark': True,
814
+ 'index': False,
815
+ },
816
+ 'price': False,
817
+ },
818
+ 'timeInForce': {
819
+ 'IOC': True,
820
+ 'FOK': True,
821
+ 'PO': True,
822
+ 'GTD': False,
823
+ },
824
+ 'hedged': False,
825
+ 'trailing': True,
826
+ 'marketBuyRequiresPrice': True,
827
+ 'marketBuyByCost': True,
828
+ # exchange-supported features
829
+ # 'selfTradePrevention': True,
830
+ # 'twap': False,
831
+ # 'iceberg': False,
832
+ # 'oco': False,
833
+ },
834
+ 'fetchMyTrades': {
835
+ 'marginMode': True,
836
+ 'limit': None,
837
+ 'daysBack': None,
838
+ 'untilDays': 99999,
839
+ },
840
+ 'fetchOrder': {
841
+ 'marginMode': False,
842
+ 'trigger': False,
843
+ 'trailing': True,
844
+ },
845
+ 'fetchOpenOrders': {
846
+ 'marginMode': False,
847
+ 'limit': 100,
848
+ 'trigger': True,
849
+ 'trailing': False,
850
+ },
851
+ 'fetchClosedOrders': {
852
+ 'marginMode': True,
853
+ 'limit': 200,
854
+ 'daysBack': None,
855
+ 'daysBackCanceled': None,
856
+ 'untilDays': None,
857
+ 'trigger': False,
858
+ 'trailing': False,
859
+ },
860
+ 'fetchOHLCV': {
861
+ 'limit': 500,
862
+ },
863
+ },
864
+ 'spot': {
865
+ 'extends': 'default',
866
+ },
867
+ 'swap': {
868
+ 'linear': {
869
+ 'extends': 'forDerivatives',
870
+ },
871
+ 'inverse': {
872
+ 'extends': 'forDerivatives',
873
+ },
874
+ },
875
+ 'future': {
876
+ 'linear': None,
877
+ 'inverse': None,
878
+ },
879
+ },
698
880
  })
699
881
 
700
- async def fetch_time(self, params={}):
882
+ async def fetch_time(self, params={}) -> Int:
701
883
  """
702
884
  fetches the current integer timestamp in milliseconds from the exchange server
885
+
886
+ https://developer-pro.bitmart.com/en/spot/#get-system-time
887
+
703
888
  :param dict [params]: extra parameters specific to the exchange API endpoint
704
889
  :returns int: the current integer timestamp in milliseconds from the exchange server
705
890
  """
@@ -714,16 +899,19 @@ class bitmart(Exchange, ImplicitAPI):
714
899
  # }
715
900
  # }
716
901
  #
717
- data = self.safe_value(response, 'data', {})
902
+ data = self.safe_dict(response, 'data', {})
718
903
  return self.safe_integer(data, 'server_time')
719
904
 
720
905
  async def fetch_status(self, params={}):
721
906
  """
722
907
  the latest known information on the availability of the exchange API
908
+
909
+ https://developer-pro.bitmart.com/en/spot/#get-system-service-status
910
+
723
911
  :param dict [params]: extra parameters specific to the exchange API endpoint
724
912
  :returns dict: a `status structure <https://docs.ccxt.com/#/?id=exchange-status-structure>`
725
913
  """
726
- options = self.safe_value(self.options, 'fetchStatus', {})
914
+ options = self.safe_dict(self.options, 'fetchStatus', {})
727
915
  defaultType = self.safe_string(self.options, 'defaultType')
728
916
  type = self.safe_string(options, 'type', defaultType)
729
917
  type = self.safe_string(params, 'type', type)
@@ -754,12 +942,12 @@ class bitmart(Exchange, ImplicitAPI):
754
942
  # }
755
943
  # }
756
944
  #
757
- data = self.safe_value(response, 'data', {})
758
- services = self.safe_value(data, 'service', [])
945
+ data = self.safe_dict(response, 'data', {})
946
+ services = self.safe_list(data, 'service', [])
759
947
  servicesByType = self.index_by(services, 'service_type')
760
948
  if type == 'swap':
761
949
  type = 'contract'
762
- service = self.safe_value(servicesByType, type)
950
+ service = self.safe_string(servicesByType, type)
763
951
  status = None
764
952
  eta = None
765
953
  if service is not None:
@@ -777,7 +965,7 @@ class bitmart(Exchange, ImplicitAPI):
777
965
  'info': response,
778
966
  }
779
967
 
780
- async def fetch_spot_markets(self, params={}):
968
+ async def fetch_spot_markets(self, params={}) -> List[MarketInterface]:
781
969
  response = await self.publicGetSpotV1SymbolsDetails(params)
782
970
  #
783
971
  # {
@@ -805,9 +993,10 @@ class bitmart(Exchange, ImplicitAPI):
805
993
  # }
806
994
  # }
807
995
  #
808
- data = self.safe_value(response, 'data', {})
809
- symbols = self.safe_value(data, 'symbols', [])
996
+ data = self.safe_dict(response, 'data', {})
997
+ symbols = self.safe_list(data, 'symbols', [])
810
998
  result = []
999
+ fees = self.fees['trading']
811
1000
  for i in range(0, len(symbols)):
812
1001
  market = symbols[i]
813
1002
  id = self.safe_string(market, 'symbol')
@@ -821,7 +1010,7 @@ class bitmart(Exchange, ImplicitAPI):
821
1010
  minSellCost = self.safe_string(market, 'min_sell_amount')
822
1011
  minCost = Precise.string_max(minBuyCost, minSellCost)
823
1012
  baseMinSize = self.safe_number(market, 'base_min_size')
824
- result.append({
1013
+ result.append(self.safe_market_structure({
825
1014
  'id': id,
826
1015
  'numericId': numericId,
827
1016
  'symbol': symbol,
@@ -846,6 +1035,8 @@ class bitmart(Exchange, ImplicitAPI):
846
1035
  'expiryDatetime': None,
847
1036
  'strike': None,
848
1037
  'optionType': None,
1038
+ 'maker': fees['maker'],
1039
+ 'taker': fees['taker'],
849
1040
  'precision': {
850
1041
  'amount': baseMinSize,
851
1042
  'price': self.parse_number(self.parse_precision(self.safe_string(market, 'price_max_precision'))),
@@ -870,46 +1061,54 @@ class bitmart(Exchange, ImplicitAPI):
870
1061
  },
871
1062
  'created': None,
872
1063
  'info': market,
873
- })
1064
+ }))
874
1065
  return result
875
1066
 
876
- async def fetch_contract_markets(self, params={}):
1067
+ async def fetch_contract_markets(self, params={}) -> List[MarketInterface]:
877
1068
  response = await self.publicGetContractPublicDetails(params)
878
1069
  #
879
1070
  # {
880
- # "code": 1000,
881
- # "message": "Ok",
882
- # "trace": "9b92a999-9463-4c96-91a4-93ad1cad0d72",
883
- # "data": {
884
- # "symbols": [{
885
- # "symbol": "BTCUSDT",
886
- # "product_type": 1,
887
- # "open_timestamp": 1594080000,
888
- # "expire_timestamp": 0,
889
- # "settle_timestamp": 0,
890
- # "base_currency": "BTC",
891
- # "quote_currency": "USDT",
892
- # "last_price": "23920",
893
- # "volume_24h": "18969368",
894
- # "turnover_24h": "458933659.7858",
895
- # "index_price": "23945.25191635",
896
- # "index_name": "BTCUSDT",
897
- # "contract_size": "0.001",
898
- # "min_leverage": "1",
899
- # "max_leverage": "100",
900
- # "price_precision": "0.1",
901
- # "vol_precision": "1",
902
- # "max_volume": "500000",
903
- # "min_volume": "1"
904
- # },
905
- # ...
906
- # ]
907
- # }
1071
+ # "code": 1000,
1072
+ # "message": "Ok",
1073
+ # "data": {
1074
+ # "symbols": [
1075
+ # {
1076
+ # "symbol": "BTCUSDT",
1077
+ # "product_type": 1,
1078
+ # "open_timestamp": 1645977600000,
1079
+ # "expire_timestamp": 0,
1080
+ # "settle_timestamp": 0,
1081
+ # "base_currency": "BTC",
1082
+ # "quote_currency": "USDT",
1083
+ # "last_price": "63547.4",
1084
+ # "volume_24h": "110938430",
1085
+ # "turnover_24h": "7004836342.6944",
1086
+ # "index_price": "63587.85404255",
1087
+ # "index_name": "BTCUSDT",
1088
+ # "contract_size": "0.001",
1089
+ # "min_leverage": "1",
1090
+ # "max_leverage": "100",
1091
+ # "price_precision": "0.1",
1092
+ # "vol_precision": "1",
1093
+ # "max_volume": "1000000",
1094
+ # "min_volume": "1",
1095
+ # "funding_rate": "0.0000801",
1096
+ # "expected_funding_rate": "-0.0000035",
1097
+ # "open_interest": "278214",
1098
+ # "open_interest_value": "17555316.9355496",
1099
+ # "high_24h": "64109.4",
1100
+ # "low_24h": "61857.6",
1101
+ # "change_24h": "0.0239264900886327",
1102
+ # "funding_time": 1726819200000
1103
+ # },
1104
+ # ]
1105
+ # }
908
1106
  # }
909
1107
  #
910
- data = self.safe_value(response, 'data', {})
911
- symbols = self.safe_value(data, 'symbols', [])
1108
+ data = self.safe_dict(response, 'data', {})
1109
+ symbols = self.safe_list(data, 'symbols', [])
912
1110
  result = []
1111
+ fees = self.fees['trading']
913
1112
  for i in range(0, len(symbols)):
914
1113
  market = symbols[i]
915
1114
  id = self.safe_string(market, 'symbol')
@@ -926,7 +1125,7 @@ class bitmart(Exchange, ImplicitAPI):
926
1125
  expiry = self.safe_integer(market, 'expire_timestamp')
927
1126
  if not isFutures and (expiry == 0):
928
1127
  expiry = None
929
- result.append({
1128
+ result.append(self.safe_market_structure({
930
1129
  'id': id,
931
1130
  'numericId': None,
932
1131
  'symbol': symbol,
@@ -951,6 +1150,8 @@ class bitmart(Exchange, ImplicitAPI):
951
1150
  'expiryDatetime': self.iso8601(expiry),
952
1151
  'strike': None,
953
1152
  'optionType': None,
1153
+ 'maker': fees['maker'],
1154
+ 'taker': fees['taker'],
954
1155
  'precision': {
955
1156
  'amount': self.safe_number(market, 'vol_precision'),
956
1157
  'price': self.safe_number(market, 'price_precision'),
@@ -975,15 +1176,21 @@ class bitmart(Exchange, ImplicitAPI):
975
1176
  },
976
1177
  'created': self.safe_integer(market, 'open_timestamp'),
977
1178
  'info': market,
978
- })
1179
+ }))
979
1180
  return result
980
1181
 
981
1182
  async def fetch_markets(self, params={}) -> List[Market]:
982
1183
  """
983
1184
  retrieves data on all markets for bitmart
1185
+
1186
+ https://developer-pro.bitmart.com/en/spot/#get-trading-pair-details-v1
1187
+ https://developer-pro.bitmart.com/en/futuresv2/#get-contract-details
1188
+
984
1189
  :param dict [params]: extra parameters specific to the exchange API endpoint
985
1190
  :returns dict[]: an array of objects representing market data
986
1191
  """
1192
+ if self.options['adjustForTimeDifference']:
1193
+ await self.load_time_difference()
987
1194
  spot = await self.fetch_spot_markets(params)
988
1195
  contract = await self.fetch_contract_markets(params)
989
1196
  return self.array_concat(spot, contract)
@@ -991,64 +1198,140 @@ class bitmart(Exchange, ImplicitAPI):
991
1198
  async def fetch_currencies(self, params={}) -> Currencies:
992
1199
  """
993
1200
  fetches all available currencies on an exchange
1201
+
1202
+ https://developer-pro.bitmart.com/en/spot/#get-currency-list-v1
1203
+
994
1204
  :param dict [params]: extra parameters specific to the exchange API endpoint
995
1205
  :returns dict: an associative dictionary of currencies
996
1206
  """
997
- response = await self.publicGetSpotV1Currencies(params)
1207
+ response = await self.publicGetAccountV1Currencies(params)
998
1208
  #
999
1209
  # {
1000
- # "message":"OK",
1001
- # "code":1000,
1002
- # "trace":"8c768b3c-025f-413f-bec5-6d6411d46883",
1003
- # "data":{
1004
- # "currencies":[
1005
- # {"currency":"MATIC","name":"Matic Network","withdraw_enabled":true,"deposit_enabled":true},
1006
- # {"currency":"KTN","name":"Kasoutuuka News","withdraw_enabled":true,"deposit_enabled":false},
1007
- # {"currency":"BRT","name":"Berith","withdraw_enabled":true,"deposit_enabled":true},
1210
+ # "message": "OK",
1211
+ # "code": 1000,
1212
+ # "trace": "619294ecef584282b26a3be322b1e01f.66.17403093228242229",
1213
+ # "data": {
1214
+ # "currencies": [
1215
+ # {
1216
+ # "currency": "BTC",
1217
+ # "name": "Bitcoin",
1218
+ # "recharge_minsize": '0.00000001',
1219
+ # "contract_address": null,
1220
+ # "network": "BTC",
1221
+ # "withdraw_enabled": True,
1222
+ # "deposit_enabled": True,
1223
+ # "withdraw_minsize": "0.0003",
1224
+ # "withdraw_minfee": "9.61",
1225
+ # "withdraw_fee_estimate": "9.61",
1226
+ # "withdraw_fee": "0.0001"
1227
+ # }
1008
1228
  # ]
1009
1229
  # }
1010
1230
  # }
1011
1231
  #
1012
- data = self.safe_value(response, 'data', {})
1013
- currencies = self.safe_value(data, 'currencies', [])
1014
- result: dict = {}
1232
+ data = self.safe_dict(response, 'data', {})
1233
+ currencies = self.safe_list(data, 'currencies', [])
1234
+ result = {}
1015
1235
  for i in range(0, len(currencies)):
1016
1236
  currency = currencies[i]
1017
- id = self.safe_string(currency, 'id')
1018
- code = self.safe_currency_code(id)
1019
- name = self.safe_string(currency, 'name')
1020
- withdrawEnabled = self.safe_value(currency, 'withdraw_enabled')
1021
- depositEnabled = self.safe_value(currency, 'deposit_enabled')
1022
- active = withdrawEnabled and depositEnabled
1023
- result[code] = {
1024
- 'id': id,
1025
- 'code': code,
1026
- 'name': name,
1027
- 'info': currency, # the original payload
1028
- 'active': active,
1029
- 'deposit': depositEnabled,
1030
- 'withdraw': withdrawEnabled,
1031
- 'fee': None,
1032
- 'precision': None,
1237
+ fullId = self.safe_string(currency, 'currency')
1238
+ currencyId = fullId
1239
+ networkId = self.safe_string(currency, 'network')
1240
+ isNtf = (fullId.find('NFT') >= 0)
1241
+ if not isNtf:
1242
+ parts = fullId.split('-')
1243
+ currencyId = self.safe_string(parts, 0)
1244
+ second = self.safe_string(parts, 1)
1245
+ if second is not None:
1246
+ networkId = second.upper()
1247
+ currencyCode = self.safe_currency_code(currencyId)
1248
+ entry = self.safe_dict(result, currencyCode)
1249
+ if entry is None:
1250
+ entry = {
1251
+ 'info': currency,
1252
+ 'id': currencyId,
1253
+ 'code': currencyCode,
1254
+ 'precision': None,
1255
+ 'name': self.safe_string(currency, 'name'),
1256
+ 'deposit': None,
1257
+ 'withdraw': None,
1258
+ 'active': None,
1259
+ 'networks': {},
1260
+ 'type': 'other' if isNtf else 'crypto',
1261
+ }
1262
+ networkCode = self.network_id_to_code(networkId)
1263
+ withdraw = self.safe_bool(currency, 'withdraw_enabled')
1264
+ deposit = self.safe_bool(currency, 'deposit_enabled')
1265
+ entry['networks'][networkCode] = {
1266
+ 'info': currency,
1267
+ 'id': networkId,
1268
+ 'code': networkCode,
1269
+ 'withdraw': withdraw,
1270
+ 'deposit': deposit,
1271
+ 'active': withdraw and deposit,
1272
+ 'fee': self.safe_number(currency, 'withdraw_fee'),
1033
1273
  'limits': {
1034
- 'amount': {'min': None, 'max': None},
1035
- 'withdraw': {'min': None, 'max': None},
1274
+ 'withdraw': {
1275
+ 'min': self.safe_number(currency, 'withdraw_minsize'),
1276
+ 'max': None,
1277
+ },
1278
+ 'deposit': {
1279
+ 'min': None,
1280
+ 'max': None,
1281
+ },
1036
1282
  },
1037
1283
  }
1284
+ result[currencyCode] = entry
1285
+ keys = list(result.keys())
1286
+ for i in range(0, len(keys)):
1287
+ key = keys[i]
1288
+ currency = result[key]
1289
+ result[key] = self.safe_currency_structure(currency)
1038
1290
  return result
1039
1291
 
1292
+ def get_currency_id_from_code_and_network(self, currencyCode: Str, networkCode: Str) -> Str:
1293
+ if networkCode is None:
1294
+ networkCode = self.default_network_code(currencyCode) # use default network code if not provided
1295
+ currency = self.currency(currencyCode)
1296
+ id = currency['id']
1297
+ idFromNetwork: Str = None
1298
+ networks = self.safe_dict(currency, 'networks', {})
1299
+ networkInfo: dict = {}
1300
+ if networkCode is None:
1301
+ # network code is not provided and there is no default network code
1302
+ network = self.safe_dict(networks, currencyCode) # trying to find network that has the same code
1303
+ if network is None:
1304
+ # use the first network in the networks list if there is no network code with the same code
1305
+ keys = list(networks.keys())
1306
+ length = len(keys)
1307
+ if length > 0:
1308
+ network = self.safe_value(networks, keys[0])
1309
+ networkInfo = self.safe_dict(network, 'info', {})
1310
+ idFromNetwork = self.safe_string(networkInfo, 'currency') # use currency name from network
1311
+ else:
1312
+ providedOrDefaultNetwork = self.safe_dict(networks, networkCode)
1313
+ if providedOrDefaultNetwork is not None:
1314
+ networkInfo = self.safe_dict(providedOrDefaultNetwork, 'info', {})
1315
+ idFromNetwork = self.safe_string(networkInfo, 'currency') # use currency name from network
1316
+ else:
1317
+ id += '-' + self.network_code_to_id(networkCode, currencyCode) # use concatenated currency id and network code if network is not found
1318
+ return idFromNetwork if (idFromNetwork is not None) else id
1319
+
1040
1320
  async def fetch_transaction_fee(self, code: str, params={}):
1041
1321
  """
1042
- * @deprecated
1322
+ @deprecated
1043
1323
  please use fetchDepositWithdrawFee instead
1044
1324
  :param str code: unified currency code
1045
1325
  :param dict [params]: extra parameters specific to the exchange API endpoint
1326
+ :param str [params.network]: the network code of the currency
1046
1327
  :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
1047
1328
  """
1048
1329
  await self.load_markets()
1049
1330
  currency = self.currency(code)
1331
+ network: Str = None
1332
+ network, params = self.handle_network_code_and_params(params)
1050
1333
  request: dict = {
1051
- 'currency': currency['id'],
1334
+ 'currency': self.get_currency_id_from_code_and_network(currency['code'], network),
1052
1335
  }
1053
1336
  response = await self.privateGetAccountV1WithdrawCharge(self.extend(request, params))
1054
1337
  #
@@ -1098,14 +1381,19 @@ class bitmart(Exchange, ImplicitAPI):
1098
1381
  async def fetch_deposit_withdraw_fee(self, code: str, params={}):
1099
1382
  """
1100
1383
  fetch the fee for deposits and withdrawals
1384
+
1385
+ https://developer-pro.bitmart.com/en/spot/#withdraw-quota-keyed
1386
+
1101
1387
  :param str code: unified currency code
1102
1388
  :param dict [params]: extra parameters specific to the exchange API endpoint
1389
+ :param str [params.network]: the network code of the currency
1103
1390
  :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
1104
1391
  """
1105
1392
  await self.load_markets()
1106
- currency = self.currency(code)
1393
+ network: Str = None
1394
+ network, params = self.handle_network_code_and_params(params)
1107
1395
  request: dict = {
1108
- 'currency': currency['id'],
1396
+ 'currency': self.get_currency_id_from_code_and_network(code, network),
1109
1397
  }
1110
1398
  response = await self.privateGetAccountV1WithdrawCharge(self.extend(request, params))
1111
1399
  #
@@ -1178,25 +1466,42 @@ class bitmart(Exchange, ImplicitAPI):
1178
1466
  #
1179
1467
  # swap
1180
1468
  #
1181
- # {
1182
- # "contract_symbol":"DOGEUSDT",
1183
- # "last_price":"0.130340",
1184
- # "index_price":"0.13048245",
1185
- # "last_funding_rate":"0.00002287",
1186
- # "price_change_percent_24h":"-2.074",
1187
- # "volume_24h":"113705028.59482228",
1188
- # "url":"https://futures.bitmart.com/en?symbol=DOGEUSDT",
1189
- # "high_price":"0.134520",
1190
- # "low_price":"0.128570",
1191
- # "legal_coin_price":"0.1302699"
1192
- # }
1469
+ # {
1470
+ # "symbol": "BTCUSDT",
1471
+ # "product_type": 1,
1472
+ # "open_timestamp": 1645977600000,
1473
+ # "expire_timestamp": 0,
1474
+ # "settle_timestamp": 0,
1475
+ # "base_currency": "BTC",
1476
+ # "quote_currency": "USDT",
1477
+ # "last_price": "63547.4",
1478
+ # "volume_24h": "110938430",
1479
+ # "turnover_24h": "7004836342.6944",
1480
+ # "index_price": "63587.85404255",
1481
+ # "index_name": "BTCUSDT",
1482
+ # "contract_size": "0.001",
1483
+ # "min_leverage": "1",
1484
+ # "max_leverage": "100",
1485
+ # "price_precision": "0.1",
1486
+ # "vol_precision": "1",
1487
+ # "max_volume": "1000000",
1488
+ # "min_volume": "1",
1489
+ # "funding_rate": "0.0000801",
1490
+ # "expected_funding_rate": "-0.0000035",
1491
+ # "open_interest": "278214",
1492
+ # "open_interest_value": "17555316.9355496",
1493
+ # "high_24h": "64109.4",
1494
+ # "low_24h": "61857.6",
1495
+ # "change_24h": "0.0239264900886327",
1496
+ # "funding_time": 1726819200000
1497
+ # }
1193
1498
  #
1194
1499
  result = self.safe_list(ticker, 'result', [])
1195
1500
  average = self.safe_string_2(ticker, 'avg_price', 'index_price')
1196
1501
  marketId = self.safe_string_2(ticker, 'symbol', 'contract_symbol')
1197
1502
  timestamp = self.safe_integer_2(ticker, 'timestamp', 'ts')
1198
1503
  last = self.safe_string_2(ticker, 'last_price', 'last')
1199
- percentage = self.safe_string(ticker, 'price_change_percent_24h')
1504
+ percentage = self.safe_string_2(ticker, 'price_change_percent_24h', 'change_24h')
1200
1505
  change = self.safe_string(ticker, 'fluctuation')
1201
1506
  high = self.safe_string_2(ticker, 'high_24h', 'high_price')
1202
1507
  low = self.safe_string_2(ticker, 'low_24h', 'low_price')
@@ -1205,8 +1510,8 @@ class bitmart(Exchange, ImplicitAPI):
1205
1510
  ask = self.safe_string_2(ticker, 'best_ask', 'ask_px')
1206
1511
  askVolume = self.safe_string_2(ticker, 'best_ask_size', 'ask_sz')
1207
1512
  open = self.safe_string(ticker, 'open_24h')
1208
- baseVolume = self.safe_string_2(ticker, 'base_volume_24h', 'v_24h')
1209
- quoteVolume = self.safe_string_lower_2(ticker, 'quote_volume_24h', 'qv_24h')
1513
+ baseVolume = self.safe_string_n(ticker, ['base_volume_24h', 'v_24h', 'volume_24h'])
1514
+ quoteVolume = self.safe_string_lower_n(ticker, ['quote_volume_24h', 'qv_24h', 'turnover_24h'])
1210
1515
  listMarketId = self.safe_string(result, 0)
1211
1516
  if listMarketId is not None:
1212
1517
  marketId = listMarketId
@@ -1253,18 +1558,22 @@ class bitmart(Exchange, ImplicitAPI):
1253
1558
  'close': last,
1254
1559
  'last': last,
1255
1560
  'previousClose': None,
1256
- 'change': change,
1561
+ 'change': None,
1257
1562
  'percentage': percentage,
1258
1563
  'average': average,
1259
1564
  'baseVolume': baseVolume,
1260
1565
  'quoteVolume': quoteVolume,
1566
+ 'indexPrice': self.safe_string(ticker, 'index_price'),
1261
1567
  'info': ticker,
1262
1568
  }, market)
1263
1569
 
1264
1570
  async def fetch_ticker(self, symbol: str, params={}) -> Ticker:
1265
1571
  """
1266
1572
  fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1267
- :see: https://developer-pro.bitmart.com/en/spot/#get-ticker-of-a-trading-pair-v3
1573
+
1574
+ https://developer-pro.bitmart.com/en/spot/#get-ticker-of-a-trading-pair-v3
1575
+ https://developer-pro.bitmart.com/en/futuresv2/#get-contract-details
1576
+
1268
1577
  :param str symbol: unified symbol of the market to fetch the ticker for
1269
1578
  :param dict [params]: extra parameters specific to the exchange API endpoint
1270
1579
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -1274,30 +1583,46 @@ class bitmart(Exchange, ImplicitAPI):
1274
1583
  request: dict = {}
1275
1584
  response = None
1276
1585
  if market['swap']:
1277
- request['contract_symbol'] = market['id']
1278
- response = await self.publicGetContractV1Tickers(self.extend(request, params))
1586
+ request['symbol'] = market['id']
1587
+ response = await self.publicGetContractPublicDetails(self.extend(request, params))
1279
1588
  #
1280
- # {
1281
- # "message":"OK",
1282
- # "code":1000,
1283
- # "trace":"4a0ebceb-d3f7-45a3-8feb-f61e230e24cd",
1284
- # "data":{
1285
- # "tickers":[
1286
- # {
1287
- # "contract_symbol":"DOGEUSDT",
1288
- # "last_price":"0.130180",
1289
- # "index_price":"0.13028635",
1290
- # "last_funding_rate":"0.00002025",
1291
- # "price_change_percent_24h":"-2.326",
1292
- # "volume_24h":"116789313.01797258",
1293
- # "url":"https://futures.bitmart.com/en?symbol=DOGEUSDT",
1294
- # "high_price":"0.134520",
1295
- # "low_price":"0.128570",
1296
- # "legal_coin_price":"0.13017401"
1297
- # }
1298
- # ]
1299
- # }
1300
- # }
1589
+ # {
1590
+ # "code": 1000,
1591
+ # "message": "Ok",
1592
+ # "data": {
1593
+ # "symbols": [
1594
+ # {
1595
+ # "symbol": "BTCUSDT",
1596
+ # "product_type": 1,
1597
+ # "open_timestamp": 1645977600000,
1598
+ # "expire_timestamp": 0,
1599
+ # "settle_timestamp": 0,
1600
+ # "base_currency": "BTC",
1601
+ # "quote_currency": "USDT",
1602
+ # "last_price": "63547.4",
1603
+ # "volume_24h": "110938430",
1604
+ # "turnover_24h": "7004836342.6944",
1605
+ # "index_price": "63587.85404255",
1606
+ # "index_name": "BTCUSDT",
1607
+ # "contract_size": "0.001",
1608
+ # "min_leverage": "1",
1609
+ # "max_leverage": "100",
1610
+ # "price_precision": "0.1",
1611
+ # "vol_precision": "1",
1612
+ # "max_volume": "1000000",
1613
+ # "min_volume": "1",
1614
+ # "funding_rate": "0.0000801",
1615
+ # "expected_funding_rate": "-0.0000035",
1616
+ # "open_interest": "278214",
1617
+ # "open_interest_value": "17555316.9355496",
1618
+ # "high_24h": "64109.4",
1619
+ # "low_24h": "61857.6",
1620
+ # "change_24h": "0.0239264900886327",
1621
+ # "funding_time": 1726819200000
1622
+ # },
1623
+ # ]
1624
+ # }
1625
+ # }
1301
1626
  #
1302
1627
  elif market['spot']:
1303
1628
  request['symbol'] = market['id']
@@ -1327,22 +1652,23 @@ class bitmart(Exchange, ImplicitAPI):
1327
1652
  else:
1328
1653
  raise NotSupported(self.id + ' fetchTicker() does not support ' + market['type'] + ' markets, only spot and swap markets are accepted')
1329
1654
  # fails in naming for contract tickers 'contract_symbol'
1330
- tickersById = None
1331
1655
  tickers = []
1332
1656
  ticker: dict = {}
1333
1657
  if market['spot']:
1334
1658
  ticker = self.safe_dict(response, 'data', {})
1335
1659
  else:
1336
1660
  data = self.safe_dict(response, 'data', {})
1337
- tickers = self.safe_list(data, 'tickers', [])
1338
- tickersById = self.index_by(tickers, 'contract_symbol')
1339
- ticker = self.safe_dict(tickersById, market['id'])
1661
+ tickers = self.safe_list(data, 'symbols', [])
1662
+ ticker = self.safe_dict(tickers, 0, {})
1340
1663
  return self.parse_ticker(ticker, market)
1341
1664
 
1342
1665
  async def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
1343
1666
  """
1344
1667
  fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1345
- :see: https://developer-pro.bitmart.com/en/spot/#get-ticker-of-all-pairs-v3
1668
+
1669
+ https://developer-pro.bitmart.com/en/spot/#get-ticker-of-all-pairs-v3
1670
+ https://developer-pro.bitmart.com/en/futuresv2/#get-contract-details
1671
+
1346
1672
  :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1347
1673
  :param dict [params]: extra parameters specific to the exchange API endpoint
1348
1674
  :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -1352,7 +1678,7 @@ class bitmart(Exchange, ImplicitAPI):
1352
1678
  type = None
1353
1679
  market = None
1354
1680
  if symbols is not None:
1355
- symbol = self.safe_value(symbols, 0)
1681
+ symbol = self.safe_string(symbols, 0)
1356
1682
  market = self.market(symbol)
1357
1683
  type, params = self.handle_market_type_and_params('fetchTickers', market, params)
1358
1684
  response = None
@@ -1383,25 +1709,41 @@ class bitmart(Exchange, ImplicitAPI):
1383
1709
  # }
1384
1710
  #
1385
1711
  elif type == 'swap':
1386
- response = await self.publicGetContractV1Tickers(params)
1712
+ response = await self.publicGetContractPublicDetails(params)
1387
1713
  #
1388
1714
  # {
1389
- # "message": "OK",
1390
1715
  # "code": 1000,
1391
- # "trace": "c1dec681c24ea5d.105.171712565",
1716
+ # "message": "Ok",
1392
1717
  # "data": {
1393
- # "tickers": [
1718
+ # "symbols": [
1394
1719
  # {
1395
- # "contract_symbol": "SNTUSDT",
1396
- # "last_price": "0.0366600",
1397
- # "index_price": "0.03587373",
1398
- # "last_funding_rate": "0.00005000",
1399
- # "price_change_percent_24h": "-2.629",
1400
- # "volume_24h": "10102540.19909109848",
1401
- # "url": "https://futures.bitmart.com/en?symbol=SNTUSDT",
1402
- # "high_price": "0.0405600",
1403
- # "low_price": "0.0355000",
1404
- # "legal_coin_price": "0.03666697"
1720
+ # "symbol": "BTCUSDT",
1721
+ # "product_type": 1,
1722
+ # "open_timestamp": 1645977600000,
1723
+ # "expire_timestamp": 0,
1724
+ # "settle_timestamp": 0,
1725
+ # "base_currency": "BTC",
1726
+ # "quote_currency": "USDT",
1727
+ # "last_price": "63547.4",
1728
+ # "volume_24h": "110938430",
1729
+ # "turnover_24h": "7004836342.6944",
1730
+ # "index_price": "63587.85404255",
1731
+ # "index_name": "BTCUSDT",
1732
+ # "contract_size": "0.001",
1733
+ # "min_leverage": "1",
1734
+ # "max_leverage": "100",
1735
+ # "price_precision": "0.1",
1736
+ # "vol_precision": "1",
1737
+ # "max_volume": "1000000",
1738
+ # "min_volume": "1",
1739
+ # "funding_rate": "0.0000801",
1740
+ # "expected_funding_rate": "-0.0000035",
1741
+ # "open_interest": "278214",
1742
+ # "open_interest_value": "17555316.9355496",
1743
+ # "high_24h": "64109.4",
1744
+ # "low_24h": "61857.6",
1745
+ # "change_24h": "0.0239264900886327",
1746
+ # "funding_time": 1726819200000
1405
1747
  # },
1406
1748
  # ]
1407
1749
  # }
@@ -1414,7 +1756,7 @@ class bitmart(Exchange, ImplicitAPI):
1414
1756
  tickers = self.safe_list(response, 'data', [])
1415
1757
  else:
1416
1758
  data = self.safe_dict(response, 'data', {})
1417
- tickers = self.safe_list(data, 'tickers', [])
1759
+ tickers = self.safe_list(data, 'symbols', [])
1418
1760
  result: dict = {}
1419
1761
  for i in range(0, len(tickers)):
1420
1762
  ticker: dict = {}
@@ -1429,8 +1771,10 @@ class bitmart(Exchange, ImplicitAPI):
1429
1771
  async def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
1430
1772
  """
1431
1773
  fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1432
- :see: https://developer-pro.bitmart.com/en/spot/#get-depth-v3
1433
- :see: https://developer-pro.bitmart.com/en/futures/#get-market-depth
1774
+
1775
+ https://developer-pro.bitmart.com/en/spot/#get-depth-v3
1776
+ https://developer-pro.bitmart.com/en/futuresv2/#get-market-depth
1777
+
1434
1778
  :param str symbol: unified symbol of the market to fetch the order book for
1435
1779
  :param int [limit]: the maximum amount of order book entries to return
1436
1780
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1495,7 +1839,7 @@ class bitmart(Exchange, ImplicitAPI):
1495
1839
  # "trace": "4cad855074664097ac6ba5258c47305d.72.16952643834721135"
1496
1840
  # }
1497
1841
  #
1498
- data = self.safe_value(response, 'data', {})
1842
+ data = self.safe_dict(response, 'data', {})
1499
1843
  timestamp = self.safe_integer_2(data, 'ts', 'timestamp')
1500
1844
  return self.parse_order_book(data, market['symbol'], timestamp)
1501
1845
 
@@ -1604,7 +1948,9 @@ class bitmart(Exchange, ImplicitAPI):
1604
1948
  async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1605
1949
  """
1606
1950
  get a list of the most recent trades for a particular symbol
1607
- :see: https://developer-pro.bitmart.com/en/spot/#get-recent-trades-v3
1951
+
1952
+ https://developer-pro.bitmart.com/en/spot/#get-recent-trades-v3
1953
+
1608
1954
  :param str symbol: unified symbol of the market to fetch trades for
1609
1955
  :param int [since]: timestamp in ms of the earliest trade to fetch
1610
1956
  :param int [limit]: the maximum number of trades to fetch
@@ -1705,8 +2051,10 @@ class bitmart(Exchange, ImplicitAPI):
1705
2051
  async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1706
2052
  """
1707
2053
  fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1708
- :see: https://developer-pro.bitmart.com/en/spot/#get-history-k-line-v3
1709
- :see: https://developer-pro.bitmart.com/en/futures/#get-k-line
2054
+
2055
+ https://developer-pro.bitmart.com/en/spot/#get-history-k-line-v3
2056
+ https://developer-pro.bitmart.com/en/futuresv2/#get-k-line
2057
+
1710
2058
  :param str symbol: unified symbol of the market to fetch OHLCV data for
1711
2059
  :param str timeframe: the length of time each candle represents
1712
2060
  :param int [since]: timestamp in ms of the earliest candle to fetch
@@ -1738,7 +2086,7 @@ class bitmart(Exchange, ImplicitAPI):
1738
2086
  if since is not None:
1739
2087
  request['after'] = self.parse_to_int((since / 1000)) - 1
1740
2088
  else:
1741
- maxLimit = 1200
2089
+ maxLimit = 500
1742
2090
  if limit is None:
1743
2091
  limit = maxLimit
1744
2092
  limit = min(maxLimit, limit)
@@ -1755,7 +2103,12 @@ class bitmart(Exchange, ImplicitAPI):
1755
2103
  request, params = self.handle_until_option('end_time', request, params, 0.001)
1756
2104
  response = None
1757
2105
  if market['swap']:
1758
- response = await self.publicGetContractPublicKline(self.extend(request, params))
2106
+ price = self.safe_string(params, 'price')
2107
+ if price == 'mark':
2108
+ params = self.omit(params, 'price')
2109
+ response = await self.publicGetContractPublicMarkpriceKline(self.extend(request, params))
2110
+ else:
2111
+ response = await self.publicGetContractPublicKline(self.extend(request, params))
1759
2112
  else:
1760
2113
  response = await self.publicGetSpotQuotationV3Klines(self.extend(request, params))
1761
2114
  #
@@ -1796,8 +2149,10 @@ class bitmart(Exchange, ImplicitAPI):
1796
2149
 
1797
2150
  async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1798
2151
  """
1799
- :see: https://developer-pro.bitmart.com/en/spot/#account-trade-list-v4-signed
1800
- :see: https://developer-pro.bitmart.com/en/futures/#get-order-trade-keyed
2152
+
2153
+ https://developer-pro.bitmart.com/en/spot/#account-trade-list-v4-signed
2154
+ https://developer-pro.bitmart.com/en/futuresv2/#get-order-trade-keyed
2155
+
1801
2156
  fetch all trades made by the user
1802
2157
  :param str symbol: unified market symbol
1803
2158
  :param int [since]: the earliest time in ms to fetch trades for
@@ -1805,6 +2160,7 @@ class bitmart(Exchange, ImplicitAPI):
1805
2160
  :param dict [params]: extra parameters specific to the exchange API endpoint
1806
2161
  :param int [params.until]: the latest time in ms to fetch trades for
1807
2162
  :param boolean [params.marginMode]: *spot* whether to fetch trades for margin orders or spot orders, defaults to spot orders(only isolated margin orders are supported)
2163
+ :param str [params.stpMode]: self-trade prevention only for spot, defaults to none, ['none', 'cancel_maker', 'cancel_taker', 'cancel_both']
1808
2164
  :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1809
2165
  """
1810
2166
  await self.load_markets()
@@ -1823,11 +2179,12 @@ class bitmart(Exchange, ImplicitAPI):
1823
2179
  marginMode, params = self.handle_margin_mode_and_params('fetchMyTrades', params)
1824
2180
  if marginMode == 'isolated':
1825
2181
  request['orderMode'] = 'iso_margin'
1826
- options = self.safe_value(self.options, 'fetchMyTrades', {})
1827
- defaultLimit = self.safe_integer(options, 'limit', 200)
2182
+ options = self.safe_dict(self.options, 'fetchMyTrades', {})
2183
+ maxLimit = 200
2184
+ defaultLimit = self.safe_integer(options, 'limit', maxLimit)
1828
2185
  if limit is None:
1829
2186
  limit = defaultLimit
1830
- request['limit'] = limit
2187
+ request['limit'] = min(limit, maxLimit)
1831
2188
  if since is not None:
1832
2189
  request['startTime'] = since
1833
2190
  if until is not None:
@@ -1899,13 +2256,16 @@ class bitmart(Exchange, ImplicitAPI):
1899
2256
 
1900
2257
  async def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1901
2258
  """
1902
- :see: https://developer-pro.bitmart.com/en/spot/#order-trade-list-v4-signed
2259
+
2260
+ https://developer-pro.bitmart.com/en/spot/#order-trade-list-v4-signed
2261
+
1903
2262
  fetch all the trades made from a single order
1904
2263
  :param str id: order id
1905
2264
  :param str symbol: unified market symbol
1906
2265
  :param int [since]: the earliest time in ms to fetch trades for
1907
2266
  :param int [limit]: the maximum number of trades to retrieve
1908
2267
  :param dict [params]: extra parameters specific to the exchange API endpoint
2268
+ :param str [params.stpMode]: self-trade prevention only for spot, defaults to none, ['none', 'cancel_maker', 'cancel_taker', 'cancel_both']
1909
2269
  :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1910
2270
  """
1911
2271
  await self.load_markets()
@@ -1917,22 +2277,22 @@ class bitmart(Exchange, ImplicitAPI):
1917
2277
  return self.parse_trades(data, None, since, limit)
1918
2278
 
1919
2279
  def custom_parse_balance(self, response, marketType) -> Balances:
1920
- data = self.safe_value(response, 'data', {})
2280
+ data = self.safe_dict(response, 'data', {})
1921
2281
  wallet = None
1922
2282
  if marketType == 'swap':
1923
- wallet = self.safe_value(response, 'data', [])
2283
+ wallet = self.safe_list(response, 'data', [])
1924
2284
  elif marketType == 'margin':
1925
- wallet = self.safe_value(data, 'symbols', [])
2285
+ wallet = self.safe_list(data, 'symbols', [])
1926
2286
  else:
1927
- wallet = self.safe_value(data, 'wallet', [])
2287
+ wallet = self.safe_list(data, 'wallet', [])
1928
2288
  result = {'info': response}
1929
2289
  if marketType == 'margin':
1930
2290
  for i in range(0, len(wallet)):
1931
2291
  entry = wallet[i]
1932
2292
  marketId = self.safe_string(entry, 'symbol')
1933
2293
  symbol = self.safe_symbol(marketId, None, '_')
1934
- base = self.safe_value(entry, 'base', {})
1935
- quote = self.safe_value(entry, 'quote', {})
2294
+ base = self.safe_dict(entry, 'base', {})
2295
+ quote = self.safe_dict(entry, 'quote', {})
1936
2296
  baseCode = self.safe_currency_code(self.safe_string(base, 'currency'))
1937
2297
  quoteCode = self.safe_currency_code(self.safe_string(quote, 'currency'))
1938
2298
  subResult: dict = {}
@@ -1948,7 +2308,7 @@ class bitmart(Exchange, ImplicitAPI):
1948
2308
  code = self.safe_currency_code(currencyId)
1949
2309
  account = self.account()
1950
2310
  account['free'] = self.safe_string_2(balance, 'available', 'available_balance')
1951
- account['used'] = self.safe_string_2(balance, 'frozen', 'frozen_balance')
2311
+ account['used'] = self.safe_string_n(balance, ['unAvailable', 'frozen', 'frozen_balance'])
1952
2312
  result[code] = account
1953
2313
  return self.safe_balance(result)
1954
2314
 
@@ -1965,10 +2325,12 @@ class bitmart(Exchange, ImplicitAPI):
1965
2325
  async def fetch_balance(self, params={}) -> Balances:
1966
2326
  """
1967
2327
  query for balance and get the amount of funds available for trading or funds locked in orders
1968
- :see: https://developer-pro.bitmart.com/en/spot/#get-spot-wallet-balance
1969
- :see: https://developer-pro.bitmart.com/en/futures/#get-contract-assets-detail
1970
- :see: https://developer-pro.bitmart.com/en/spot/#get-account-balance
1971
- :see: https://developer-pro.bitmart.com/en/spot/#get-margin-account-details-isolated
2328
+
2329
+ https://developer-pro.bitmart.com/en/spot/#get-spot-wallet-balance-keyed
2330
+ https://developer-pro.bitmart.com/en/futuresv2/#get-contract-assets-keyed
2331
+ https://developer-pro.bitmart.com/en/spot/#get-account-balance-keyed
2332
+ https://developer-pro.bitmart.com/en/spot/#get-margin-account-details-isolated-keyed
2333
+
1972
2334
  :param dict [params]: extra parameters specific to the exchange API endpoint
1973
2335
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1974
2336
  """
@@ -2015,8 +2377,8 @@ class bitmart(Exchange, ImplicitAPI):
2015
2377
  # "trace":"5c3b7fc7-93b2-49ef-bb59-7fdc56915b59",
2016
2378
  # "data":{
2017
2379
  # "wallet":[
2018
- # {"currency":"BTC","name":"Bitcoin","available":"0.00000062","frozen":"0.00000000"},
2019
- # {"currency":"ETH","name":"Ethereum","available":"0.00002277","frozen":"0.00000000"}
2380
+ # {"currency":"BTC","name":"Bitcoin","available":"0.00000062","frozen":"0.00000000","available_usd_valuation":null},
2381
+ # {"currency":"ETH","name":"Ethereum","available":"0.00002277","frozen":"0.00000000","available_usd_valuation":null}
2020
2382
  # ]
2021
2383
  # }
2022
2384
  # }
@@ -2109,6 +2471,9 @@ class bitmart(Exchange, ImplicitAPI):
2109
2471
  async def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
2110
2472
  """
2111
2473
  fetch the trading fees for a market
2474
+
2475
+ https://developer-pro.bitmart.com/en/spot/#get-actual-trade-fee-rate-keyed
2476
+
2112
2477
  :param str symbol: unified market symbol
2113
2478
  :param dict [params]: extra parameters specific to the exchange API endpoint
2114
2479
  :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
@@ -2133,12 +2498,12 @@ class bitmart(Exchange, ImplicitAPI):
2133
2498
  # }
2134
2499
  # }
2135
2500
  #
2136
- data = self.safe_value(response, 'data')
2501
+ data = self.safe_dict(response, 'data', {})
2137
2502
  return self.parse_trading_fee(data)
2138
2503
 
2139
2504
  def parse_order(self, order: dict, market: Market = None) -> Order:
2140
2505
  #
2141
- # createOrder
2506
+ # createOrder, editOrder
2142
2507
  #
2143
2508
  # {
2144
2509
  # "order_id": 2707217580
@@ -2238,7 +2603,7 @@ class bitmart(Exchange, ImplicitAPI):
2238
2603
  trailingActivationPrice = self.safe_number(order, 'activation_price')
2239
2604
  return self.safe_order({
2240
2605
  'id': id,
2241
- 'clientOrderId': self.safe_string(order, 'client_order_id'),
2606
+ 'clientOrderId': self.safe_string_2(order, 'client_order_id', 'clientOrderId'),
2242
2607
  'info': order,
2243
2608
  'timestamp': timestamp,
2244
2609
  'datetime': self.iso8601(timestamp),
@@ -2249,7 +2614,6 @@ class bitmart(Exchange, ImplicitAPI):
2249
2614
  'postOnly': postOnly,
2250
2615
  'side': self.parse_order_side(self.safe_string(order, 'side')),
2251
2616
  'price': self.omit_zero(priceString),
2252
- 'stopPrice': trailingActivationPrice,
2253
2617
  'triggerPrice': trailingActivationPrice,
2254
2618
  'amount': self.omit_zero(self.safe_string(order, 'size')),
2255
2619
  'cost': self.safe_string_2(order, 'filled_notional', 'filledNotional'),
@@ -2292,13 +2656,15 @@ class bitmart(Exchange, ImplicitAPI):
2292
2656
  '4': 'closed', # Completed
2293
2657
  },
2294
2658
  }
2295
- statuses = self.safe_value(statusesByType, type, {})
2659
+ statuses = self.safe_dict(statusesByType, type, {})
2296
2660
  return self.safe_string(statuses, status, status)
2297
2661
 
2298
2662
  async def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
2299
2663
  """
2300
2664
  create a market buy order by providing the symbol and cost
2301
- :see: https://developer-pro.bitmart.com/en/spot/#new-order-v2-signed
2665
+
2666
+ https://developer-pro.bitmart.com/en/spot/#new-order-v2-signed
2667
+
2302
2668
  :param str symbol: unified symbol of the market to create an order in
2303
2669
  :param float cost: how much you want to trade in units of the quote currency
2304
2670
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2314,15 +2680,19 @@ class bitmart(Exchange, ImplicitAPI):
2314
2680
  async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
2315
2681
  """
2316
2682
  create a trade order
2317
- :see: https://developer-pro.bitmart.com/en/spot/#new-order-v2-signed
2318
- :see: https://developer-pro.bitmart.com/en/spot/#place-margin-order
2319
- :see: https://developer-pro.bitmart.com/en/futures/#submit-order-signed
2320
- :see: https://developer-pro.bitmart.com/en/futures/#submit-plan-order-signed
2683
+
2684
+ https://developer-pro.bitmart.com/en/spot/#new-order-v2-signed
2685
+ https://developer-pro.bitmart.com/en/spot/#new-margin-order-v1-signed
2686
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-order-signed
2687
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-plan-order-signed
2688
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-tp-sl-order-signed
2689
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-trail-order-signed
2690
+
2321
2691
  :param str symbol: unified symbol of the market to create an order in
2322
2692
  :param str type: 'market', 'limit' or 'trailing' for swap markets only
2323
2693
  :param str side: 'buy' or 'sell'
2324
2694
  :param float amount: how much of currency you want to trade in units of base currency
2325
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2695
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2326
2696
  :param dict [params]: extra parameters specific to the exchange API endpoint
2327
2697
  :param str [params.marginMode]: 'cross' or 'isolated'
2328
2698
  :param str [params.leverage]: *swap only* leverage level
@@ -2335,6 +2705,10 @@ class bitmart(Exchange, ImplicitAPI):
2335
2705
  :param int [params.activation_price_type]: *swap trailing order only* 1: last price, 2: fair price, default is 1
2336
2706
  :param str [params.trailingPercent]: *swap only* the percent to trail away from the current market price, min 0.1 max 5
2337
2707
  :param str [params.trailingTriggerPrice]: *swap only* the price to trigger a trailing order, default uses the price argument
2708
+ :param str [params.stopLossPrice]: *swap only* the price to trigger a stop-loss order
2709
+ :param str [params.takeProfitPrice]: *swap only* the price to trigger a take-profit order
2710
+ :param int [params.plan_category]: *swap tp/sl only* 1: tp/sl, 2: position tp/sl, default is 1
2711
+ :param str [params.stpMode]: self-trade prevention only for spot, defaults to none, ['none', 'cancel_maker', 'cancel_taker', 'cancel_both']
2338
2712
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2339
2713
  """
2340
2714
  await self.load_markets()
@@ -2342,6 +2716,10 @@ class bitmart(Exchange, ImplicitAPI):
2342
2716
  result = self.handle_margin_mode_and_params('createOrder', params)
2343
2717
  marginMode = self.safe_string(result, 0)
2344
2718
  triggerPrice = self.safe_string_n(params, ['triggerPrice', 'stopPrice', 'trigger_price'])
2719
+ stopLossPrice = self.safe_string(params, 'stopLossPrice')
2720
+ takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
2721
+ isStopLoss = stopLossPrice is not None
2722
+ isTakeProfit = takeProfitPrice is not None
2345
2723
  isTriggerOrder = triggerPrice is not None
2346
2724
  response = None
2347
2725
  if market['spot']:
@@ -2352,8 +2730,14 @@ class bitmart(Exchange, ImplicitAPI):
2352
2730
  response = await self.privatePostSpotV2SubmitOrder(spotRequest)
2353
2731
  else:
2354
2732
  swapRequest = self.create_swap_order_request(symbol, type, side, amount, price, params)
2355
- if isTriggerOrder:
2733
+ activationPrice = self.safe_string(swapRequest, 'activation_price')
2734
+ if activationPrice is not None:
2735
+ # if type is trailing
2736
+ response = await self.privatePostContractPrivateSubmitTrailOrder(swapRequest)
2737
+ elif isTriggerOrder:
2356
2738
  response = await self.privatePostContractPrivateSubmitPlanOrder(swapRequest)
2739
+ elif isStopLoss or isTakeProfit:
2740
+ response = await self.privatePostContractPrivateSubmitTpSlOrder(swapRequest)
2357
2741
  else:
2358
2742
  response = await self.privatePostContractPrivateSubmitOrder(swapRequest)
2359
2743
  #
@@ -2371,7 +2755,7 @@ class bitmart(Exchange, ImplicitAPI):
2371
2755
  # swap
2372
2756
  # {"code":1000,"message":"Ok","data":{"order_id":231116359426639,"price":"market price"},"trace":"7f9c94e10f9d4513bc08a7bfc2a5559a.62.16996369620521911"}
2373
2757
  #
2374
- data = self.safe_value(response, 'data', {})
2758
+ data = self.safe_dict(response, 'data', {})
2375
2759
  order = self.parse_order(data, market)
2376
2760
  order['type'] = type
2377
2761
  order['side'] = side
@@ -2382,9 +2766,12 @@ class bitmart(Exchange, ImplicitAPI):
2382
2766
  async def create_orders(self, orders: List[OrderRequest], params={}):
2383
2767
  """
2384
2768
  create a list of trade orders
2385
- :see: https://developer-pro.bitmart.com/en/spot/#new-batch-order-v4-signed
2769
+
2770
+ https://developer-pro.bitmart.com/en/spot/#new-batch-order-v4-signed
2771
+
2386
2772
  :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
2387
2773
  :param dict [params]: extra parameters specific to the exchange API endpoint
2774
+ :param str [params.stpMode]: self-trade prevention only for spot, defaults to none, ['none', 'cancel_maker', 'cancel_taker', 'cancel_both']
2388
2775
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2389
2776
  """
2390
2777
  await self.load_markets()
@@ -2443,15 +2830,17 @@ class bitmart(Exchange, ImplicitAPI):
2443
2830
 
2444
2831
  def create_swap_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
2445
2832
  """
2446
- * @ignore
2833
+ @ignore
2447
2834
  create a trade order
2448
- :see: https://developer-pro.bitmart.com/en/futures/#submit-order-signed
2449
- :see: https://developer-pro.bitmart.com/en/futures/#submit-plan-order-signed
2835
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-order-signed
2836
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-plan-order-signed
2837
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-tp-sl-order-signed
2838
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-trail-order-signed
2450
2839
  :param str symbol: unified symbol of the market to create an order in
2451
- :param str type: 'market', 'limit' or 'trailing'
2840
+ :param str type: 'market', 'limit', 'trailing', 'stop_loss', or 'take_profit'
2452
2841
  :param str side: 'buy' or 'sell'
2453
2842
  :param float amount: how much of currency you want to trade in units of base currency
2454
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2843
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2455
2844
  :param dict [params]: extra parameters specific to the exchange API endpoint
2456
2845
  :param int [params.leverage]: leverage level
2457
2846
  :param boolean [params.reduceOnly]: *swap only* reduce only
@@ -2463,19 +2852,29 @@ class bitmart(Exchange, ImplicitAPI):
2463
2852
  :param int [params.activation_price_type]: *swap trailing order only* 1: last price, 2: fair price, default is 1
2464
2853
  :param str [params.trailingPercent]: *swap only* the percent to trail away from the current market price, min 0.1 max 5
2465
2854
  :param str [params.trailingTriggerPrice]: *swap only* the price to trigger a trailing order, default uses the price argument
2855
+ :param str [params.stopLossPrice]: *swap only* the price to trigger a stop-loss order
2856
+ :param str [params.takeProfitPrice]: *swap only* the price to trigger a take-profit order
2857
+ :param int [params.plan_category]: *swap tp/sl only* 1: tp/sl, 2: position tp/sl, default is 1
2466
2858
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2467
2859
  """
2468
2860
  market = self.market(symbol)
2861
+ stopLossPrice = self.safe_string(params, 'stopLossPrice')
2862
+ takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
2863
+ isStopLoss = stopLossPrice is not None
2864
+ isTakeProfit = takeProfitPrice is not None
2865
+ if isStopLoss:
2866
+ type = 'stop_loss'
2867
+ elif isTakeProfit:
2868
+ type = 'take_profit'
2469
2869
  request: dict = {
2470
2870
  'symbol': market['id'],
2471
- 'type': type,
2472
2871
  'size': int(self.amount_to_precision(symbol, amount)),
2473
2872
  }
2474
2873
  timeInForce = self.safe_string(params, 'timeInForce')
2475
2874
  mode = self.safe_integer(params, 'mode') # only for swap
2476
2875
  isMarketOrder = type == 'market'
2477
2876
  postOnly = None
2478
- reduceOnly = self.safe_value(params, 'reduceOnly')
2877
+ reduceOnly = self.safe_bool(params, 'reduceOnly')
2479
2878
  isExchangeSpecificPo = (mode == 4)
2480
2879
  postOnly, params = self.handle_post_only(isMarketOrder, isExchangeSpecificPo, params)
2481
2880
  ioc = ((timeInForce == 'IOC') or (mode == 3))
@@ -2496,11 +2895,13 @@ class bitmart(Exchange, ImplicitAPI):
2496
2895
  if isLimitOrder:
2497
2896
  request['price'] = self.price_to_precision(symbol, price)
2498
2897
  elif type == 'trailing' or isTrailingPercentOrder:
2898
+ type = 'trailing'
2499
2899
  request['callback_rate'] = trailingPercent
2500
2900
  request['activation_price'] = self.price_to_precision(symbol, trailingTriggerPrice)
2501
2901
  request['activation_price_type'] = self.safe_integer(params, 'activation_price_type', 1)
2502
2902
  if isTriggerOrder:
2503
- request['executive_price'] = self.price_to_precision(symbol, price)
2903
+ if isLimitOrder or price is not None:
2904
+ request['executive_price'] = self.price_to_precision(symbol, price)
2504
2905
  request['trigger_price'] = self.price_to_precision(symbol, triggerPrice)
2505
2906
  request['price_type'] = self.safe_integer(params, 'price_type', 1)
2506
2907
  if side == 'buy':
@@ -2513,6 +2914,18 @@ class bitmart(Exchange, ImplicitAPI):
2513
2914
  request['price_way'] = 1
2514
2915
  else:
2515
2916
  request['price_way'] = 2
2917
+ marginMode = None
2918
+ marginMode, params = self.handle_margin_mode_and_params('createOrder', params, 'cross')
2919
+ if isStopLoss or isTakeProfit:
2920
+ reduceOnly = True
2921
+ request['price_type'] = self.safe_integer(params, 'price_type', 1)
2922
+ request['executive_price'] = self.price_to_precision(symbol, price)
2923
+ if isStopLoss:
2924
+ request['trigger_price'] = self.price_to_precision(symbol, stopLossPrice)
2925
+ else:
2926
+ request['trigger_price'] = self.price_to_precision(symbol, takeProfitPrice)
2927
+ else:
2928
+ request['open_type'] = marginMode
2516
2929
  if side == 'buy':
2517
2930
  if reduceOnly:
2518
2931
  request['side'] = 2 # buy close short
@@ -2523,29 +2936,31 @@ class bitmart(Exchange, ImplicitAPI):
2523
2936
  request['side'] = 3 # sell close long
2524
2937
  else:
2525
2938
  request['side'] = 4 # sell open short
2526
- marginMode = None
2527
- marginMode, params = self.handle_margin_mode_and_params('createOrder', params, 'cross')
2528
- request['open_type'] = marginMode
2529
2939
  clientOrderId = self.safe_string(params, 'clientOrderId')
2530
2940
  if clientOrderId is not None:
2531
2941
  params = self.omit(params, 'clientOrderId')
2532
2942
  request['client_order_id'] = clientOrderId
2533
- leverage = self.safe_integer(params, 'leverage', 1)
2534
- params = self.omit(params, ['timeInForce', 'postOnly', 'reduceOnly', 'leverage', 'trailingTriggerPrice', 'trailingPercent', 'triggerPrice', 'stopPrice'])
2535
- request['leverage'] = self.number_to_string(leverage)
2943
+ leverage = self.safe_integer(params, 'leverage')
2944
+ params = self.omit(params, ['timeInForce', 'postOnly', 'reduceOnly', 'leverage', 'trailingTriggerPrice', 'trailingPercent', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice'])
2945
+ if leverage is not None:
2946
+ request['leverage'] = self.number_to_string(leverage)
2947
+ elif isTriggerOrder:
2948
+ request['leverage'] = '1' # for plan orders leverage is required, if not available default to 1
2949
+ if type != 'trailing':
2950
+ request['type'] = type
2536
2951
  return self.extend(request, params)
2537
2952
 
2538
2953
  def create_spot_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
2539
2954
  """
2540
- * @ignore
2955
+ @ignore
2541
2956
  create a spot order request
2542
- :see: https://developer-pro.bitmart.com/en/spot/#place-spot-order
2543
- :see: https://developer-pro.bitmart.com/en/spot/#place-margin-order
2957
+ https://developer-pro.bitmart.com/en/spot/#new-order-v2-signed
2958
+ https://developer-pro.bitmart.com/en/spot/#new-margin-order-v1-signed
2544
2959
  :param str symbol: unified symbol of the market to create an order in
2545
2960
  :param str type: 'market' or 'limit'
2546
2961
  :param str side: 'buy' or 'sell'
2547
2962
  :param float amount: how much of currency you want to trade in units of base currency
2548
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2963
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2549
2964
  :param dict [params]: extra parameters specific to the exchange API endpoint
2550
2965
  :param str [params.marginMode]: 'cross' or 'isolated'
2551
2966
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
@@ -2603,15 +3018,19 @@ class bitmart(Exchange, ImplicitAPI):
2603
3018
  async def cancel_order(self, id: str, symbol: Str = None, params={}):
2604
3019
  """
2605
3020
  cancels an open order
2606
- :see: https://developer-pro.bitmart.com/en/futures/#cancel-order-signed
2607
- :see: https://developer-pro.bitmart.com/en/spot/#cancel-order-v3-signed
2608
- :see: https://developer-pro.bitmart.com/en/futures/#cancel-plan-order-signed
2609
- :see: https://developer-pro.bitmart.com/en/futures/#cancel-plan-order-signed
3021
+
3022
+ https://developer-pro.bitmart.com/en/futuresv2/#cancel-order-signed
3023
+ https://developer-pro.bitmart.com/en/spot/#cancel-order-v3-signed
3024
+ https://developer-pro.bitmart.com/en/futuresv2/#cancel-plan-order-signed
3025
+ https://developer-pro.bitmart.com/en/futuresv2/#cancel-order-signed
3026
+ https://developer-pro.bitmart.com/en/futuresv2/#cancel-trail-order-signed
3027
+
2610
3028
  :param str id: order id
2611
3029
  :param str symbol: unified symbol of the market the order was made in
2612
3030
  :param dict [params]: extra parameters specific to the exchange API endpoint
2613
3031
  :param str [params.clientOrderId]: *spot only* the client order id of the order to cancel
2614
- :param boolean [params.stop]: *swap only* whether the order is a stop order
3032
+ :param boolean [params.trigger]: *swap only* whether the order is a trigger order
3033
+ :param boolean [params.trailing]: *swap only* whether the order is a stop order
2615
3034
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2616
3035
  """
2617
3036
  if symbol is None:
@@ -2631,12 +3050,15 @@ class bitmart(Exchange, ImplicitAPI):
2631
3050
  if market['spot']:
2632
3051
  response = await self.privatePostSpotV3CancelOrder(self.extend(request, params))
2633
3052
  else:
2634
- stop = self.safe_value_2(params, 'stop', 'trigger')
3053
+ trigger = self.safe_bool_2(params, 'stop', 'trigger')
3054
+ trailing = self.safe_bool(params, 'trailing')
2635
3055
  params = self.omit(params, ['stop', 'trigger'])
2636
- if not stop:
2637
- response = await self.privatePostContractPrivateCancelOrder(self.extend(request, params))
2638
- else:
3056
+ if trigger:
2639
3057
  response = await self.privatePostContractPrivateCancelPlanOrder(self.extend(request, params))
3058
+ elif trailing:
3059
+ response = await self.privatePostContractPrivateCancelTrailOrder(self.extend(request, params))
3060
+ else:
3061
+ response = await self.privatePostContractPrivateCancelOrder(self.extend(request, params))
2640
3062
  # swap
2641
3063
  # {"code":1000,"message":"Ok","trace":"7f9c94e10f9d4513bc08a7bfc2a5559a.55.16959817848001851"}
2642
3064
  #
@@ -2661,7 +3083,7 @@ class bitmart(Exchange, ImplicitAPI):
2661
3083
  # }
2662
3084
  #
2663
3085
  if market['swap']:
2664
- return response
3086
+ return self.safe_order({'info': response})
2665
3087
  data = self.safe_value(response, 'data')
2666
3088
  if data is True:
2667
3089
  return self.safe_order({'id': id}, market)
@@ -2677,10 +3099,12 @@ class bitmart(Exchange, ImplicitAPI):
2677
3099
  order = self.safe_order({'id': id, 'symbol': market['symbol'], 'info': {}}, market)
2678
3100
  return order
2679
3101
 
2680
- async def cancel_orders(self, ids: List[str], symbol: Str = None, params={}):
3102
+ async def cancel_orders(self, ids: List[str], symbol: Str = None, params={}) -> List[Order]:
2681
3103
  """
2682
3104
  cancel multiple orders
2683
- :see: https://developer-pro.bitmart.com/en/spot/#cancel-batch-order-v4-signed
3105
+
3106
+ https://developer-pro.bitmart.com/en/spot/#cancel-batch-order-v4-signed
3107
+
2684
3108
  :param str[] ids: order ids
2685
3109
  :param str symbol: unified symbol of the market the order was made in
2686
3110
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2734,8 +3158,10 @@ class bitmart(Exchange, ImplicitAPI):
2734
3158
  async def cancel_all_orders(self, symbol: Str = None, params={}):
2735
3159
  """
2736
3160
  cancel all open orders in a market
2737
- :see: https://developer-pro.bitmart.com/en/spot/#cancel-all-orders
2738
- :see: https://developer-pro.bitmart.com/en/futures/#cancel-all-orders-signed
3161
+
3162
+ https://developer-pro.bitmart.com/en/spot/#cancel-all-order-v4-signed
3163
+ https://developer-pro.bitmart.com/en/futuresv2/#cancel-all-orders-signed
3164
+
2739
3165
  :param str symbol: unified market symbol of the market to cancel orders in
2740
3166
  :param dict [params]: extra parameters specific to the exchange API endpoint
2741
3167
  :param str [params.side]: *spot only* 'buy' or 'sell'
@@ -2751,7 +3177,7 @@ class bitmart(Exchange, ImplicitAPI):
2751
3177
  type = None
2752
3178
  type, params = self.handle_market_type_and_params('cancelAllOrders', market, params)
2753
3179
  if type == 'spot':
2754
- response = await self.privatePostSpotV1CancelOrders(self.extend(request, params))
3180
+ response = await self.privatePostSpotV4CancelAll(self.extend(request, params))
2755
3181
  elif type == 'swap':
2756
3182
  if symbol is None:
2757
3183
  raise ArgumentsRequired(self.id + ' cancelAllOrders() requires a symbol argument')
@@ -2774,7 +3200,7 @@ class bitmart(Exchange, ImplicitAPI):
2774
3200
  # "trace": "7f9c94e10f9d4513bc08a7bfc2a5559a.70.16954131323145323"
2775
3201
  # }
2776
3202
  #
2777
- return response
3203
+ return [self.safe_order({'info': response})]
2778
3204
 
2779
3205
  async def fetch_orders_by_status(self, status, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2780
3206
  if symbol is None:
@@ -2825,15 +3251,17 @@ class bitmart(Exchange, ImplicitAPI):
2825
3251
  # }
2826
3252
  # }
2827
3253
  #
2828
- data = self.safe_value(response, 'data', {})
3254
+ data = self.safe_dict(response, 'data', {})
2829
3255
  orders = self.safe_list(data, 'orders', [])
2830
3256
  return self.parse_orders(orders, market, since, limit)
2831
3257
 
2832
3258
  async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2833
3259
  """
2834
- :see: https://developer-pro.bitmart.com/en/spot/#current-open-orders-v4-signed
2835
- :see: https://developer-pro.bitmart.com/en/futures/#get-all-open-orders-keyed
2836
- :see: https://developer-pro.bitmart.com/en/futures/#get-all-current-plan-orders-keyed
3260
+
3261
+ https://developer-pro.bitmart.com/en/spot/#current-open-orders-v4-signed
3262
+ https://developer-pro.bitmart.com/en/futuresv2/#get-all-open-orders-keyed
3263
+ https://developer-pro.bitmart.com/en/futuresv2/#get-all-current-plan-orders-keyed
3264
+
2837
3265
  fetch all unfilled currently open orders
2838
3266
  :param str symbol: unified market symbol
2839
3267
  :param int [since]: the earliest time in ms to fetch open orders for
@@ -2846,6 +3274,7 @@ class bitmart(Exchange, ImplicitAPI):
2846
3274
  :param str [params.orderType]: *swap only* 'limit', 'market', or 'trailing'
2847
3275
  :param boolean [params.trailing]: *swap only* set to True if you want to fetch trailing orders
2848
3276
  :param boolean [params.trigger]: *swap only* set to True if you want to fetch trigger orders
3277
+ :param str [params.stpMode]: self-trade prevention only for spot, defaults to none, ['none', 'cancel_maker', 'cancel_taker', 'cancel_both']
2849
3278
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2850
3279
  """
2851
3280
  await self.load_markets()
@@ -2854,12 +3283,12 @@ class bitmart(Exchange, ImplicitAPI):
2854
3283
  if symbol is not None:
2855
3284
  market = self.market(symbol)
2856
3285
  request['symbol'] = market['id']
2857
- if limit is not None:
2858
- request['limit'] = limit
2859
3286
  type = None
2860
3287
  response = None
2861
3288
  type, params = self.handle_market_type_and_params('fetchOpenOrders', market, params)
2862
3289
  if type == 'spot':
3290
+ if limit is not None:
3291
+ request['limit'] = min(limit, 200)
2863
3292
  marginMode = None
2864
3293
  marginMode, params = self.handle_margin_mode_and_params('fetchOpenOrders', params)
2865
3294
  if marginMode == 'isolated':
@@ -2872,9 +3301,11 @@ class bitmart(Exchange, ImplicitAPI):
2872
3301
  request['endTime'] = until
2873
3302
  response = await self.privatePostSpotV4QueryOpenOrders(self.extend(request, params))
2874
3303
  elif type == 'swap':
2875
- isStop = self.safe_value_2(params, 'stop', 'trigger')
3304
+ if limit is not None:
3305
+ request['limit'] = min(limit, 100)
3306
+ isTrigger = self.safe_bool_2(params, 'stop', 'trigger')
2876
3307
  params = self.omit(params, ['stop', 'trigger'])
2877
- if isStop:
3308
+ if isTrigger:
2878
3309
  response = await self.privateGetContractPrivateCurrentPlanOrder(self.extend(request, params))
2879
3310
  else:
2880
3311
  trailing = self.safe_bool(params, 'trailing', False)
@@ -2946,8 +3377,10 @@ class bitmart(Exchange, ImplicitAPI):
2946
3377
 
2947
3378
  async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2948
3379
  """
2949
- :see: https://developer-pro.bitmart.com/en/spot/#account-orders-v4-signed
2950
- :see: https://developer-pro.bitmart.com/en/futures/#get-order-history-keyed
3380
+
3381
+ https://developer-pro.bitmart.com/en/spot/#account-orders-v4-signed
3382
+ https://developer-pro.bitmart.com/en/futuresv2/#get-order-history-keyed
3383
+
2951
3384
  fetches information on multiple closed orders made by the user
2952
3385
  :param str symbol: unified market symbol of the market orders were made in
2953
3386
  :param int [since]: the earliest time in ms to fetch orders for
@@ -2955,6 +3388,7 @@ class bitmart(Exchange, ImplicitAPI):
2955
3388
  :param dict [params]: extra parameters specific to the exchange API endpoint
2956
3389
  :param int [params.until]: timestamp in ms of the latest entry
2957
3390
  :param str [params.marginMode]: *spot only* 'cross' or 'isolated', for margin trading
3391
+ :param str [params.stpMode]: self-trade prevention only for spot, defaults to none, ['none', 'cancel_maker', 'cancel_taker', 'cancel_both']
2958
3392
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2959
3393
  """
2960
3394
  await self.load_markets()
@@ -2968,12 +3402,8 @@ class bitmart(Exchange, ImplicitAPI):
2968
3402
  if type != 'spot':
2969
3403
  if symbol is None:
2970
3404
  raise ArgumentsRequired(self.id + ' fetchClosedOrders() requires a symbol argument')
2971
- marginMode = None
2972
- marginMode, params = self.handle_margin_mode_and_params('fetchClosedOrders', params)
2973
- if marginMode == 'isolated':
2974
- request['orderMode'] = 'iso_margin'
2975
- startTimeKey = 'startTime' if (type == 'spot') else 'start_time'
2976
3405
  if since is not None:
3406
+ startTimeKey = 'startTime' if (type == 'spot') else 'start_time'
2977
3407
  request[startTimeKey] = since
2978
3408
  endTimeKey = 'endTime' if (type == 'spot') else 'end_time'
2979
3409
  until = self.safe_integer_2(params, 'until', endTimeKey)
@@ -2982,6 +3412,10 @@ class bitmart(Exchange, ImplicitAPI):
2982
3412
  request[endTimeKey] = until
2983
3413
  response = None
2984
3414
  if type == 'spot':
3415
+ marginMode = None
3416
+ marginMode, params = self.handle_margin_mode_and_params('fetchClosedOrders', params)
3417
+ if marginMode == 'isolated':
3418
+ request['orderMode'] = 'iso_margin'
2985
3419
  response = await self.privatePostSpotV4QueryHistoryOrders(self.extend(request, params))
2986
3420
  else:
2987
3421
  response = await self.privateGetContractPrivateOrderHistory(self.extend(request, params))
@@ -3002,15 +3436,18 @@ class bitmart(Exchange, ImplicitAPI):
3002
3436
  async def fetch_order(self, id: str, symbol: Str = None, params={}):
3003
3437
  """
3004
3438
  fetches information on an order made by the user
3005
- :see: https://developer-pro.bitmart.com/en/spot/#query-order-by-id-v4-signed
3006
- :see: https://developer-pro.bitmart.com/en/spot/#query-order-by-clientorderid-v4-signed
3007
- :see: https://developer-pro.bitmart.com/en/futures/#get-order-detail-keyed
3439
+
3440
+ https://developer-pro.bitmart.com/en/spot/#query-order-by-id-v4-signed
3441
+ https://developer-pro.bitmart.com/en/spot/#query-order-by-clientorderid-v4-signed
3442
+ https://developer-pro.bitmart.com/en/futuresv2/#get-order-detail-keyed
3443
+
3008
3444
  :param str id: the id of the order
3009
3445
  :param str symbol: unified symbol of the market the order was made in
3010
3446
  :param dict [params]: extra parameters specific to the exchange API endpoint
3011
3447
  :param str [params.clientOrderId]: *spot* fetch the order by client order id instead of order id
3012
3448
  :param str [params.orderType]: *swap only* 'limit', 'market', 'liquidate', 'bankruptcy', 'adl' or 'trailing'
3013
3449
  :param boolean [params.trailing]: *swap only* set to True if you want to fetch a trailing order
3450
+ :param str [params.stpMode]: self-trade prevention only for spot, defaults to none, ['none', 'cancel_maker', 'cancel_taker', 'cancel_both']
3014
3451
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
3015
3452
  """
3016
3453
  await self.load_markets()
@@ -3095,28 +3532,23 @@ class bitmart(Exchange, ImplicitAPI):
3095
3532
  data = self.safe_dict(response, 'data', {})
3096
3533
  return self.parse_order(data, market)
3097
3534
 
3098
- async def fetch_deposit_address(self, code: str, params={}):
3535
+ async def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
3099
3536
  """
3100
3537
  fetch the deposit address for a currency associated with self account
3101
- :see: https://developer-pro.bitmart.com/en/spot/#deposit-address-keyed
3538
+
3539
+ https://developer-pro.bitmart.com/en/spot/#deposit-address-keyed
3540
+
3102
3541
  :param str code: unified currency code
3103
3542
  :param dict [params]: extra parameters specific to the exchange API endpoint
3104
3543
  :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
3105
3544
  """
3106
3545
  await self.load_markets()
3107
3546
  currency = self.currency(code)
3547
+ network: Str = None
3548
+ network, params = self.handle_network_code_and_params(params)
3108
3549
  request: dict = {
3109
- 'currency': currency['id'],
3550
+ 'currency': self.get_currency_id_from_code_and_network(code, network),
3110
3551
  }
3111
- if code == 'USDT':
3112
- defaultNetworks = self.safe_value(self.options, 'defaultNetworks')
3113
- defaultNetwork = self.safe_string_upper(defaultNetworks, code)
3114
- networks = self.safe_value(self.options, 'networks', {})
3115
- networkInner = self.safe_string_upper(params, 'network', defaultNetwork) # self line allows the user to specify either ERC20 or ETH
3116
- networkInner = self.safe_string(networks, networkInner, networkInner) # handle ERC20>ETH alias
3117
- if networkInner is not None:
3118
- request['currency'] = request['currency'] + '-' + networkInner # when network the currency need to be changed to currency + '-' + network https://developer-pro.bitmart.com/en/account/withdraw_apply.html on the end of page
3119
- params = self.omit(params, 'network')
3120
3552
  response = await self.privateGetAccountV1DepositAddress(self.extend(request, params))
3121
3553
  #
3122
3554
  # {
@@ -3134,8 +3566,9 @@ class bitmart(Exchange, ImplicitAPI):
3134
3566
  data = self.safe_dict(response, 'data', {})
3135
3567
  return self.parse_deposit_address(data, currency)
3136
3568
 
3137
- def parse_deposit_address(self, depositAddress, currency=None):
3569
+ def parse_deposit_address(self, depositAddress, currency=None) -> DepositAddress:
3138
3570
  #
3571
+ # fetchDepositAddress
3139
3572
  # {
3140
3573
  # currency: 'ETH',
3141
3574
  # chain: 'Ethereum',
@@ -3143,63 +3576,64 @@ class bitmart(Exchange, ImplicitAPI):
3143
3576
  # address_memo: ''
3144
3577
  # }
3145
3578
  #
3579
+ # fetchWithdrawAddress
3580
+ # {
3581
+ # "currency": "ETH",
3582
+ # "network": "ETH",
3583
+ # "address": "0x1121",
3584
+ # "memo": "12",
3585
+ # "remark": "12",
3586
+ # "addressType": 0,
3587
+ # "verifyStatus": 0
3588
+ # }
3589
+ #
3146
3590
  currencyId = self.safe_string(depositAddress, 'currency')
3591
+ network = self.safe_string_2(depositAddress, 'chain', 'network')
3592
+ if currencyId.find('NFT') < 0:
3593
+ parts = currencyId.split('-')
3594
+ currencyId = self.safe_string(parts, 0)
3595
+ secondPart = self.safe_string(parts, 1)
3596
+ if secondPart is not None:
3597
+ network = secondPart
3147
3598
  address = self.safe_string(depositAddress, 'address')
3148
- chain = self.safe_string(depositAddress, 'chain')
3149
- network = None
3150
3599
  currency = self.safe_currency(currencyId, currency)
3151
- if chain is not None:
3152
- parts = chain.split('-')
3153
- partsLength = len(parts)
3154
- networkId = self.safe_string(parts, partsLength - 1)
3155
- network = self.safe_network_code(networkId, currency)
3156
3600
  self.check_address(address)
3157
3601
  return {
3158
3602
  'info': depositAddress,
3159
3603
  'currency': self.safe_string(currency, 'code'),
3604
+ 'network': self.network_id_to_code(network),
3160
3605
  'address': address,
3161
- 'tag': self.safe_string(depositAddress, 'address_memo'),
3162
- 'network': network,
3606
+ 'tag': self.safe_string_2(depositAddress, 'address_memo', 'memo'),
3163
3607
  }
3164
3608
 
3165
- def safe_network_code(self, networkId, currency=None):
3166
- name = self.safe_string(currency, 'name')
3167
- if networkId == name:
3168
- code = self.safe_string(currency, 'code')
3169
- return code
3170
- return self.network_id_to_code(networkId)
3171
-
3172
- async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
3609
+ async def withdraw(self, code: str, amount: float, address: str, tag: Str = None, params={}) -> Transaction:
3173
3610
  """
3174
3611
  make a withdrawal
3612
+
3613
+ https://developer-pro.bitmart.com/en/spot/#withdraw-signed
3614
+
3175
3615
  :param str code: unified currency code
3176
3616
  :param float amount: the amount to withdraw
3177
3617
  :param str address: the address to withdraw to
3178
3618
  :param str tag:
3179
3619
  :param dict [params]: extra parameters specific to the exchange API endpoint
3620
+ :param str [params.network]: the network name for self withdrawal
3180
3621
  :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
3181
3622
  """
3182
3623
  tag, params = self.handle_withdraw_tag_and_params(tag, params)
3183
3624
  self.check_address(address)
3184
3625
  await self.load_markets()
3185
3626
  currency = self.currency(code)
3627
+ network: Str = None
3628
+ network, params = self.handle_network_code_and_params(params)
3186
3629
  request: dict = {
3187
- 'currency': currency['id'],
3630
+ 'currency': self.get_currency_id_from_code_and_network(code, network),
3188
3631
  'amount': amount,
3189
3632
  'destination': 'To Digital Address', # To Digital Address, To Binance, To OKEX
3190
3633
  'address': address,
3191
3634
  }
3192
3635
  if tag is not None:
3193
3636
  request['address_memo'] = tag
3194
- if code == 'USDT':
3195
- defaultNetworks = self.safe_value(self.options, 'defaultNetworks')
3196
- defaultNetwork = self.safe_string_upper(defaultNetworks, code)
3197
- networks = self.safe_value(self.options, 'networks', {})
3198
- network = self.safe_string_upper(params, 'network', defaultNetwork) # self line allows the user to specify either ERC20 or ETH
3199
- network = self.safe_string(networks, network, network) # handle ERC20>ETH alias
3200
- if network is not None:
3201
- request['currency'] = request['currency'] + '-' + network # when network the currency need to be changed to currency + '-' + network https://developer-pro.bitmart.com/en/account/withdraw_apply.html on the end of page
3202
- params = self.omit(params, 'network')
3203
3637
  response = await self.privatePostAccountV1WithdrawApply(self.extend(request, params))
3204
3638
  #
3205
3639
  # {
@@ -3211,7 +3645,7 @@ class bitmart(Exchange, ImplicitAPI):
3211
3645
  # }
3212
3646
  # }
3213
3647
  #
3214
- data = self.safe_value(response, 'data')
3648
+ data = self.safe_dict(response, 'data', {})
3215
3649
  transaction = self.parse_transaction(data, currency)
3216
3650
  return self.extend(transaction, {
3217
3651
  'code': code,
@@ -3222,26 +3656,21 @@ class bitmart(Exchange, ImplicitAPI):
3222
3656
  async def fetch_transactions_by_type(self, type, code: Str = None, since: Int = None, limit: Int = None, params={}):
3223
3657
  await self.load_markets()
3224
3658
  if limit is None:
3225
- limit = 50 # max 50
3659
+ limit = 1000 # max 1000
3226
3660
  request: dict = {
3227
3661
  'operation_type': type, # deposit or withdraw
3228
- 'offset': 1,
3229
3662
  'N': limit,
3230
3663
  }
3231
3664
  currency = None
3232
3665
  if code is not None:
3233
3666
  currency = self.currency(code)
3234
3667
  request['currency'] = currency['id']
3235
- if code == 'USDT':
3236
- defaultNetworks = self.safe_value(self.options, 'defaultNetworks')
3237
- defaultNetwork = self.safe_string_upper(defaultNetworks, code)
3238
- networks = self.safe_value(self.options, 'networks', {})
3239
- network = self.safe_string_upper(params, 'network', defaultNetwork) # self line allows the user to specify either ERC20 or ETH
3240
- network = self.safe_string(networks, network, network) # handle ERC20>ETH alias
3241
- if network is not None:
3242
- request['currency'] += '-' + network # when network the currency need to be changed to currency + '-' + network https://developer-pro.bitmart.com/en/account/withdraw_apply.html on the end of page
3243
- currency['code'] = request['currency'] # update currency code to filter
3244
- params = self.omit(params, 'network')
3668
+ if since is not None:
3669
+ request['startTime'] = since
3670
+ until = self.safe_integer(params, 'until')
3671
+ if until is not None:
3672
+ params = self.omit(params, 'until')
3673
+ request['endTime'] = until
3245
3674
  response = await self.privateGetAccountV2DepositWithdrawHistory(self.extend(request, params))
3246
3675
  #
3247
3676
  # {
@@ -3267,13 +3696,16 @@ class bitmart(Exchange, ImplicitAPI):
3267
3696
  # }
3268
3697
  # }
3269
3698
  #
3270
- data = self.safe_value(response, 'data', {})
3699
+ data = self.safe_dict(response, 'data', {})
3271
3700
  records = self.safe_list(data, 'records', [])
3272
3701
  return self.parse_transactions(records, currency, since, limit)
3273
3702
 
3274
3703
  async def fetch_deposit(self, id: str, code: Str = None, params={}):
3275
3704
  """
3276
3705
  fetch information on a deposit
3706
+
3707
+ https://developer-pro.bitmart.com/en/spot/#get-a-deposit-or-withdraw-detail-keyed
3708
+
3277
3709
  :param str id: deposit id
3278
3710
  :param str code: not used by bitmart fetchDeposit()
3279
3711
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -3306,13 +3738,16 @@ class bitmart(Exchange, ImplicitAPI):
3306
3738
  # }
3307
3739
  # }
3308
3740
  #
3309
- data = self.safe_value(response, 'data', {})
3741
+ data = self.safe_dict(response, 'data', {})
3310
3742
  record = self.safe_dict(data, 'record', {})
3311
3743
  return self.parse_transaction(record)
3312
3744
 
3313
3745
  async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
3314
3746
  """
3315
3747
  fetch all deposits made to an account
3748
+
3749
+ https://developer-pro.bitmart.com/en/spot/#get-deposit-and-withdraw-history-keyed
3750
+
3316
3751
  :param str code: unified currency code
3317
3752
  :param int [since]: the earliest time in ms to fetch deposits for
3318
3753
  :param int [limit]: the maximum number of deposits structures to retrieve
@@ -3324,6 +3759,9 @@ class bitmart(Exchange, ImplicitAPI):
3324
3759
  async def fetch_withdrawal(self, id: str, code: Str = None, params={}):
3325
3760
  """
3326
3761
  fetch data on a currency withdrawal via the withdrawal id
3762
+
3763
+ https://developer-pro.bitmart.com/en/spot/#get-a-deposit-or-withdraw-detail-keyed
3764
+
3327
3765
  :param str id: withdrawal id
3328
3766
  :param str code: not used by bitmart.fetchWithdrawal
3329
3767
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -3356,13 +3794,16 @@ class bitmart(Exchange, ImplicitAPI):
3356
3794
  # }
3357
3795
  # }
3358
3796
  #
3359
- data = self.safe_value(response, 'data', {})
3797
+ data = self.safe_dict(response, 'data', {})
3360
3798
  record = self.safe_dict(data, 'record', {})
3361
3799
  return self.parse_transaction(record)
3362
3800
 
3363
3801
  async def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
3364
3802
  """
3365
3803
  fetch all withdrawals made from an account
3804
+
3805
+ https://developer-pro.bitmart.com/en/spot/#get-deposit-and-withdraw-history-keyed
3806
+
3366
3807
  :param str code: unified currency code
3367
3808
  :param int [since]: the earliest time in ms to fetch withdrawals for
3368
3809
  :param int [limit]: the maximum number of withdrawals structures to retrieve
@@ -3419,6 +3860,12 @@ class bitmart(Exchange, ImplicitAPI):
3419
3860
  amount = self.safe_number(transaction, 'arrival_amount')
3420
3861
  timestamp = self.safe_integer(transaction, 'apply_time')
3421
3862
  currencyId = self.safe_string(transaction, 'currency')
3863
+ networkId: Str = None
3864
+ if currencyId is not None:
3865
+ if currencyId.find('NFT') < 0:
3866
+ parts = currencyId.split('-')
3867
+ currencyId = self.safe_string(parts, 0)
3868
+ networkId = self.safe_string(parts, 1)
3422
3869
  code = self.safe_currency_code(currencyId, currency)
3423
3870
  status = self.parse_transaction_status(self.safe_string(transaction, 'status'))
3424
3871
  feeCost = self.safe_number(transaction, 'fee')
@@ -3436,7 +3883,7 @@ class bitmart(Exchange, ImplicitAPI):
3436
3883
  'id': id,
3437
3884
  'currency': code,
3438
3885
  'amount': amount,
3439
- 'network': None,
3886
+ 'network': self.network_id_to_code(networkId),
3440
3887
  'address': address,
3441
3888
  'addressFrom': None,
3442
3889
  'addressTo': None,
@@ -3457,7 +3904,9 @@ class bitmart(Exchange, ImplicitAPI):
3457
3904
  async def repay_isolated_margin(self, symbol: str, code: str, amount, params={}):
3458
3905
  """
3459
3906
  repay borrowed margin and interest
3460
- :see: https://developer-pro.bitmart.com/en/spot/#margin-repay-isolated
3907
+
3908
+ https://developer-pro.bitmart.com/en/spot/#margin-repay-isolated-signed
3909
+
3461
3910
  :param str symbol: unified market symbol
3462
3911
  :param str code: unified currency code of the currency to repay
3463
3912
  :param str amount: the amount to repay
@@ -3483,7 +3932,7 @@ class bitmart(Exchange, ImplicitAPI):
3483
3932
  # }
3484
3933
  # }
3485
3934
  #
3486
- data = self.safe_value(response, 'data', {})
3935
+ data = self.safe_dict(response, 'data', {})
3487
3936
  transaction = self.parse_margin_loan(data, currency)
3488
3937
  return self.extend(transaction, {
3489
3938
  'amount': amount,
@@ -3493,7 +3942,9 @@ class bitmart(Exchange, ImplicitAPI):
3493
3942
  async def borrow_isolated_margin(self, symbol: str, code: str, amount: float, params={}):
3494
3943
  """
3495
3944
  create a loan to borrow margin
3496
- :see: https://developer-pro.bitmart.com/en/spot/#margin-borrow-isolated
3945
+
3946
+ https://developer-pro.bitmart.com/en/spot/#margin-borrow-isolated-signed
3947
+
3497
3948
  :param str symbol: unified market symbol
3498
3949
  :param str code: unified currency code of the currency to borrow
3499
3950
  :param str amount: the amount to borrow
@@ -3519,7 +3970,7 @@ class bitmart(Exchange, ImplicitAPI):
3519
3970
  # }
3520
3971
  # }
3521
3972
  #
3522
- data = self.safe_value(response, 'data', {})
3973
+ data = self.safe_dict(response, 'data', {})
3523
3974
  transaction = self.parse_margin_loan(data, currency)
3524
3975
  return self.extend(transaction, {
3525
3976
  'amount': amount,
@@ -3553,7 +4004,9 @@ class bitmart(Exchange, ImplicitAPI):
3553
4004
  async def fetch_isolated_borrow_rate(self, symbol: str, params={}) -> IsolatedBorrowRate:
3554
4005
  """
3555
4006
  fetch the rate of interest to borrow a currency for margin trading
3556
- :see: https://developer-pro.bitmart.com/en/spot/#get-trading-pair-borrowing-rate-and-amount-keyed
4007
+
4008
+ https://developer-pro.bitmart.com/en/spot/#get-trading-pair-borrowing-rate-and-amount-keyed
4009
+
3557
4010
  :param str symbol: unified symbol of the market to fetch the borrow rate for
3558
4011
  :param dict [params]: extra parameters specific to the exchange API endpoint
3559
4012
  :returns dict: an `isolated borrow rate structure <https://github.com/ccxt/ccxt/wiki/Manual#isolated-borrow-rate-structure>`
@@ -3596,12 +4049,12 @@ class bitmart(Exchange, ImplicitAPI):
3596
4049
  # }
3597
4050
  # }
3598
4051
  #
3599
- data = self.safe_value(response, 'data', {})
3600
- symbols = self.safe_value(data, 'symbols', [])
3601
- borrowRate = self.safe_value(symbols, 0)
4052
+ data = self.safe_dict(response, 'data', {})
4053
+ symbols = self.safe_list(data, 'symbols', [])
4054
+ borrowRate = self.safe_dict(symbols, 0, [])
3602
4055
  return self.parse_isolated_borrow_rate(borrowRate, market)
3603
4056
 
3604
- def parse_isolated_borrow_rate(self, info, market: Market = None) -> IsolatedBorrowRate:
4057
+ def parse_isolated_borrow_rate(self, info: dict, market: Market = None) -> IsolatedBorrowRate:
3605
4058
  #
3606
4059
  # {
3607
4060
  # "symbol": "BTC_USDT",
@@ -3627,8 +4080,8 @@ class bitmart(Exchange, ImplicitAPI):
3627
4080
  #
3628
4081
  marketId = self.safe_string(info, 'symbol')
3629
4082
  symbol = self.safe_symbol(marketId, market)
3630
- baseData = self.safe_value(info, 'base', {})
3631
- quoteData = self.safe_value(info, 'quote', {})
4083
+ baseData = self.safe_dict(info, 'base', {})
4084
+ quoteData = self.safe_dict(info, 'quote', {})
3632
4085
  baseId = self.safe_string(baseData, 'currency')
3633
4086
  quoteId = self.safe_string(quoteData, 'currency')
3634
4087
  return {
@@ -3646,7 +4099,9 @@ class bitmart(Exchange, ImplicitAPI):
3646
4099
  async def fetch_isolated_borrow_rates(self, params={}) -> IsolatedBorrowRates:
3647
4100
  """
3648
4101
  fetch the borrow interest rates of all currencies, currently only works for isolated margin
3649
- :see: https://developer-pro.bitmart.com/en/spot/#get-trading-pair-borrowing-rate-and-amount-keyed
4102
+
4103
+ https://developer-pro.bitmart.com/en/spot/#get-trading-pair-borrowing-rate-and-amount-keyed
4104
+
3650
4105
  :param dict [params]: extra parameters specific to the exchange API endpoint
3651
4106
  :returns dict: a list of `isolated borrow rate structures <https://docs.ccxt.com/#/?id=isolated-borrow-rate-structure>`
3652
4107
  """
@@ -3684,15 +4139,17 @@ class bitmart(Exchange, ImplicitAPI):
3684
4139
  # }
3685
4140
  # }
3686
4141
  #
3687
- data = self.safe_value(response, 'data', {})
3688
- symbols = self.safe_value(data, 'symbols', [])
4142
+ data = self.safe_dict(response, 'data', {})
4143
+ symbols = self.safe_list(data, 'symbols', [])
3689
4144
  return self.parse_isolated_borrow_rates(symbols)
3690
4145
 
3691
4146
  async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
3692
4147
  """
3693
4148
  transfer currency internally between wallets on the same account, currently only supports transfer between spot and margin
3694
- :see: https://developer-pro.bitmart.com/en/spot/#margin-asset-transfer-signed
3695
- :see: https://developer-pro.bitmart.com/en/futures/#transfer-signed
4149
+
4150
+ https://developer-pro.bitmart.com/en/spot/#margin-asset-transfer-signed
4151
+ https://developer-pro.bitmart.com/en/futuresv2/#transfer-signed
4152
+
3696
4153
  :param str code: unified currency code
3697
4154
  :param float amount: amount to transfer
3698
4155
  :param str fromAccount: account to transfer from
@@ -3752,7 +4209,7 @@ class bitmart(Exchange, ImplicitAPI):
3752
4209
  # }
3753
4210
  # }
3754
4211
  #
3755
- data = self.safe_value(response, 'data', {})
4212
+ data = self.safe_dict(response, 'data', {})
3756
4213
  return self.extend(self.parse_transfer(data, currency), {
3757
4214
  'status': self.parse_transfer_status(self.safe_string_2(response, 'code', 'message')),
3758
4215
  })
@@ -3818,10 +4275,12 @@ class bitmart(Exchange, ImplicitAPI):
3818
4275
  'status': self.parse_transfer_status(self.safe_string(transfer, 'state')),
3819
4276
  }
3820
4277
 
3821
- async def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> TransferEntries:
4278
+ async def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[TransferEntry]:
3822
4279
  """
3823
4280
  fetch a history of internal transfers made on an account, only transfers between spot and swap are supported
3824
- :see: https://developer-pro.bitmart.com/en/futures/#get-transfer-list-signed
4281
+
4282
+ https://developer-pro.bitmart.com/en/futuresv2/#get-transfer-list-signed
4283
+
3825
4284
  :param str code: unified currency code of the currency transferred
3826
4285
  :param int [since]: the earliest time in ms to fetch transfers for
3827
4286
  :param int [limit]: the maximum number of transfer structures to retrieve
@@ -3870,14 +4329,16 @@ class bitmart(Exchange, ImplicitAPI):
3870
4329
  # }
3871
4330
  # }
3872
4331
  #
3873
- data = self.safe_value(response, 'data', {})
4332
+ data = self.safe_dict(response, 'data', {})
3874
4333
  records = self.safe_list(data, 'records', [])
3875
4334
  return self.parse_transfers(records, currency, since, limit)
3876
4335
 
3877
- async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4336
+ async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[BorrowInterest]:
3878
4337
  """
3879
4338
  fetch the interest owed by the user for borrowing currency for margin trading
3880
- :see: https://developer-pro.bitmart.com/en/spot/#get-borrow-record-isolated
4339
+
4340
+ https://developer-pro.bitmart.com/en/spot/#get-borrow-record-isolated-keyed
4341
+
3881
4342
  :param str code: unified currency code
3882
4343
  :param str symbol: unified market symbol when fetch interest in isolated markets
3883
4344
  :param int [since]: the earliest time in ms to fetch borrrow interest for
@@ -3918,12 +4379,12 @@ class bitmart(Exchange, ImplicitAPI):
3918
4379
  # }
3919
4380
  # }
3920
4381
  #
3921
- data = self.safe_value(response, 'data', {})
3922
- rows = self.safe_value(data, 'records', [])
4382
+ data = self.safe_dict(response, 'data', {})
4383
+ rows = self.safe_list(data, 'records', [])
3923
4384
  interest = self.parse_borrow_interests(rows, market)
3924
4385
  return self.filter_by_currency_since_limit(interest, code, since, limit)
3925
4386
 
3926
- def parse_borrow_interest(self, info: dict, market: Market = None):
4387
+ def parse_borrow_interest(self, info: dict, market: Market = None) -> BorrowInterest:
3927
4388
  #
3928
4389
  # {
3929
4390
  # "borrow_id": "1657664327844Lk5eJJugXmdHHZoe",
@@ -3940,21 +4401,23 @@ class bitmart(Exchange, ImplicitAPI):
3940
4401
  market = self.safe_market(marketId, market)
3941
4402
  timestamp = self.safe_integer(info, 'create_time')
3942
4403
  return {
4404
+ 'info': info,
3943
4405
  'symbol': self.safe_string(market, 'symbol'),
3944
- 'marginMode': 'isolated',
3945
4406
  'currency': self.safe_currency_code(self.safe_string(info, 'currency')),
3946
4407
  'interest': self.safe_number(info, 'interest_amount'),
3947
4408
  'interestRate': self.safe_number(info, 'hourly_interest'),
3948
4409
  'amountBorrowed': self.safe_number(info, 'borrow_amount'),
4410
+ 'marginMode': 'isolated',
3949
4411
  'timestamp': timestamp, # borrow creation time
3950
4412
  'datetime': self.iso8601(timestamp),
3951
- 'info': info,
3952
4413
  }
3953
4414
 
3954
4415
  async def fetch_open_interest(self, symbol: str, params={}):
3955
4416
  """
3956
4417
  Retrieves the open interest of a currency
3957
- :see: https://developer-pro.bitmart.com/en/futures/#get-futures-openinterest
4418
+
4419
+ https://developer-pro.bitmart.com/en/futuresv2/#get-futures-openinterest
4420
+
3958
4421
  :param str symbol: Unified CCXT market symbol
3959
4422
  :param dict [params]: exchange specific parameters
3960
4423
  :returns dict} an open interest structure{@link https://docs.ccxt.com/#/?id=open-interest-structure:
@@ -4003,10 +4466,12 @@ class bitmart(Exchange, ImplicitAPI):
4003
4466
  'info': interest,
4004
4467
  }, market)
4005
4468
 
4006
- async def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
4469
+ async def set_leverage(self, leverage: int, symbol: Str = None, params={}):
4007
4470
  """
4008
4471
  set the level of leverage for a market
4009
- :see: https://developer-pro.bitmart.com/en/futures/#submit-leverage-signed
4472
+
4473
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-leverage-signed
4474
+
4010
4475
  :param float leverage: the rate of leverage
4011
4476
  :param str symbol: unified market symbol
4012
4477
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -4029,10 +4494,12 @@ class bitmart(Exchange, ImplicitAPI):
4029
4494
  }
4030
4495
  return await self.privatePostContractPrivateSubmitLeverage(self.extend(request, params))
4031
4496
 
4032
- async def fetch_funding_rate(self, symbol: str, params={}):
4497
+ async def fetch_funding_rate(self, symbol: str, params={}) -> FundingRate:
4033
4498
  """
4034
4499
  fetch the current funding rate
4035
- :see: https://developer-pro.bitmart.com/en/futures/#get-current-funding-rate
4500
+
4501
+ https://developer-pro.bitmart.com/en/futuresv2/#get-current-funding-rate
4502
+
4036
4503
  :param str symbol: unified market symbol
4037
4504
  :param dict [params]: extra parameters specific to the exchange API endpoint
4038
4505
  :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
@@ -4058,10 +4525,66 @@ class bitmart(Exchange, ImplicitAPI):
4058
4525
  # "trace": "4cad855074654097ac7ba5257c47305d.54.16951844206655589"
4059
4526
  # }
4060
4527
  #
4061
- data = self.safe_value(response, 'data', {})
4528
+ data = self.safe_dict(response, 'data', {})
4062
4529
  return self.parse_funding_rate(data, market)
4063
4530
 
4064
- def parse_funding_rate(self, contract, market: Market = None):
4531
+ async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4532
+ """
4533
+ fetches historical funding rate prices
4534
+
4535
+ https://developer-pro.bitmart.com/en/futuresv2/#get-funding-rate-history
4536
+
4537
+ :param str symbol: unified symbol of the market to fetch the funding rate history for
4538
+ :param int [since]: not sent to exchange api, exchange api always returns the most recent data, only used to filter exchange response
4539
+ :param int [limit]: the maximum amount of funding rate structures to fetch
4540
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4541
+ :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
4542
+ """
4543
+ if symbol is None:
4544
+ raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
4545
+ await self.load_markets()
4546
+ market = self.market(symbol)
4547
+ request: dict = {
4548
+ 'symbol': market['id'],
4549
+ }
4550
+ if limit is not None:
4551
+ request['limit'] = limit
4552
+ response = await self.publicGetContractPublicFundingRateHistory(self.extend(request, params))
4553
+ #
4554
+ # {
4555
+ # "code": 1000,
4556
+ # "message": "Ok",
4557
+ # "data": {
4558
+ # "list": [
4559
+ # {
4560
+ # "symbol": "BTCUSDT",
4561
+ # "funding_rate": "0.000091412174",
4562
+ # "funding_time": "1734336000000"
4563
+ # },
4564
+ # ]
4565
+ # },
4566
+ # "trace": "fg73d949fgfdf6a40c8fc7f5ae6738.54.345345345345"
4567
+ # }
4568
+ #
4569
+ data = self.safe_dict(response, 'data', {})
4570
+ result = self.safe_list(data, 'list', [])
4571
+ rates = []
4572
+ for i in range(0, len(result)):
4573
+ entry = result[i]
4574
+ marketId = self.safe_string(entry, 'symbol')
4575
+ symbolInner = self.safe_symbol(marketId, market, '-', 'swap')
4576
+ timestamp = self.safe_integer(entry, 'funding_time')
4577
+ rates.append({
4578
+ 'info': entry,
4579
+ 'symbol': symbolInner,
4580
+ 'fundingRate': self.safe_number(entry, 'funding_rate'),
4581
+ 'timestamp': timestamp,
4582
+ 'datetime': self.iso8601(timestamp),
4583
+ })
4584
+ sorted = self.sort_by(rates, 'timestamp')
4585
+ return self.filter_by_symbol_since_limit(sorted, market['symbol'], since, limit)
4586
+
4587
+ def parse_funding_rate(self, contract, market: Market = None) -> FundingRate:
4065
4588
  #
4066
4589
  # {
4067
4590
  # "timestamp": 1695184410697,
@@ -4090,12 +4613,15 @@ class bitmart(Exchange, ImplicitAPI):
4090
4613
  'previousFundingRate': self.safe_number(contract, 'rate_value'),
4091
4614
  'previousFundingTimestamp': None,
4092
4615
  'previousFundingDatetime': None,
4616
+ 'interval': None,
4093
4617
  }
4094
4618
 
4095
4619
  async def fetch_position(self, symbol: str, params={}):
4096
4620
  """
4097
4621
  fetch data on a single open contract trade position
4098
- :see: https://developer-pro.bitmart.com/en/futures/#get-current-position-keyed
4622
+
4623
+ https://developer-pro.bitmart.com/en/futuresv2/#get-current-position-keyed
4624
+
4099
4625
  :param str symbol: unified market symbol of the market the position is held in
4100
4626
  :param dict [params]: extra parameters specific to the exchange API endpoint
4101
4627
  :returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
@@ -4135,14 +4661,17 @@ class bitmart(Exchange, ImplicitAPI):
4135
4661
  # "trace":"4cad855074664097ac5ba5257c47305d.67.16963925142065945"
4136
4662
  # }
4137
4663
  #
4138
- data = self.safe_value(response, 'data', [])
4664
+ data = self.safe_list(response, 'data', [])
4139
4665
  first = self.safe_dict(data, 0, {})
4140
4666
  return self.parse_position(first, market)
4141
4667
 
4142
- async def fetch_positions(self, symbols: Strings = None, params={}):
4668
+ async def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
4143
4669
  """
4144
4670
  fetch all open contract positions
4145
- :see: https://developer-pro.bitmart.com/en/futures/#get-current-position-keyed
4671
+
4672
+ https://developer-pro.bitmart.com/en/futuresv2/#get-current-position-keyed
4673
+ https://developer-pro.bitmart.com/en/futuresv2/#get-current-position-v2-keyed
4674
+
4146
4675
  :param str[]|None symbols: list of unified market symbols
4147
4676
  :param dict [params]: extra parameters specific to the exchange API endpoint
4148
4677
  :returns dict[]: a list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
@@ -4158,7 +4687,7 @@ class bitmart(Exchange, ImplicitAPI):
4158
4687
  if symbolsLength == 1:
4159
4688
  # only supports symbols or sending one symbol
4160
4689
  request['symbol'] = market['id']
4161
- response = await self.privateGetContractPrivatePosition(self.extend(request, params))
4690
+ response = await self.privateGetContractPrivatePositionV2(self.extend(request, params))
4162
4691
  #
4163
4692
  # {
4164
4693
  # "code": 1000,
@@ -4188,7 +4717,7 @@ class bitmart(Exchange, ImplicitAPI):
4188
4717
  # "trace":"4cad855074664097ac5ba5257c47305d.67.16963925142065945"
4189
4718
  # }
4190
4719
  #
4191
- positions = self.safe_value(response, 'data', [])
4720
+ positions = self.safe_list(response, 'data', [])
4192
4721
  result = []
4193
4722
  for i in range(0, len(positions)):
4194
4723
  result.append(self.parse_position(positions[i]))
@@ -4262,7 +4791,9 @@ class bitmart(Exchange, ImplicitAPI):
4262
4791
  async def fetch_my_liquidations(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4263
4792
  """
4264
4793
  retrieves the users liquidated positions
4265
- :see: https://developer-pro.bitmart.com/en/futures/#get-order-history-keyed
4794
+
4795
+ https://developer-pro.bitmart.com/en/futuresv2/#get-order-history-keyed
4796
+
4266
4797
  :param str symbol: unified CCXT market symbol
4267
4798
  :param int [since]: the earliest time in ms to fetch liquidations for
4268
4799
  :param int [limit]: the maximum number of liquidation structures to retrieve
@@ -4308,7 +4839,7 @@ class bitmart(Exchange, ImplicitAPI):
4308
4839
  # "trace": "4cad855074664097ac6ba4257c47305d.71.16965658195443021"
4309
4840
  # }
4310
4841
  #
4311
- data = self.safe_value(response, 'data', [])
4842
+ data = self.safe_list(response, 'data', [])
4312
4843
  result = []
4313
4844
  for i in range(0, len(data)):
4314
4845
  entry = data[i]
@@ -4355,11 +4886,417 @@ class bitmart(Exchange, ImplicitAPI):
4355
4886
  'datetime': self.iso8601(timestamp),
4356
4887
  })
4357
4888
 
4889
+ async def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}) -> Order:
4890
+ """
4891
+ edits an open order
4892
+
4893
+ https://developer-pro.bitmart.com/en/futuresv2/#modify-plan-order-signed
4894
+ https://developer-pro.bitmart.com/en/futuresv2/#modify-tp-sl-order-signed
4895
+ https://developer-pro.bitmart.com/en/futuresv2/#modify-preset-plan-order-signed
4896
+ https://developer-pro.bitmart.com/en/futuresv2/#modify-limit-order-signed
4897
+
4898
+ :param str id: order id
4899
+ :param str symbol: unified symbol of the market to edit an order in
4900
+ :param str type: 'market' or 'limit'
4901
+ :param str side: 'buy' or 'sell'
4902
+ :param float [amount]: how much you want to trade in units of the base currency
4903
+ :param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
4904
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4905
+ :param str [params.triggerPrice]: *swap only* the price to trigger a stop order
4906
+ :param str [params.stopLossPrice]: *swap only* the price to trigger a stop-loss order
4907
+ :param str [params.takeProfitPrice]: *swap only* the price to trigger a take-profit order
4908
+ :param str [params.stopLoss.triggerPrice]: *swap only* the price to trigger a preset stop-loss order
4909
+ :param str [params.takeProfit.triggerPrice]: *swap only* the price to trigger a preset take-profit order
4910
+ :param str [params.clientOrderId]: client order id of the order
4911
+ :param int [params.price_type]: *swap only* 1: last price, 2: fair price, default is 1
4912
+ :param int [params.plan_category]: *swap tp/sl only* 1: tp/sl, 2: position tp/sl, default is 1
4913
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
4914
+ """
4915
+ await self.load_markets()
4916
+ market = self.market(symbol)
4917
+ if not market['swap']:
4918
+ raise NotSupported(self.id + ' editOrder() does not support ' + market['type'] + ' markets, only swap markets are supported')
4919
+ stopLossPrice = self.safe_string(params, 'stopLossPrice')
4920
+ takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
4921
+ triggerPrice = self.safe_string_n(params, ['triggerPrice', 'stopPrice', 'trigger_price'])
4922
+ stopLoss = self.safe_dict(params, 'stopLoss', {})
4923
+ takeProfit = self.safe_dict(params, 'takeProfit', {})
4924
+ presetStopLoss = self.safe_string(stopLoss, 'triggerPrice')
4925
+ presetTakeProfit = self.safe_string(takeProfit, 'triggerPrice')
4926
+ isTriggerOrder = triggerPrice is not None
4927
+ isStopLoss = stopLossPrice is not None
4928
+ isTakeProfit = takeProfitPrice is not None
4929
+ isPresetStopLoss = presetStopLoss is not None
4930
+ isPresetTakeProfit = presetTakeProfit is not None
4931
+ isLimitOrder = (type == 'limit')
4932
+ request: dict = {
4933
+ 'symbol': market['id'],
4934
+ }
4935
+ clientOrderId = self.safe_string(params, 'clientOrderId')
4936
+ if clientOrderId is not None:
4937
+ params = self.omit(params, 'clientOrderId')
4938
+ request['client_order_id'] = clientOrderId
4939
+ if id is not None:
4940
+ request['order_id'] = id
4941
+ params = self.omit(params, ['triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'stopLoss', 'takeProfit'])
4942
+ response = None
4943
+ if isTriggerOrder or isStopLoss or isTakeProfit:
4944
+ request['price_type'] = self.safe_integer(params, 'price_type', 1)
4945
+ if price is not None:
4946
+ request['executive_price'] = self.price_to_precision(symbol, price)
4947
+ if isTriggerOrder:
4948
+ request['type'] = type
4949
+ request['trigger_price'] = self.price_to_precision(symbol, triggerPrice)
4950
+ response = await self.privatePostContractPrivateModifyPlanOrder(self.extend(request, params))
4951
+ #
4952
+ # {
4953
+ # "code": 1000,
4954
+ # "message": "Ok",
4955
+ # "data": {
4956
+ # "order_id": "3000023150003503"
4957
+ # },
4958
+ # "trace": "324523453245.108.1734567125596324575"
4959
+ # }
4960
+ #
4961
+ elif isStopLoss or isTakeProfit:
4962
+ request['category'] = type
4963
+ if isStopLoss:
4964
+ request['trigger_price'] = self.price_to_precision(symbol, stopLossPrice)
4965
+ else:
4966
+ request['trigger_price'] = self.price_to_precision(symbol, takeProfitPrice)
4967
+ response = await self.privatePostContractPrivateModifyTpSlOrder(self.extend(request, params))
4968
+ #
4969
+ # {
4970
+ # "code": 1000,
4971
+ # "message": "Ok",
4972
+ # "data": {
4973
+ # "order_id": "3000023150003480"
4974
+ # },
4975
+ # "trace": "23452345.104.1724536582682345459"
4976
+ # }
4977
+ #
4978
+ elif isPresetStopLoss or isPresetTakeProfit:
4979
+ if isPresetStopLoss:
4980
+ request['preset_stop_loss_price_type'] = self.safe_integer(params, 'price_type', 1)
4981
+ request['preset_stop_loss_price'] = self.price_to_precision(symbol, presetStopLoss)
4982
+ else:
4983
+ request['preset_take_profit_price_type'] = self.safe_integer(params, 'price_type', 1)
4984
+ request['preset_take_profit_price'] = self.price_to_precision(symbol, presetTakeProfit)
4985
+ response = await self.privatePostContractPrivateModifyPresetPlanOrder(self.extend(request, params))
4986
+ #
4987
+ # {
4988
+ # "code": 1000,
4989
+ # "message": "Ok",
4990
+ # "data": {
4991
+ # "order_id": "3000023150003496"
4992
+ # },
4993
+ # "trace": "a5c3234534534a836bc476a203.123452.172716624359200197"
4994
+ # }
4995
+ #
4996
+ elif isLimitOrder:
4997
+ request['order_id'] = self.parse_to_int(id) # reparse id self endpoint is the only one requiring it
4998
+ if amount is not None:
4999
+ request['size'] = self.amount_to_precision(symbol, amount)
5000
+ if price is not None:
5001
+ request['price'] = self.price_to_precision(symbol, price)
5002
+ response = await self.privatePostContractPrivateModifyLimitOrder(self.extend(request, params))
5003
+ else:
5004
+ raise NotSupported(self.id + ' editOrder() only supports limit, trigger, stop loss and take profit orders')
5005
+ data = self.safe_dict(response, 'data', {})
5006
+ return self.parse_order(data, market)
5007
+
5008
+ async def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LedgerEntry]:
5009
+ """
5010
+ fetch the history of changes, actions done by the user or operations that altered the balance of the user
5011
+
5012
+ https://developer-pro.bitmart.com/en/futuresv2/#get-transaction-history-keyed
5013
+
5014
+ :param str [code]: unified currency code
5015
+ :param int [since]: timestamp in ms of the earliest ledger entry
5016
+ :param int [limit]: max number of ledger entries to return
5017
+ :param dict [params]: extra parameters specific to the exchange API endpoint
5018
+ :param int [params.until]: timestamp in ms of the latest ledger entry
5019
+ :returns dict[]: a list of `ledger structures <https://docs.ccxt.com/#/?id=ledger>`
5020
+ """
5021
+ await self.load_markets()
5022
+ currency = None
5023
+ if code is not None:
5024
+ currency = self.currency(code)
5025
+ request: dict = {}
5026
+ request, params = self.handle_until_option('end_time', request, params)
5027
+ transactionsRequest = self.fetch_transactions_request(0, None, since, limit, params)
5028
+ response = await self.privateGetContractPrivateTransactionHistory(transactionsRequest)
5029
+ #
5030
+ # {
5031
+ # "code": 1000,
5032
+ # "message": "Ok",
5033
+ # "data": [
5034
+ # {
5035
+ # "time": "1734422402121",
5036
+ # "type": "Funding Fee",
5037
+ # "amount": "-0.00008253",
5038
+ # "asset": "USDT",
5039
+ # "symbol": "LTCUSDT",
5040
+ # "tran_id": "1734422402121",
5041
+ # "flow_type": 3
5042
+ # },
5043
+ # ],
5044
+ # "trace": "4cd11f83c71egfhfgh842790f07241e.23.173442343427772866"
5045
+ # }
5046
+ #
5047
+ data = self.safe_list(response, 'data', [])
5048
+ return self.parse_ledger(data, currency, since, limit)
5049
+
5050
+ def parse_ledger_entry(self, item: dict, currency: Currency = None) -> LedgerEntry:
5051
+ #
5052
+ # {
5053
+ # "time": "1734422402121",
5054
+ # "type": "Funding Fee",
5055
+ # "amount": "-0.00008253",
5056
+ # "asset": "USDT",
5057
+ # "symbol": "LTCUSDT",
5058
+ # "tran_id": "1734422402121",
5059
+ # "flow_type": 3
5060
+ # }
5061
+ #
5062
+ amount = self.safe_string(item, 'amount')
5063
+ direction = None
5064
+ if Precise.string_le(amount, '0'):
5065
+ direction = 'out'
5066
+ amount = Precise.string_mul('-1', amount)
5067
+ else:
5068
+ direction = 'in'
5069
+ currencyId = self.safe_string(item, 'asset')
5070
+ currency = self.safe_currency(currencyId, currency)
5071
+ timestamp = self.safe_integer(item, 'time')
5072
+ type = self.safe_string(item, 'type')
5073
+ return self.safe_ledger_entry({
5074
+ 'info': item,
5075
+ 'id': self.safe_string(item, 'tran_id'),
5076
+ 'direction': direction,
5077
+ 'account': None,
5078
+ 'referenceAccount': None,
5079
+ 'referenceId': self.safe_string(item, 'tradeId'),
5080
+ 'type': self.parse_ledger_entry_type(type),
5081
+ 'currency': currency['code'],
5082
+ 'amount': self.parse_number(amount),
5083
+ 'timestamp': timestamp,
5084
+ 'datetime': self.iso8601(timestamp),
5085
+ 'before': None,
5086
+ 'after': None,
5087
+ 'status': None,
5088
+ 'fee': None,
5089
+ }, currency)
5090
+
5091
+ def parse_ledger_entry_type(self, type):
5092
+ ledgerType: dict = {
5093
+ 'Commission Fee': 'fee',
5094
+ 'Funding Fee': 'fee',
5095
+ 'Realized PNL': 'trade',
5096
+ 'Transfer': 'transfer',
5097
+ 'Liquidation Clearance': 'settlement',
5098
+ }
5099
+ return self.safe_string(ledgerType, type, type)
5100
+
5101
+ def fetch_transactions_request(self, flowType: Int = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
5102
+ request: dict = {}
5103
+ if flowType is not None:
5104
+ request['flow_type'] = flowType
5105
+ market = None
5106
+ if symbol is not None:
5107
+ market = self.market(symbol)
5108
+ request['symbol'] = market['id']
5109
+ if since is not None:
5110
+ request['start_time'] = since
5111
+ if limit is not None:
5112
+ request['page_size'] = limit
5113
+ request, params = self.handle_until_option('end_time', request, params)
5114
+ return self.extend(request, params)
5115
+
5116
+ async def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[FundingHistory]:
5117
+ """
5118
+ fetch the history of funding payments paid and received on self account
5119
+
5120
+ https://developer-pro.bitmart.com/en/futuresv2/#get-transaction-history-keyed
5121
+
5122
+ :param str [symbol]: unified market symbol
5123
+ :param int [since]: the starting timestamp in milliseconds
5124
+ :param int [limit]: the number of entries to return
5125
+ :param dict [params]: extra parameters specific to the exchange API endpoint
5126
+ :param int [params.until]: the latest time in ms to fetch funding history for
5127
+ :returns dict[]: a list of `funding history structures <https://docs.ccxt.com/#/?id=funding-history-structure>`
5128
+ """
5129
+ await self.load_markets()
5130
+ market = None
5131
+ if symbol is not None:
5132
+ market = self.market(symbol)
5133
+ request: dict = {}
5134
+ request, params = self.handle_until_option('end_time', request, params)
5135
+ transactionsRequest = self.fetch_transactions_request(3, symbol, since, limit, params)
5136
+ response = await self.privateGetContractPrivateTransactionHistory(transactionsRequest)
5137
+ #
5138
+ # {
5139
+ # "code": 1000,
5140
+ # "message": "Ok",
5141
+ # "data": [
5142
+ # {
5143
+ # "time": "1734422402121",
5144
+ # "type": "Funding Fee",
5145
+ # "amount": "-0.00008253",
5146
+ # "asset": "USDT",
5147
+ # "symbol": "LTCUSDT",
5148
+ # "tran_id": "1734422402121",
5149
+ # "flow_type": 3
5150
+ # },
5151
+ # ],
5152
+ # "trace": "4cd11f83c71egfhfgh842790f07241e.23.173442343427772866"
5153
+ # }
5154
+ #
5155
+ data = self.safe_list(response, 'data', [])
5156
+ return self.parse_funding_histories(data, market, since, limit)
5157
+
5158
+ def parse_funding_history(self, contract, market: Market = None):
5159
+ #
5160
+ # {
5161
+ # "time": "1734422402121",
5162
+ # "type": "Funding Fee",
5163
+ # "amount": "-0.00008253",
5164
+ # "asset": "USDT",
5165
+ # "symbol": "LTCUSDT",
5166
+ # "tran_id": "1734422402121",
5167
+ # "flow_type": 3
5168
+ # }
5169
+ #
5170
+ marketId = self.safe_string(contract, 'symbol')
5171
+ currencyId = self.safe_string(contract, 'asset')
5172
+ timestamp = self.safe_integer(contract, 'time')
5173
+ return {
5174
+ 'info': contract,
5175
+ 'symbol': self.safe_symbol(marketId, market, None, 'swap'),
5176
+ 'code': self.safe_currency_code(currencyId),
5177
+ 'timestamp': timestamp,
5178
+ 'datetime': self.iso8601(timestamp),
5179
+ 'id': self.safe_string(contract, 'tran_id'),
5180
+ 'amount': self.safe_number(contract, 'amount'),
5181
+ }
5182
+
5183
+ def parse_funding_histories(self, contracts, market=None, since: Int = None, limit: Int = None) -> List[FundingHistory]:
5184
+ result = []
5185
+ for i in range(0, len(contracts)):
5186
+ contract = contracts[i]
5187
+ result.append(self.parse_funding_history(contract, market))
5188
+ sorted = self.sort_by(result, 'timestamp')
5189
+ return self.filter_by_since_limit(sorted, since, limit)
5190
+
5191
+ async def fetch_withdraw_addresses(self, code: str, note=None, networkCode=None, params={}):
5192
+ await self.load_markets()
5193
+ codes = None
5194
+ if code is not None:
5195
+ currency = self.currency(code)
5196
+ code = currency['code']
5197
+ codes = [code]
5198
+ response = await self.privateGetAccountV1WithdrawAddressList(params)
5199
+ #
5200
+ # {
5201
+ # "message": "OK",
5202
+ # "code": 1000,
5203
+ # "trace": "0e6edd79-f77f-4251-abe5-83ba75d06c1a",
5204
+ # "data": {
5205
+ # "list": [
5206
+ # {
5207
+ # "currency": "ETH",
5208
+ # "network": "ETH",
5209
+ # "address": "0x1121",
5210
+ # "memo": "12",
5211
+ # "remark": "12",
5212
+ # "addressType": 0,
5213
+ # "verifyStatus": 0
5214
+ # }
5215
+ # ]
5216
+ # }
5217
+ # }
5218
+ #
5219
+ data = self.safe_dict(response, 'data', {})
5220
+ list = self.safe_list(data, 'list', [])
5221
+ allAddresses = self.parse_deposit_addresses(list, codes, False)
5222
+ addresses = []
5223
+ for i in range(0, len(allAddresses)):
5224
+ address = allAddresses[i]
5225
+ noteMatch = (note is None) or (address['note'] == note)
5226
+ networkMatch = (networkCode is None) or (address['network'] == networkCode)
5227
+ if noteMatch and networkMatch:
5228
+ addresses.append(address)
5229
+ return addresses
5230
+
5231
+ async def set_position_mode(self, hedged: bool, symbol: Str = None, params={}):
5232
+ """
5233
+ set hedged to True or False for a market
5234
+
5235
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-leverage-signed
5236
+
5237
+ :param bool hedged: set to True to use dualSidePosition
5238
+ :param str symbol: not used by bingx setPositionMode()
5239
+ :param dict [params]: extra parameters specific to the exchange API endpoint
5240
+ :returns dict: response from the exchange
5241
+ """
5242
+ await self.load_markets()
5243
+ positionMode = None
5244
+ if hedged:
5245
+ positionMode = 'hedge_mode'
5246
+ else:
5247
+ positionMode = 'one_way_mode'
5248
+ request: dict = {
5249
+ 'position_mode': positionMode,
5250
+ }
5251
+ #
5252
+ # {
5253
+ # "code": 1000,
5254
+ # "trace": "0cc6f4c4-8b8c-4253-8e90-8d3195aa109c",
5255
+ # "message": "Ok",
5256
+ # "data": {
5257
+ # "position_mode":"one_way_mode"
5258
+ # }
5259
+ # }
5260
+ #
5261
+ return await self.privatePostContractPrivateSetPositionMode(self.extend(request, params))
5262
+
5263
+ async def fetch_position_mode(self, symbol: Str = None, params={}):
5264
+ """
5265
+ fetchs the position mode, hedged or one way, hedged for binance is set identically for all linear markets or all inverse markets
5266
+
5267
+ https://developer-pro.bitmart.com/en/futuresv2/#get-position-mode-keyed
5268
+
5269
+ :param str symbol: not used
5270
+ :param dict [params]: extra parameters specific to the exchange API endpoint
5271
+ :returns dict: an object detailing whether the market is in hedged or one-way mode
5272
+ """
5273
+ response = await self.privateGetContractPrivateGetPositionMode(params)
5274
+ #
5275
+ # {
5276
+ # "code": 1000,
5277
+ # "trace": "0cc6f4c4-8b8c-4253-8e90-8d3195aa109c",
5278
+ # "message": "Ok",
5279
+ # "data": {
5280
+ # "position_mode":"one_way_mode"
5281
+ # }
5282
+ # }
5283
+ #
5284
+ data = self.safe_dict(response, 'data')
5285
+ positionMode = self.safe_string(data, 'position_mode')
5286
+ return {
5287
+ 'info': response,
5288
+ 'hedged': (positionMode == 'hedge_mode'),
5289
+ }
5290
+
4358
5291
  def nonce(self):
4359
- return self.milliseconds()
5292
+ return self.milliseconds() - self.options['timeDifference']
4360
5293
 
4361
5294
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
4362
- baseUrl = self.implode_hostname(self.urls['api']['rest'])
5295
+ parts = path.split('/')
5296
+ # to do: refactor api endpoints with spot/swap sections
5297
+ category = self.safe_string(parts, 0, 'spot')
5298
+ market = 'spot' if (category == 'spot' or category == 'account') else 'swap'
5299
+ baseUrl = self.implode_hostname(self.urls['api'][market])
4363
5300
  url = baseUrl + '/' + self.implode_params(path, params)
4364
5301
  query = self.omit(params, self.extract_params(path))
4365
5302
  queryString = ''
@@ -4370,7 +5307,7 @@ class bitmart(Exchange, ImplicitAPI):
4370
5307
  url += '?' + queryString
4371
5308
  if api == 'private':
4372
5309
  self.check_required_credentials()
4373
- timestamp = str(self.milliseconds())
5310
+ timestamp = str(self.nonce())
4374
5311
  brokerId = self.safe_string(self.options, 'brokerId', 'CCXTxBitmart000')
4375
5312
  headers = {
4376
5313
  'X-BM-KEY': self.apiKey,
@@ -4396,6 +5333,7 @@ class bitmart(Exchange, ImplicitAPI):
4396
5333
  # {"message":"Bad Request [from is empty]","code":50000,"trace":"579986f7-c93a-4559-926b-06ba9fa79d76","data":{}}
4397
5334
  # {"message":"Kline size over 500","code":50004,"trace":"d625caa8-e8ca-4bd2-b77c-958776965819","data":{}}
4398
5335
  # {"message":"Balance not enough","code":50020,"trace":"7c709d6a-3292-462c-98c5-32362540aeef","data":{}}
5336
+ # {"code":40012,"message":"You contract account available balance not enough.","trace":"..."}
4399
5337
  #
4400
5338
  # contract
4401
5339
  #
@@ -4407,9 +5345,9 @@ class bitmart(Exchange, ImplicitAPI):
4407
5345
  isErrorCode = (errorCode is not None) and (errorCode != '1000')
4408
5346
  if isErrorCode or isErrorMessage:
4409
5347
  feedback = self.id + ' ' + body
4410
- self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
4411
- self.throw_broadly_matched_exception(self.exceptions['broad'], errorCode, feedback)
4412
5348
  self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
4413
5349
  self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
5350
+ self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
5351
+ self.throw_broadly_matched_exception(self.exceptions['broad'], errorCode, feedback)
4414
5352
  raise ExchangeError(feedback) # unknown message
4415
5353
  return None