bitmart 0.0.116__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 (466) hide show
  1. bitmart/__init__.py +7 -0
  2. bitmart/ccxt/__init__.py +102 -0
  3. bitmart/ccxt/abstract/bitmart.py +117 -0
  4. bitmart/ccxt/async_support/__init__.py +81 -0
  5. bitmart/ccxt/async_support/base/__init__.py +1 -0
  6. bitmart/ccxt/async_support/base/exchange.py +2315 -0
  7. bitmart/ccxt/async_support/base/throttler.py +88 -0
  8. bitmart/ccxt/async_support/base/ws/__init__.py +38 -0
  9. bitmart/ccxt/async_support/base/ws/cache.py +219 -0
  10. bitmart/ccxt/async_support/base/ws/client.py +350 -0
  11. bitmart/ccxt/async_support/base/ws/functions.py +59 -0
  12. bitmart/ccxt/async_support/base/ws/future.py +46 -0
  13. bitmart/ccxt/async_support/base/ws/order_book.py +78 -0
  14. bitmart/ccxt/async_support/base/ws/order_book_side.py +174 -0
  15. bitmart/ccxt/async_support/bitmart.py +5361 -0
  16. bitmart/ccxt/base/__init__.py +27 -0
  17. bitmart/ccxt/base/decimal_to_precision.py +178 -0
  18. bitmart/ccxt/base/errors.py +273 -0
  19. bitmart/ccxt/base/exchange.py +7642 -0
  20. bitmart/ccxt/base/precise.py +297 -0
  21. bitmart/ccxt/base/types.py +619 -0
  22. bitmart/ccxt/bitmart.py +5361 -0
  23. bitmart/ccxt/pro/__init__.py +66 -0
  24. bitmart/ccxt/pro/bitmart.py +1917 -0
  25. bitmart/ccxt/static_dependencies/README.md +1 -0
  26. bitmart/ccxt/static_dependencies/__init__.py +1 -0
  27. bitmart/ccxt/static_dependencies/bip/__init__.py +6 -0
  28. bitmart/ccxt/static_dependencies/bip/addr/P2PKH_addr.py +205 -0
  29. bitmart/ccxt/static_dependencies/bip/addr/__init__.py +5 -0
  30. bitmart/ccxt/static_dependencies/bip/addr/addr_dec_utils.py +125 -0
  31. bitmart/ccxt/static_dependencies/bip/addr/addr_key_validator.py +162 -0
  32. bitmart/ccxt/static_dependencies/bip/addr/iaddr_decoder.py +48 -0
  33. bitmart/ccxt/static_dependencies/bip/addr/iaddr_encoder.py +50 -0
  34. bitmart/ccxt/static_dependencies/bip/base58/__init__.py +3 -0
  35. bitmart/ccxt/static_dependencies/bip/base58/base58.py +207 -0
  36. bitmart/ccxt/static_dependencies/bip/base58/base58_ex.py +25 -0
  37. bitmart/ccxt/static_dependencies/bip/base58/base58_xmr.py +155 -0
  38. bitmart/ccxt/static_dependencies/bip/bech32/__init__.py +4 -0
  39. bitmart/ccxt/static_dependencies/bip/bech32/bch_bech32.py +220 -0
  40. bitmart/ccxt/static_dependencies/bip/bech32/bech32.py +235 -0
  41. bitmart/ccxt/static_dependencies/bip/bech32/bech32_base.py +246 -0
  42. bitmart/ccxt/static_dependencies/bip/bech32/bech32_ex.py +25 -0
  43. bitmart/ccxt/static_dependencies/bip/bech32/segwit_bech32.py +173 -0
  44. bitmart/ccxt/static_dependencies/bip/bip32/__init__.py +14 -0
  45. bitmart/ccxt/static_dependencies/bip/bip32/base/__init__.py +3 -0
  46. bitmart/ccxt/static_dependencies/bip/bip32/base/bip32_base.py +581 -0
  47. bitmart/ccxt/static_dependencies/bip/bip32/base/ibip32_key_derivator.py +83 -0
  48. bitmart/ccxt/static_dependencies/bip/bip32/base/ibip32_mst_key_generator.py +47 -0
  49. bitmart/ccxt/static_dependencies/bip/bip32/bip32_const.py +35 -0
  50. bitmart/ccxt/static_dependencies/bip/bip32/bip32_ex.py +29 -0
  51. bitmart/ccxt/static_dependencies/bip/bip32/bip32_key_data.py +500 -0
  52. bitmart/ccxt/static_dependencies/bip/bip32/bip32_key_net_ver.py +83 -0
  53. bitmart/ccxt/static_dependencies/bip/bip32/bip32_key_ser.py +294 -0
  54. bitmart/ccxt/static_dependencies/bip/bip32/bip32_keys.py +457 -0
  55. bitmart/ccxt/static_dependencies/bip/bip32/bip32_path.py +247 -0
  56. bitmart/ccxt/static_dependencies/bip/bip32/bip32_utils.py +72 -0
  57. bitmart/ccxt/static_dependencies/bip/bip32/kholaw/__init__.py +4 -0
  58. bitmart/ccxt/static_dependencies/bip/bip32/kholaw/bip32_kholaw_ed25519.py +82 -0
  59. bitmart/ccxt/static_dependencies/bip/bip32/kholaw/bip32_kholaw_ed25519_key_derivator.py +118 -0
  60. bitmart/ccxt/static_dependencies/bip/bip32/kholaw/bip32_kholaw_key_derivator_base.py +204 -0
  61. bitmart/ccxt/static_dependencies/bip/bip32/kholaw/bip32_kholaw_mst_key_generator.py +119 -0
  62. bitmart/ccxt/static_dependencies/bip/bip32/slip10/__init__.py +1 -0
  63. bitmart/ccxt/static_dependencies/bip/bip32/slip10/bip32_slip10_key_derivator.py +200 -0
  64. bitmart/ccxt/static_dependencies/bip/bip32/slip10/bip32_slip10_mst_key_generator.py +168 -0
  65. bitmart/ccxt/static_dependencies/bip/bip32/slip10/bip32_slip10_secp256k1.py +82 -0
  66. bitmart/ccxt/static_dependencies/bip/bip44/__init__.py +1 -0
  67. bitmart/ccxt/static_dependencies/bip/bip44/bip44.py +265 -0
  68. bitmart/ccxt/static_dependencies/bip/bip44_base/__init__.py +3 -0
  69. bitmart/ccxt/static_dependencies/bip/bip44_base/bip44_base.py +624 -0
  70. bitmart/ccxt/static_dependencies/bip/bip44_base/bip44_base_ex.py +25 -0
  71. bitmart/ccxt/static_dependencies/bip/bip44_base/bip44_keys.py +225 -0
  72. bitmart/ccxt/static_dependencies/bip/coin_conf/__init__.py +2 -0
  73. bitmart/ccxt/static_dependencies/bip/coin_conf/coin_conf.py +68 -0
  74. bitmart/ccxt/static_dependencies/bip/coin_conf/coins_conf.py +890 -0
  75. bitmart/ccxt/static_dependencies/bip/conf/__init__.py +0 -0
  76. bitmart/ccxt/static_dependencies/bip/conf/bip44/__init__.py +3 -0
  77. bitmart/ccxt/static_dependencies/bip/conf/bip44/bip44_coins.py +126 -0
  78. bitmart/ccxt/static_dependencies/bip/conf/bip44/bip44_conf.py +1360 -0
  79. bitmart/ccxt/static_dependencies/bip/conf/bip44/bip44_conf_getter.py +153 -0
  80. bitmart/ccxt/static_dependencies/bip/conf/bip49/__init__.py +3 -0
  81. bitmart/ccxt/static_dependencies/bip/conf/bip49/bip49_coins.py +53 -0
  82. bitmart/ccxt/static_dependencies/bip/conf/bip49/bip49_conf.py +366 -0
  83. bitmart/ccxt/static_dependencies/bip/conf/bip49/bip49_conf_getter.py +80 -0
  84. bitmart/ccxt/static_dependencies/bip/conf/bip84/__init__.py +3 -0
  85. bitmart/ccxt/static_dependencies/bip/conf/bip84/bip84_coins.py +39 -0
  86. bitmart/ccxt/static_dependencies/bip/conf/bip84/bip84_conf.py +113 -0
  87. bitmart/ccxt/static_dependencies/bip/conf/bip84/bip84_conf_getter.py +66 -0
  88. bitmart/ccxt/static_dependencies/bip/conf/bip86/__init__.py +3 -0
  89. bitmart/ccxt/static_dependencies/bip/conf/bip86/bip86_coins.py +37 -0
  90. bitmart/ccxt/static_dependencies/bip/conf/bip86/bip86_conf.py +83 -0
  91. bitmart/ccxt/static_dependencies/bip/conf/bip86/bip86_conf_getter.py +64 -0
  92. bitmart/ccxt/static_dependencies/bip/conf/common/__init__.py +8 -0
  93. bitmart/ccxt/static_dependencies/bip/conf/common/atom_addr.py +104 -0
  94. bitmart/ccxt/static_dependencies/bip/conf/common/bip_bitcoin_cash_conf.py +106 -0
  95. bitmart/ccxt/static_dependencies/bip/conf/common/bip_coin_conf.py +217 -0
  96. bitmart/ccxt/static_dependencies/bip/conf/common/bip_coins.py +28 -0
  97. bitmart/ccxt/static_dependencies/bip/conf/common/bip_conf_const.py +30 -0
  98. bitmart/ccxt/static_dependencies/bip/conf/common/bip_litecoin_conf.py +121 -0
  99. bitmart/ccxt/static_dependencies/bip/ecc/__init__.py +42 -0
  100. bitmart/ccxt/static_dependencies/bip/ecc/common/__init__.py +0 -0
  101. bitmart/ccxt/static_dependencies/bip/ecc/common/dummy_point.py +219 -0
  102. bitmart/ccxt/static_dependencies/bip/ecc/common/ikeys.py +263 -0
  103. bitmart/ccxt/static_dependencies/bip/ecc/common/ipoint.py +190 -0
  104. bitmart/ccxt/static_dependencies/bip/ecc/conf.py +28 -0
  105. bitmart/ccxt/static_dependencies/bip/ecc/curve/__init__.py +0 -0
  106. bitmart/ccxt/static_dependencies/bip/ecc/curve/elliptic_curve.py +121 -0
  107. bitmart/ccxt/static_dependencies/bip/ecc/curve/elliptic_curve_getter.py +74 -0
  108. bitmart/ccxt/static_dependencies/bip/ecc/curve/elliptic_curve_types.py +37 -0
  109. bitmart/ccxt/static_dependencies/bip/ecc/ecdsa/__init__.py +0 -0
  110. bitmart/ccxt/static_dependencies/bip/ecc/ecdsa/ecdsa_keys.py +36 -0
  111. bitmart/ccxt/static_dependencies/bip/ecc/secp256k1/__init__.py +0 -0
  112. bitmart/ccxt/static_dependencies/bip/ecc/secp256k1/secp256k1.py +36 -0
  113. bitmart/ccxt/static_dependencies/bip/ecc/secp256k1/secp256k1_const.py +59 -0
  114. bitmart/ccxt/static_dependencies/bip/ecc/secp256k1/secp256k1_keys_ecdsa.py +248 -0
  115. bitmart/ccxt/static_dependencies/bip/ecc/secp256k1/secp256k1_point_ecdsa.py +234 -0
  116. bitmart/ccxt/static_dependencies/bip/slip/__init__.py +0 -0
  117. bitmart/ccxt/static_dependencies/bip/slip/slip173/__init__.py +1 -0
  118. bitmart/ccxt/static_dependencies/bip/slip/slip173/slip173.py +60 -0
  119. bitmart/ccxt/static_dependencies/bip/slip/slip32/__init__.py +4 -0
  120. bitmart/ccxt/static_dependencies/bip/slip/slip32/slip32.py +322 -0
  121. bitmart/ccxt/static_dependencies/bip/slip/slip32/slip32_key_net_ver.py +62 -0
  122. bitmart/ccxt/static_dependencies/bip/slip/slip44/__init__.py +1 -0
  123. bitmart/ccxt/static_dependencies/bip/slip/slip44/slip44.py +81 -0
  124. bitmart/ccxt/static_dependencies/bip/utils/__init__.py +0 -0
  125. bitmart/ccxt/static_dependencies/bip/utils/conf/__init__.py +1 -0
  126. bitmart/ccxt/static_dependencies/bip/utils/conf/coin_names.py +59 -0
  127. bitmart/ccxt/static_dependencies/bip/utils/crypto/__init__.py +10 -0
  128. bitmart/ccxt/static_dependencies/bip/utils/crypto/aes_ecb.py +152 -0
  129. bitmart/ccxt/static_dependencies/bip/utils/crypto/blake2.py +191 -0
  130. bitmart/ccxt/static_dependencies/bip/utils/crypto/chacha20_poly1305.py +101 -0
  131. bitmart/ccxt/static_dependencies/bip/utils/crypto/hash160.py +57 -0
  132. bitmart/ccxt/static_dependencies/bip/utils/crypto/hmac.py +118 -0
  133. bitmart/ccxt/static_dependencies/bip/utils/crypto/pbkdf2.py +66 -0
  134. bitmart/ccxt/static_dependencies/bip/utils/crypto/ripemd.py +58 -0
  135. bitmart/ccxt/static_dependencies/bip/utils/crypto/scrypt.py +66 -0
  136. bitmart/ccxt/static_dependencies/bip/utils/crypto/sha2.py +182 -0
  137. bitmart/ccxt/static_dependencies/bip/utils/crypto/sha3.py +99 -0
  138. bitmart/ccxt/static_dependencies/bip/utils/misc/__init__.py +7 -0
  139. bitmart/ccxt/static_dependencies/bip/utils/misc/algo.py +108 -0
  140. bitmart/ccxt/static_dependencies/bip/utils/misc/base32.py +151 -0
  141. bitmart/ccxt/static_dependencies/bip/utils/misc/bit.py +115 -0
  142. bitmart/ccxt/static_dependencies/bip/utils/misc/bytes.py +200 -0
  143. bitmart/ccxt/static_dependencies/bip/utils/misc/data_bytes.py +181 -0
  144. bitmart/ccxt/static_dependencies/bip/utils/misc/integer.py +97 -0
  145. bitmart/ccxt/static_dependencies/bip/utils/misc/string.py +54 -0
  146. bitmart/ccxt/static_dependencies/bip/utils/typing/__init__.py +1 -0
  147. bitmart/ccxt/static_dependencies/bip/utils/typing/literal.py +27 -0
  148. bitmart/ccxt/static_dependencies/bip/wif/__init__.py +1 -0
  149. bitmart/ccxt/static_dependencies/bip/wif/wif.py +144 -0
  150. bitmart/ccxt/static_dependencies/dydx_v4_client/amino/amino_pb2.py +31 -0
  151. bitmart/ccxt/static_dependencies/dydx_v4_client/cosmos/base/v1beta1/coin_pb2.py +47 -0
  152. bitmart/ccxt/static_dependencies/dydx_v4_client/cosmos/crypto/multisig/keys_pb2.py +33 -0
  153. bitmart/ccxt/static_dependencies/dydx_v4_client/cosmos/crypto/multisig/v1beta1/multisig_pb2.py +33 -0
  154. bitmart/ccxt/static_dependencies/dydx_v4_client/cosmos/crypto/secp256k1/keys_pb2.py +34 -0
  155. bitmart/ccxt/static_dependencies/dydx_v4_client/cosmos/msg/v1/msg_pb2.py +27 -0
  156. bitmart/ccxt/static_dependencies/dydx_v4_client/cosmos/tx/signing/v1beta1/signing_pb2.py +38 -0
  157. bitmart/ccxt/static_dependencies/dydx_v4_client/cosmos/tx/v1beta1/tx_pb2.py +75 -0
  158. bitmart/ccxt/static_dependencies/dydx_v4_client/cosmos_proto/cosmos_pb2.py +36 -0
  159. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/accountplus/accountplus_pb2.py +31 -0
  160. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/accountplus/genesis_pb2.py +40 -0
  161. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/accountplus/models_pb2.py +26 -0
  162. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/accountplus/params_pb2.py +29 -0
  163. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/accountplus/query_pb2.py +57 -0
  164. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/accountplus/tx_pb2.py +51 -0
  165. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/block_rate_limit_config_pb2.py +37 -0
  166. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/clob_pair_pb2.py +41 -0
  167. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/equity_tier_limit_config_pb2.py +35 -0
  168. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/finalize_block_pb2.py +27 -0
  169. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/liquidations_config_pb2.py +39 -0
  170. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/liquidations_pb2.py +38 -0
  171. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/matches_pb2.py +55 -0
  172. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/mev_pb2.py +49 -0
  173. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/operation_pb2.py +32 -0
  174. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/order_pb2.py +86 -0
  175. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/order_removals_pb2.py +32 -0
  176. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/process_proposer_matches_events_pb2.py +42 -0
  177. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/query_pb2.py +124 -0
  178. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/streaming_pb2.py +29 -0
  179. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/tx_pb2.py +117 -0
  180. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/sending/genesis_pb2.py +26 -0
  181. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/sending/query_pb2.py +26 -0
  182. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/sending/transfer_pb2.py +61 -0
  183. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/sending/tx_pb2.py +37 -0
  184. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/subaccounts/asset_position_pb2.py +29 -0
  185. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/subaccounts/genesis_pb2.py +30 -0
  186. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/subaccounts/perpetual_position_pb2.py +33 -0
  187. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/subaccounts/query_pb2.py +63 -0
  188. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/subaccounts/streaming_pb2.py +31 -0
  189. bitmart/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/subaccounts/subaccount_pb2.py +33 -0
  190. bitmart/ccxt/static_dependencies/dydx_v4_client/gogoproto/gogo_pb2.py +102 -0
  191. bitmart/ccxt/static_dependencies/dydx_v4_client/registry.py +38 -0
  192. bitmart/ccxt/static_dependencies/ecdsa/__init__.py +14 -0
  193. bitmart/ccxt/static_dependencies/ecdsa/_version.py +520 -0
  194. bitmart/ccxt/static_dependencies/ecdsa/curves.py +56 -0
  195. bitmart/ccxt/static_dependencies/ecdsa/der.py +221 -0
  196. bitmart/ccxt/static_dependencies/ecdsa/ecdsa.py +310 -0
  197. bitmart/ccxt/static_dependencies/ecdsa/ellipticcurve.py +1039 -0
  198. bitmart/ccxt/static_dependencies/ecdsa/keys.py +343 -0
  199. bitmart/ccxt/static_dependencies/ecdsa/numbertheory.py +531 -0
  200. bitmart/ccxt/static_dependencies/ecdsa/rfc6979.py +100 -0
  201. bitmart/ccxt/static_dependencies/ecdsa/util.py +266 -0
  202. bitmart/ccxt/static_dependencies/ethereum/__init__.py +7 -0
  203. bitmart/ccxt/static_dependencies/ethereum/abi/__init__.py +16 -0
  204. bitmart/ccxt/static_dependencies/ethereum/abi/abi.py +19 -0
  205. bitmart/ccxt/static_dependencies/ethereum/abi/base.py +152 -0
  206. bitmart/ccxt/static_dependencies/ethereum/abi/codec.py +217 -0
  207. bitmart/ccxt/static_dependencies/ethereum/abi/constants.py +3 -0
  208. bitmart/ccxt/static_dependencies/ethereum/abi/decoding.py +565 -0
  209. bitmart/ccxt/static_dependencies/ethereum/abi/encoding.py +720 -0
  210. bitmart/ccxt/static_dependencies/ethereum/abi/exceptions.py +139 -0
  211. bitmart/ccxt/static_dependencies/ethereum/abi/grammar.py +443 -0
  212. bitmart/ccxt/static_dependencies/ethereum/abi/packed.py +13 -0
  213. bitmart/ccxt/static_dependencies/ethereum/abi/py.typed +0 -0
  214. bitmart/ccxt/static_dependencies/ethereum/abi/registry.py +643 -0
  215. bitmart/ccxt/static_dependencies/ethereum/abi/tools/__init__.py +3 -0
  216. bitmart/ccxt/static_dependencies/ethereum/abi/tools/_strategies.py +230 -0
  217. bitmart/ccxt/static_dependencies/ethereum/abi/utils/__init__.py +0 -0
  218. bitmart/ccxt/static_dependencies/ethereum/abi/utils/numeric.py +83 -0
  219. bitmart/ccxt/static_dependencies/ethereum/abi/utils/padding.py +27 -0
  220. bitmart/ccxt/static_dependencies/ethereum/abi/utils/string.py +19 -0
  221. bitmart/ccxt/static_dependencies/ethereum/account/__init__.py +3 -0
  222. bitmart/ccxt/static_dependencies/ethereum/account/encode_typed_data/__init__.py +4 -0
  223. bitmart/ccxt/static_dependencies/ethereum/account/encode_typed_data/encoding_and_hashing.py +239 -0
  224. bitmart/ccxt/static_dependencies/ethereum/account/encode_typed_data/helpers.py +40 -0
  225. bitmart/ccxt/static_dependencies/ethereum/account/messages.py +263 -0
  226. bitmart/ccxt/static_dependencies/ethereum/account/py.typed +0 -0
  227. bitmart/ccxt/static_dependencies/ethereum/hexbytes/__init__.py +5 -0
  228. bitmart/ccxt/static_dependencies/ethereum/hexbytes/_utils.py +54 -0
  229. bitmart/ccxt/static_dependencies/ethereum/hexbytes/main.py +65 -0
  230. bitmart/ccxt/static_dependencies/ethereum/hexbytes/py.typed +0 -0
  231. bitmart/ccxt/static_dependencies/ethereum/typing/__init__.py +63 -0
  232. bitmart/ccxt/static_dependencies/ethereum/typing/abi.py +6 -0
  233. bitmart/ccxt/static_dependencies/ethereum/typing/bls.py +7 -0
  234. bitmart/ccxt/static_dependencies/ethereum/typing/discovery.py +5 -0
  235. bitmart/ccxt/static_dependencies/ethereum/typing/encoding.py +7 -0
  236. bitmart/ccxt/static_dependencies/ethereum/typing/enums.py +17 -0
  237. bitmart/ccxt/static_dependencies/ethereum/typing/ethpm.py +9 -0
  238. bitmart/ccxt/static_dependencies/ethereum/typing/evm.py +20 -0
  239. bitmart/ccxt/static_dependencies/ethereum/typing/networks.py +1122 -0
  240. bitmart/ccxt/static_dependencies/ethereum/typing/py.typed +0 -0
  241. bitmart/ccxt/static_dependencies/ethereum/utils/__init__.py +115 -0
  242. bitmart/ccxt/static_dependencies/ethereum/utils/abi.py +72 -0
  243. bitmart/ccxt/static_dependencies/ethereum/utils/address.py +171 -0
  244. bitmart/ccxt/static_dependencies/ethereum/utils/applicators.py +151 -0
  245. bitmart/ccxt/static_dependencies/ethereum/utils/conversions.py +190 -0
  246. bitmart/ccxt/static_dependencies/ethereum/utils/currency.py +107 -0
  247. bitmart/ccxt/static_dependencies/ethereum/utils/curried/__init__.py +269 -0
  248. bitmart/ccxt/static_dependencies/ethereum/utils/debug.py +20 -0
  249. bitmart/ccxt/static_dependencies/ethereum/utils/decorators.py +132 -0
  250. bitmart/ccxt/static_dependencies/ethereum/utils/encoding.py +6 -0
  251. bitmart/ccxt/static_dependencies/ethereum/utils/exceptions.py +4 -0
  252. bitmart/ccxt/static_dependencies/ethereum/utils/functional.py +75 -0
  253. bitmart/ccxt/static_dependencies/ethereum/utils/hexadecimal.py +74 -0
  254. bitmart/ccxt/static_dependencies/ethereum/utils/humanize.py +188 -0
  255. bitmart/ccxt/static_dependencies/ethereum/utils/logging.py +159 -0
  256. bitmart/ccxt/static_dependencies/ethereum/utils/module_loading.py +31 -0
  257. bitmart/ccxt/static_dependencies/ethereum/utils/numeric.py +43 -0
  258. bitmart/ccxt/static_dependencies/ethereum/utils/py.typed +0 -0
  259. bitmart/ccxt/static_dependencies/ethereum/utils/toolz.py +76 -0
  260. bitmart/ccxt/static_dependencies/ethereum/utils/types.py +54 -0
  261. bitmart/ccxt/static_dependencies/ethereum/utils/typing/__init__.py +18 -0
  262. bitmart/ccxt/static_dependencies/ethereum/utils/typing/misc.py +14 -0
  263. bitmart/ccxt/static_dependencies/ethereum/utils/units.py +31 -0
  264. bitmart/ccxt/static_dependencies/keccak/__init__.py +3 -0
  265. bitmart/ccxt/static_dependencies/keccak/keccak.py +197 -0
  266. bitmart/ccxt/static_dependencies/lark/__init__.py +38 -0
  267. bitmart/ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  268. bitmart/ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  269. bitmart/ccxt/static_dependencies/lark/ast_utils.py +59 -0
  270. bitmart/ccxt/static_dependencies/lark/common.py +86 -0
  271. bitmart/ccxt/static_dependencies/lark/exceptions.py +292 -0
  272. bitmart/ccxt/static_dependencies/lark/grammar.py +130 -0
  273. bitmart/ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  274. bitmart/ccxt/static_dependencies/lark/grammars/common.lark +59 -0
  275. bitmart/ccxt/static_dependencies/lark/grammars/lark.lark +62 -0
  276. bitmart/ccxt/static_dependencies/lark/grammars/python.lark +302 -0
  277. bitmart/ccxt/static_dependencies/lark/grammars/unicode.lark +7 -0
  278. bitmart/ccxt/static_dependencies/lark/indenter.py +143 -0
  279. bitmart/ccxt/static_dependencies/lark/lark.py +658 -0
  280. bitmart/ccxt/static_dependencies/lark/lexer.py +678 -0
  281. bitmart/ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  282. bitmart/ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  283. bitmart/ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  284. bitmart/ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  285. bitmart/ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  286. bitmart/ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  287. bitmart/ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  288. bitmart/ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  289. bitmart/ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  290. bitmart/ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  291. bitmart/ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  292. bitmart/ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  293. bitmart/ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  294. bitmart/ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  295. bitmart/ccxt/static_dependencies/lark/py.typed +0 -0
  296. bitmart/ccxt/static_dependencies/lark/reconstruct.py +107 -0
  297. bitmart/ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  298. bitmart/ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  299. bitmart/ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  300. bitmart/ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  301. bitmart/ccxt/static_dependencies/lark/tree.py +267 -0
  302. bitmart/ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  303. bitmart/ccxt/static_dependencies/lark/tree_templates.py +180 -0
  304. bitmart/ccxt/static_dependencies/lark/utils.py +343 -0
  305. bitmart/ccxt/static_dependencies/lark/visitors.py +596 -0
  306. bitmart/ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  307. bitmart/ccxt/static_dependencies/marshmallow/base.py +65 -0
  308. bitmart/ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  309. bitmart/ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  310. bitmart/ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  311. bitmart/ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  312. bitmart/ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  313. bitmart/ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  314. bitmart/ccxt/static_dependencies/marshmallow/py.typed +0 -0
  315. bitmart/ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  316. bitmart/ccxt/static_dependencies/marshmallow/types.py +12 -0
  317. bitmart/ccxt/static_dependencies/marshmallow/utils.py +378 -0
  318. bitmart/ccxt/static_dependencies/marshmallow/validate.py +678 -0
  319. bitmart/ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  320. bitmart/ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  321. bitmart/ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  322. bitmart/ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  323. bitmart/ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  324. bitmart/ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  325. bitmart/ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  326. bitmart/ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  327. bitmart/ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  328. bitmart/ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  329. bitmart/ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  330. bitmart/ccxt/static_dependencies/mnemonic/__init__.py +4 -0
  331. bitmart/ccxt/static_dependencies/mnemonic/mnemonic.py +282 -0
  332. bitmart/ccxt/static_dependencies/mnemonic/py.typed +1 -0
  333. bitmart/ccxt/static_dependencies/mnemonic/wordlist/chinese_simplified.txt +2048 -0
  334. bitmart/ccxt/static_dependencies/mnemonic/wordlist/chinese_traditional.txt +2048 -0
  335. bitmart/ccxt/static_dependencies/mnemonic/wordlist/czech.txt +2048 -0
  336. bitmart/ccxt/static_dependencies/mnemonic/wordlist/english.txt +2048 -0
  337. bitmart/ccxt/static_dependencies/mnemonic/wordlist/french.txt +2048 -0
  338. bitmart/ccxt/static_dependencies/mnemonic/wordlist/italian.txt +2048 -0
  339. bitmart/ccxt/static_dependencies/mnemonic/wordlist/japanese.txt +2048 -0
  340. bitmart/ccxt/static_dependencies/mnemonic/wordlist/korean.txt +2048 -0
  341. bitmart/ccxt/static_dependencies/mnemonic/wordlist/portuguese.txt +2048 -0
  342. bitmart/ccxt/static_dependencies/mnemonic/wordlist/russian.txt +2048 -0
  343. bitmart/ccxt/static_dependencies/mnemonic/wordlist/spanish.txt +2048 -0
  344. bitmart/ccxt/static_dependencies/mnemonic/wordlist/turkish.txt +2048 -0
  345. bitmart/ccxt/static_dependencies/msgpack/__init__.py +55 -0
  346. bitmart/ccxt/static_dependencies/msgpack/_cmsgpack.pyx +11 -0
  347. bitmart/ccxt/static_dependencies/msgpack/_packer.pyx +374 -0
  348. bitmart/ccxt/static_dependencies/msgpack/_unpacker.pyx +547 -0
  349. bitmart/ccxt/static_dependencies/msgpack/buff_converter.h +8 -0
  350. bitmart/ccxt/static_dependencies/msgpack/exceptions.py +48 -0
  351. bitmart/ccxt/static_dependencies/msgpack/ext.py +168 -0
  352. bitmart/ccxt/static_dependencies/msgpack/fallback.py +951 -0
  353. bitmart/ccxt/static_dependencies/msgpack/pack.h +89 -0
  354. bitmart/ccxt/static_dependencies/msgpack/pack_template.h +820 -0
  355. bitmart/ccxt/static_dependencies/msgpack/sysdep.h +194 -0
  356. bitmart/ccxt/static_dependencies/msgpack/unpack.h +391 -0
  357. bitmart/ccxt/static_dependencies/msgpack/unpack_define.h +95 -0
  358. bitmart/ccxt/static_dependencies/msgpack/unpack_template.h +464 -0
  359. bitmart/ccxt/static_dependencies/parsimonious/__init__.py +10 -0
  360. bitmart/ccxt/static_dependencies/parsimonious/exceptions.py +105 -0
  361. bitmart/ccxt/static_dependencies/parsimonious/expressions.py +479 -0
  362. bitmart/ccxt/static_dependencies/parsimonious/grammar.py +487 -0
  363. bitmart/ccxt/static_dependencies/parsimonious/nodes.py +325 -0
  364. bitmart/ccxt/static_dependencies/parsimonious/utils.py +40 -0
  365. bitmart/ccxt/static_dependencies/starknet/__init__.py +0 -0
  366. bitmart/ccxt/static_dependencies/starknet/abi/v0/__init__.py +2 -0
  367. bitmart/ccxt/static_dependencies/starknet/abi/v0/model.py +44 -0
  368. bitmart/ccxt/static_dependencies/starknet/abi/v0/parser.py +216 -0
  369. bitmart/ccxt/static_dependencies/starknet/abi/v0/schemas.py +72 -0
  370. bitmart/ccxt/static_dependencies/starknet/abi/v0/shape.py +63 -0
  371. bitmart/ccxt/static_dependencies/starknet/abi/v1/__init__.py +2 -0
  372. bitmart/ccxt/static_dependencies/starknet/abi/v1/core_structures.json +14 -0
  373. bitmart/ccxt/static_dependencies/starknet/abi/v1/model.py +39 -0
  374. bitmart/ccxt/static_dependencies/starknet/abi/v1/parser.py +220 -0
  375. bitmart/ccxt/static_dependencies/starknet/abi/v1/parser_transformer.py +179 -0
  376. bitmart/ccxt/static_dependencies/starknet/abi/v1/schemas.py +66 -0
  377. bitmart/ccxt/static_dependencies/starknet/abi/v1/shape.py +47 -0
  378. bitmart/ccxt/static_dependencies/starknet/abi/v2/__init__.py +2 -0
  379. bitmart/ccxt/static_dependencies/starknet/abi/v2/model.py +89 -0
  380. bitmart/ccxt/static_dependencies/starknet/abi/v2/parser.py +293 -0
  381. bitmart/ccxt/static_dependencies/starknet/abi/v2/parser_transformer.py +192 -0
  382. bitmart/ccxt/static_dependencies/starknet/abi/v2/schemas.py +132 -0
  383. bitmart/ccxt/static_dependencies/starknet/abi/v2/shape.py +107 -0
  384. bitmart/ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  385. bitmart/ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  386. bitmart/ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  387. bitmart/ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  388. bitmart/ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  389. bitmart/ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  390. bitmart/ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  391. bitmart/ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  392. bitmart/ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  393. bitmart/ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  394. bitmart/ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  395. bitmart/ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  396. bitmart/ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  397. bitmart/ccxt/static_dependencies/starknet/common.py +15 -0
  398. bitmart/ccxt/static_dependencies/starknet/constants.py +39 -0
  399. bitmart/ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  400. bitmart/ccxt/static_dependencies/starknet/hash/address.py +79 -0
  401. bitmart/ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  402. bitmart/ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  403. bitmart/ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  404. bitmart/ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  405. bitmart/ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  406. bitmart/ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  407. bitmart/ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  408. bitmart/ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  409. bitmart/ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  410. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  411. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  412. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  413. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  414. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  415. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  416. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  417. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  418. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  419. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  420. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  421. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  422. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  423. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  424. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  425. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  426. bitmart/ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  427. bitmart/ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  428. bitmart/ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  429. bitmart/ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  430. bitmart/ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  431. bitmart/ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  432. bitmart/ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  433. bitmart/ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  434. bitmart/ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  435. bitmart/ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  436. bitmart/ccxt/static_dependencies/starkware/__init__.py +0 -0
  437. bitmart/ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  438. bitmart/ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  439. bitmart/ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  440. bitmart/ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  441. bitmart/ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  442. bitmart/ccxt/static_dependencies/sympy/__init__.py +0 -0
  443. bitmart/ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  444. bitmart/ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  445. bitmart/ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  446. bitmart/ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  447. bitmart/ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  448. bitmart/ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  449. bitmart/ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  450. bitmart/ccxt/static_dependencies/toolz/__init__.py +26 -0
  451. bitmart/ccxt/static_dependencies/toolz/_signatures.py +784 -0
  452. bitmart/ccxt/static_dependencies/toolz/_version.py +520 -0
  453. bitmart/ccxt/static_dependencies/toolz/compatibility.py +30 -0
  454. bitmart/ccxt/static_dependencies/toolz/curried/__init__.py +101 -0
  455. bitmart/ccxt/static_dependencies/toolz/curried/exceptions.py +22 -0
  456. bitmart/ccxt/static_dependencies/toolz/curried/operator.py +22 -0
  457. bitmart/ccxt/static_dependencies/toolz/dicttoolz.py +339 -0
  458. bitmart/ccxt/static_dependencies/toolz/functoolz.py +1049 -0
  459. bitmart/ccxt/static_dependencies/toolz/itertoolz.py +1057 -0
  460. bitmart/ccxt/static_dependencies/toolz/recipes.py +46 -0
  461. bitmart/ccxt/static_dependencies/toolz/utils.py +9 -0
  462. bitmart/ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  463. bitmart/ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  464. bitmart-0.0.116.dist-info/METADATA +342 -0
  465. bitmart-0.0.116.dist-info/RECORD +466 -0
  466. bitmart-0.0.116.dist-info/WHEEL +4 -0
@@ -0,0 +1,1917 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+
6
+ import ccxt.async_support
7
+ from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
8
+ from ccxt.async_support.base.ws.order_book_side import Asks, Bids
9
+ import hashlib
10
+ from ccxt.base.types import Any, Balances, Bool, Int, Market, Order, OrderBook, Position, Str, Strings, Ticker, Tickers, Trade
11
+ from ccxt.async_support.base.ws.client import Client
12
+ from typing import List
13
+ from ccxt.base.errors import ExchangeError
14
+ from ccxt.base.errors import AuthenticationError
15
+ from ccxt.base.errors import NotSupported
16
+
17
+
18
+ from ccxt.async_support import bitmart as bitmartAsync
19
+
20
+
21
+ class bitmart(bitmartAsync):
22
+
23
+ def describe(self) -> Any:
24
+ return self.deep_extend(super(bitmart, self).describe(), {
25
+ 'has': {
26
+ 'createOrderWs': False,
27
+ 'editOrderWs': False,
28
+ 'fetchOpenOrdersWs': False,
29
+ 'fetchOrderWs': False,
30
+ 'cancelOrderWs': False,
31
+ 'cancelOrdersWs': False,
32
+ 'cancelAllOrdersWs': False,
33
+ 'ws': True,
34
+ 'watchBalance': True,
35
+ 'watchTicker': True,
36
+ 'watchTickers': True,
37
+ 'watchBidsAsks': True,
38
+ 'watchOrderBook': True,
39
+ 'watchOrderBookForSymbols': True,
40
+ 'watchOrders': True,
41
+ 'watchTrades': True,
42
+ 'watchTradesForSymbols': True,
43
+ 'watchOHLCV': True,
44
+ 'watchPosition': 'emulated',
45
+ 'watchPositions': True,
46
+ 'unWatchBidsAsks': False, # the same channel
47
+ 'unWatchOHLCV': True,
48
+ 'unWatchOrderBook': True,
49
+ 'unWatchOrderBookForSymbols': True,
50
+ 'unWatchOrders': True,
51
+ 'unWatchPositions': True,
52
+ 'unWatchTicker': True,
53
+ 'unWatchTickers': True,
54
+ 'unWatchTrades': True,
55
+ 'unWatchTradesForSymbols': True,
56
+ },
57
+ 'urls': {
58
+ 'api': {
59
+ 'ws': {
60
+ 'spot': {
61
+ 'public': 'wss://ws-manager-compress.{hostname}/api?protocol=1.1',
62
+ 'private': 'wss://ws-manager-compress.{hostname}/user?protocol=1.1',
63
+ },
64
+ 'swap': {
65
+ 'public': 'wss://openapi-ws-v2.{hostname}/api?protocol=1.1',
66
+ 'private': 'wss://openapi-ws-v2.{hostname}/user?protocol=1.1',
67
+ },
68
+ },
69
+ },
70
+ },
71
+ 'options': {
72
+ 'defaultType': 'spot',
73
+ 'watchBalance': {
74
+ 'fetchBalanceSnapshot': True, # or False
75
+ 'awaitBalanceSnapshot': False, # whether to wait for the balance snapshot before providing updates
76
+ },
77
+ #
78
+ # orderbook channels can have:
79
+ # - 'depth5', 'depth20', 'depth50' # these endpoints emit full Orderbooks once in every 500ms
80
+ # - 'depth/increase100' # self endpoint is preferred, because it emits once in 100ms. however, when self value is chosen, it only affects spot-market, but contracts markets automatically `depth50` will be being used
81
+ 'watchOrderBook': {
82
+ 'depth': 'depth/increase100',
83
+ },
84
+ 'watchOrderBookForSymbols': {
85
+ 'depth': 'depth/increase100',
86
+ },
87
+ 'watchTrades': {
88
+ 'ignoreDuplicates': True,
89
+ },
90
+ 'ws': {
91
+ 'inflate': True,
92
+ },
93
+ 'timeframes': {
94
+ '1m': '1m',
95
+ '3m': '3m',
96
+ '5m': '5m',
97
+ '15m': '15m',
98
+ '30m': '30m',
99
+ '45m': '45m',
100
+ '1h': '1H',
101
+ '2h': '2H',
102
+ '3h': '3H',
103
+ '4h': '4H',
104
+ '1d': '1D',
105
+ '1w': '1W',
106
+ '1M': '1M',
107
+ },
108
+ },
109
+ 'streaming': {
110
+ 'keepAlive': 15000,
111
+ },
112
+ })
113
+
114
+ async def subscribe(self, channel, symbol, type, params={}):
115
+ market = self.market(symbol)
116
+ url = self.implode_hostname(self.urls['api']['ws'][type]['public'])
117
+ request = {}
118
+ messageHash = None
119
+ unsubscribe = self.safe_bool(params, 'unsubscribe', False)
120
+ prefix = ''
121
+ requestOp = 'subscribe'
122
+ if unsubscribe:
123
+ params = self.omit(params, 'unsubscribe')
124
+ prefix = 'unsubscribe::'
125
+ requestOp = 'unsubscribe'
126
+ if type == 'spot':
127
+ messageHash = 'spot/' + channel + ':' + market['id']
128
+ request = {
129
+ 'op': requestOp,
130
+ 'args': [messageHash],
131
+ }
132
+ else:
133
+ messageHash = 'futures/' + channel + ':' + market['id']
134
+ speed = self.safe_string(params, 'speed')
135
+ if speed is not None:
136
+ params = self.omit(params, 'speed')
137
+ messageHash += ':' + speed
138
+ request = {
139
+ 'action': requestOp,
140
+ 'args': [messageHash],
141
+ }
142
+ messageHash = prefix + messageHash
143
+ return await self.watch(url, messageHash, self.deep_extend(request, params), messageHash)
144
+
145
+ async def subscribe_multiple(self, channel: str, type: str, symbols: Strings = None, params={}):
146
+ symbols = self.market_symbols(symbols, type, False, True)
147
+ url = self.implode_hostname(self.urls['api']['ws'][type]['public'])
148
+ channelType = 'spot' if (type == 'spot') else 'futures'
149
+ actionType = 'op' if (type == 'spot') else 'action'
150
+ rawSubscriptions = []
151
+ messageHashes = []
152
+ subHashes = []
153
+ unsubscribe = self.safe_bool(params, 'unsubscribe', False)
154
+ prefix = ''
155
+ requestOp = 'subscribe'
156
+ if unsubscribe:
157
+ params = self.omit(params, 'unsubscribe')
158
+ prefix = 'unsubscribe::'
159
+ requestOp = 'unsubscribe'
160
+ for i in range(0, len(symbols)):
161
+ market = self.market(symbols[i])
162
+ message = channelType + '/' + channel + ':' + market['id']
163
+ subHash = prefix + message
164
+ messageHash = prefix + channel + ':' + market['symbol']
165
+ rawSubscriptions.append(message)
166
+ subHashes.append(subHash)
167
+ messageHashes.append(messageHash)
168
+ # exclusion, futures "tickers" need one generic request for all symbols
169
+ # if (type != 'spot') and (channel == 'ticker'):
170
+ # rawSubscriptions = [channelType + '/' + channel]
171
+ # }
172
+ # Exchange update from 2025-02-11 supports subscription by trading pair for swap
173
+ request: dict = {
174
+ 'args': rawSubscriptions,
175
+ }
176
+ request[actionType] = requestOp
177
+ return await self.watch_multiple(url, messageHashes, self.deep_extend(request, params), subHashes)
178
+
179
+ async def watch_balance(self, params={}) -> Balances:
180
+ """
181
+
182
+ https://developer-pro.bitmart.com/en/spot/#private-balance-change
183
+ https://developer-pro.bitmart.com/en/futuresv2/#private-assets-channel
184
+
185
+ watch balance and get the amount of funds available for trading or funds locked in orders
186
+ :param dict [params]: extra parameters specific to the exchange API endpoint
187
+ :returns dict: a `balance structure <https://docs.ccxt.com/?id=balance-structure>`
188
+ """
189
+ await self.load_markets()
190
+ type = 'spot'
191
+ type, params = self.handle_market_type_and_params('watchBalance', None, params)
192
+ await self.authenticate(type, params)
193
+ request = {}
194
+ if type == 'spot':
195
+ request = {
196
+ 'op': 'subscribe',
197
+ 'args': ['spot/user/balance:BALANCE_UPDATE'],
198
+ }
199
+ else:
200
+ request = {
201
+ 'action': 'subscribe',
202
+ 'args': ['futures/asset:USDT', 'futures/asset:BTC', 'futures/asset:ETH'],
203
+ }
204
+ messageHash = 'balance:' + type
205
+ url = self.implode_hostname(self.urls['api']['ws'][type]['private'])
206
+ client = self.client(url)
207
+ self.set_balance_cache(client, type, messageHash)
208
+ fetchBalanceSnapshot = None
209
+ awaitBalanceSnapshot = None
210
+ fetchBalanceSnapshot, params = self.handle_option_and_params(params, 'watchBalance', 'fetchBalanceSnapshot', True)
211
+ awaitBalanceSnapshot, params = self.handle_option_and_params(params, 'watchBalance', 'awaitBalanceSnapshot', False)
212
+ if fetchBalanceSnapshot and awaitBalanceSnapshot:
213
+ await client.future(type + ':fetchBalanceSnapshot')
214
+ return await self.watch(url, messageHash, self.deep_extend(request, params), messageHash)
215
+
216
+ def set_balance_cache(self, client: Client, type, subscribeHash):
217
+ if subscribeHash in client.subscriptions:
218
+ return
219
+ options = self.safe_dict(self.options, 'watchBalance')
220
+ snapshot = self.safe_bool(options, 'fetchBalanceSnapshot', True)
221
+ if snapshot:
222
+ messageHash = type + ':' + 'fetchBalanceSnapshot'
223
+ if not (messageHash in client.futures):
224
+ client.future(messageHash)
225
+ self.spawn(self.load_balance_snapshot, client, messageHash, type)
226
+ self.balance[type] = {}
227
+ # without self comment, transpilation breaks for some reason...
228
+
229
+ async def load_balance_snapshot(self, client, messageHash, type):
230
+ response = await self.fetch_balance({'type': type})
231
+ self.balance[type] = self.extend(response, self.safe_value(self.balance, type, {}))
232
+ # don't remove the future from the .futures cache
233
+ if messageHash in client.futures:
234
+ future = client.futures[messageHash]
235
+ future.resolve()
236
+ client.resolve(self.balance[type], 'balance:' + type)
237
+
238
+ def handle_balance(self, client: Client, message):
239
+ #
240
+ # spot
241
+ # {
242
+ # "data":[
243
+ # {
244
+ # "balance_details":[
245
+ # {
246
+ # "av_bal":"0.206000000000000000000000000000",
247
+ # "ccy":"LTC",
248
+ # "fz_bal":"0.100000000000000000000000000000"
249
+ # }
250
+ # ],
251
+ # "event_time":"1701632345416",
252
+ # "event_type":"TRANSACTION_COMPLETED"
253
+ # }
254
+ # ],
255
+ # "table":"spot/user/balance"
256
+ # }
257
+ # swap
258
+ # {
259
+ # group: 'futures/asset:USDT',
260
+ # data: {
261
+ # currency: 'USDT',
262
+ # available_balance: '37.19688649135',
263
+ # position_deposit: '0.788687546',
264
+ # frozen_balance: '0'
265
+ # }
266
+ # }
267
+ #
268
+ channel = self.safe_string_2(message, 'table', 'group')
269
+ data = self.safe_value(message, 'data')
270
+ if data is None:
271
+ return
272
+ isSpot = (channel.find('spot') >= 0)
273
+ type = 'spot' if isSpot else 'swap'
274
+ self.balance[type]['info'] = message
275
+ if isSpot:
276
+ if not isinstance(data, list):
277
+ return
278
+ for i in range(0, len(data)):
279
+ timestamp = self.safe_integer(message, 'event_time')
280
+ self.balance[type]['timestamp'] = timestamp
281
+ self.balance[type]['datetime'] = self.iso8601(timestamp)
282
+ balanceDetails = self.safe_list(data[i], 'balance_details', [])
283
+ for ii in range(0, len(balanceDetails)):
284
+ rawBalance = balanceDetails[i]
285
+ account = self.account()
286
+ currencyId = self.safe_string(rawBalance, 'ccy')
287
+ code = self.safe_currency_code(currencyId)
288
+ account['free'] = self.safe_string(rawBalance, 'av_bal')
289
+ account['used'] = self.safe_string(rawBalance, 'fz_bal')
290
+ self.balance[type][code] = account
291
+ else:
292
+ currencyId = self.safe_string(data, 'currency')
293
+ code = self.safe_currency_code(currencyId)
294
+ account = self.account()
295
+ account['free'] = self.safe_string(data, 'available_balance')
296
+ account['used'] = self.safe_string(data, 'frozen_balance')
297
+ self.balance[type][code] = account
298
+ self.balance[type] = self.safe_balance(self.balance[type])
299
+ messageHash = 'balance:' + type
300
+ client.resolve(self.balance[type], messageHash)
301
+
302
+ async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
303
+ """
304
+
305
+ https://developer-pro.bitmart.com/en/spot/#public-trade-channel
306
+ https://developer-pro.bitmart.com/en/futuresv2/#public-trade-channel
307
+
308
+ get the list of most recent trades for a particular symbol
309
+ :param str symbol: unified symbol of the market to fetch trades for
310
+ :param int [since]: timestamp in ms of the earliest trade to fetch
311
+ :param int [limit]: the maximum amount of trades to fetch
312
+ :param dict [params]: extra parameters specific to the exchange API endpoint
313
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/?id=public-trades>`
314
+ """
315
+ return await self.watch_trades_for_symbols([symbol], since, limit, params)
316
+
317
+ async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
318
+ """
319
+
320
+ https://developer-pro.bitmart.com/en/spot/#public-trade-channel
321
+ https://developer-pro.bitmart.com/en/futuresv2/#public-trade-channel
322
+
323
+ get the list of most recent trades for a list of symbols
324
+ :param str[] symbols: unified symbol of the market to fetch trades for
325
+ :param int [since]: timestamp in ms of the earliest trade to fetch
326
+ :param int [limit]: the maximum amount of trades to fetch
327
+ :param dict [params]: extra parameters specific to the exchange API endpoint
328
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/?id=public-trades>`
329
+ """
330
+ await self.load_markets()
331
+ marketType = None
332
+ symbols, marketType, params = self.get_params_for_multiple_sub('watchTradesForSymbols', symbols, limit, params)
333
+ channelName = 'trade'
334
+ trades = await self.subscribe_multiple(channelName, marketType, symbols, params)
335
+ if self.newUpdates:
336
+ first = self.safe_dict(trades, 0)
337
+ tradeSymbol = self.safe_string(first, 'symbol')
338
+ limit = trades.getLimit(tradeSymbol, limit)
339
+ result = self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
340
+ if self.handle_option('watchTrades', 'ignoreDuplicates', True):
341
+ filtered = self.remove_repeated_trades_from_array(result)
342
+ filtered = self.sort_by(filtered, 'timestamp')
343
+ return filtered
344
+ return result
345
+
346
+ async def un_watch_trades(self, symbol: str, params={}) -> Any:
347
+ """
348
+ unWatches from the stream channel
349
+
350
+ https://developer-pro.bitmart.com/en/spot/#public-trade-channel
351
+ https://developer-pro.bitmart.com/en/futuresv2/#public-trade-channel
352
+
353
+ :param str symbol: unified symbol of the market to fetch trades for
354
+ :param dict [params]: extra parameters specific to the exchange API endpoint
355
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
356
+ """
357
+ return await self.un_watch_trades_for_symbols([symbol], params)
358
+
359
+ async def un_watch_trades_for_symbols(self, symbols: List[str], params={}) -> Any:
360
+ """
361
+ unsubscribes from the trades channel
362
+
363
+ https://developer-pro.bitmart.com/en/spot/#public-trade-channel
364
+ https://developer-pro.bitmart.com/en/futuresv2/#public-trade-channel
365
+
366
+ :param str[] symbols: unified symbol of the market to fetch trades for
367
+ :param dict [params]: extra parameters specific to the exchange API endpoint
368
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
369
+ """
370
+ await self.load_markets()
371
+ marketType = None
372
+ symbols, marketType, params = self.get_params_for_multiple_sub('unWatchTradesForSymbols', symbols, None, params)
373
+ channelName = 'trade'
374
+ params = self.extend(params, {'unsubscribe': True})
375
+ return await self.subscribe_multiple(channelName, marketType, symbols, params)
376
+
377
+ def get_params_for_multiple_sub(self, methodName: str, symbols: List[str], limit: Int = None, params={}):
378
+ symbols = self.market_symbols(symbols, None, False, True)
379
+ length = len(symbols)
380
+ if length > 20:
381
+ raise NotSupported(self.id + ' ' + methodName + '() accepts a maximum of 20 symbols in one request')
382
+ market = self.market(symbols[0])
383
+ marketType = None
384
+ marketType, params = self.handle_market_type_and_params(methodName, market, params)
385
+ return [symbols, marketType, params]
386
+
387
+ async def watch_ticker(self, symbol: str, params={}) -> Ticker:
388
+ """
389
+
390
+ https://developer-pro.bitmart.com/en/spot/#public-ticker-channel
391
+ https://developer-pro.bitmart.com/en/futuresv2/#public-ticker-channel
392
+
393
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
394
+ :param str symbol: unified symbol of the market to fetch the ticker for
395
+ :param dict [params]: extra parameters specific to the exchange API endpoint
396
+ :returns dict: a `ticker structure <https://docs.ccxt.com/?id=ticker-structure>`
397
+ """
398
+ await self.load_markets()
399
+ symbol = self.symbol(symbol)
400
+ tickers = await self.watch_tickers([symbol], params)
401
+ return tickers[symbol]
402
+
403
+ async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
404
+ """
405
+
406
+ https://developer-pro.bitmart.com/en/spot/#public-ticker-channel
407
+ https://developer-pro.bitmart.com/en/futuresv2/#public-ticker-channel
408
+
409
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
410
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
411
+ :param dict [params]: extra parameters specific to the exchange API endpoint
412
+ :returns dict: a `ticker structure <https://docs.ccxt.com/?id=ticker-structure>`
413
+ """
414
+ await self.load_markets()
415
+ market = self.get_market_from_symbols(symbols)
416
+ marketType = None
417
+ marketType, params = self.handle_market_type_and_params('watchTickers', market, params)
418
+ ticker = await self.subscribe_multiple('ticker', marketType, symbols, params)
419
+ if self.newUpdates:
420
+ tickers: dict = {}
421
+ tickers[ticker['symbol']] = ticker
422
+ return tickers
423
+ return self.filter_by_array(self.tickers, 'symbol', symbols)
424
+
425
+ async def un_watch_ticker(self, symbol: str, params={}) -> Any:
426
+ """
427
+ unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
428
+
429
+ https://developer-pro.bitmart.com/en/spot/#public-ticker-channel
430
+ https://developer-pro.bitmart.com/en/futuresv2/#public-ticker-channel
431
+
432
+ :param str symbol: unified symbol of the market to fetch the ticker for
433
+ :param dict [params]: extra parameters specific to the exchange API endpoint
434
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
435
+ """
436
+ return await self.un_watch_tickers([symbol], params)
437
+
438
+ async def un_watch_tickers(self, symbols: Strings = None, params={}) -> Any:
439
+ """
440
+ unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
441
+
442
+ https://developer-pro.bitmart.com/en/spot/#public-ticker-channel
443
+ https://developer-pro.bitmart.com/en/futuresv2/#public-ticker-channel
444
+
445
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
446
+ :param dict [params]: extra parameters specific to the exchange API endpoint
447
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
448
+ """
449
+ await self.load_markets()
450
+ market = self.get_market_from_symbols(symbols)
451
+ marketType = None
452
+ marketType, params = self.handle_market_type_and_params('watchTickers', market, params)
453
+ params = self.extend(params, {'unsubscribe': True})
454
+ return await self.subscribe_multiple('ticker', marketType, symbols, params)
455
+
456
+ async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
457
+ """
458
+
459
+ https://developer-pro.bitmart.com/en/spot/#public-ticker-channel
460
+ https://developer-pro.bitmart.com/en/futuresv2/#public-ticker-channel
461
+
462
+ watches best bid & ask for symbols
463
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
464
+ :param dict [params]: extra parameters specific to the exchange API endpoint
465
+ :returns dict: a `ticker structure <https://docs.ccxt.com/?id=ticker-structure>`
466
+ """
467
+ await self.load_markets()
468
+ symbols = self.market_symbols(symbols, None, False)
469
+ firstMarket = self.get_market_from_symbols(symbols)
470
+ marketType = None
471
+ marketType, params = self.handle_market_type_and_params('watchBidsAsks', firstMarket, params)
472
+ url = self.implode_hostname(self.urls['api']['ws'][marketType]['public'])
473
+ channelType = 'spot' if (marketType == 'spot') else 'futures'
474
+ actionType = 'op' if (marketType == 'spot') else 'action'
475
+ rawSubscriptions = []
476
+ messageHashes = []
477
+ for i in range(0, len(symbols)):
478
+ market = self.market(symbols[i])
479
+ rawSubscriptions.append(channelType + '/ticker:' + market['id'])
480
+ messageHashes.append('bidask:' + symbols[i])
481
+ if marketType != 'spot':
482
+ rawSubscriptions = [channelType + '/ticker']
483
+ request: dict = {
484
+ 'args': rawSubscriptions,
485
+ }
486
+ request[actionType] = 'subscribe'
487
+ newTickers = await self.watch_multiple(url, messageHashes, request, rawSubscriptions)
488
+ if self.newUpdates:
489
+ tickers: dict = {}
490
+ tickers[newTickers['symbol']] = newTickers
491
+ return tickers
492
+ return self.filter_by_array(self.bidsasks, 'symbol', symbols)
493
+
494
+ def handle_bid_ask(self, client: Client, message):
495
+ table = self.safe_string(message, 'table')
496
+ isSpot = (table is not None)
497
+ rawTickers = []
498
+ if isSpot:
499
+ rawTickers = self.safe_list(message, 'data', [])
500
+ else:
501
+ rawTickers = [self.safe_dict(message, 'data', {})]
502
+ if not len(rawTickers):
503
+ return
504
+ for i in range(0, len(rawTickers)):
505
+ ticker = self.parse_ws_bid_ask(rawTickers[i])
506
+ symbol = ticker['symbol']
507
+ self.bidsasks[symbol] = ticker
508
+ messageHash = 'bidask:' + symbol
509
+ client.resolve(ticker, messageHash)
510
+
511
+ def parse_ws_bid_ask(self, ticker, market=None):
512
+ marketId = self.safe_string(ticker, 'symbol')
513
+ market = self.safe_market(marketId, market)
514
+ symbol = self.safe_string(market, 'symbol')
515
+ timestamp = self.safe_integer(ticker, 'ms_t')
516
+ return self.safe_ticker({
517
+ 'symbol': symbol,
518
+ 'timestamp': timestamp,
519
+ 'datetime': self.iso8601(timestamp),
520
+ 'ask': self.safe_string_2(ticker, 'ask_px', 'ask_price'),
521
+ 'askVolume': self.safe_string_2(ticker, 'ask_sz', 'ask_vol'),
522
+ 'bid': self.safe_string_2(ticker, 'bid_px', 'bid_price'),
523
+ 'bidVolume': self.safe_string_2(ticker, 'bid_sz', 'bid_vol'),
524
+ 'info': ticker,
525
+ }, market)
526
+
527
+ async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
528
+ """
529
+ watches information on multiple orders made by the user
530
+
531
+ https://developer-pro.bitmart.com/en/spot/#private-order-progress
532
+ https://developer-pro.bitmart.com/en/futuresv2/#private-order-channel
533
+
534
+ :param str symbol: unified market symbol of the market orders were made in
535
+ :param int [since]: the earliest time in ms to fetch orders for
536
+ :param int [limit]: the maximum number of order structures to retrieve
537
+ :param dict [params]: extra parameters specific to the exchange API endpoint
538
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/?id=order-structure>`
539
+ """
540
+ await self.load_markets()
541
+ market = None
542
+ messageHash = 'orders'
543
+ if symbol is not None:
544
+ symbol = self.symbol(symbol)
545
+ market = self.market(symbol)
546
+ messageHash = 'orders::' + symbol
547
+ type = 'spot'
548
+ type, params = self.handle_market_type_and_params('watchOrders', market, params)
549
+ await self.authenticate(type, params)
550
+ request = None
551
+ if type == 'spot':
552
+ argsRequest = 'spot/user/order:'
553
+ if symbol is not None:
554
+ argsRequest += market['id']
555
+ else:
556
+ argsRequest = 'spot/user/orders:ALL_SYMBOLS'
557
+ request = {
558
+ 'op': 'subscribe',
559
+ 'args': [argsRequest],
560
+ }
561
+ else:
562
+ request = {
563
+ 'action': 'subscribe',
564
+ 'args': ['futures/order'],
565
+ }
566
+ url = self.implode_hostname(self.urls['api']['ws'][type]['private'])
567
+ newOrders = await self.watch(url, messageHash, self.deep_extend(request, params), messageHash)
568
+ if self.newUpdates:
569
+ return newOrders
570
+ return self.filter_by_symbol_since_limit(self.orders, symbol, since, limit, True)
571
+
572
+ async def un_watch_orders(self, symbol: Str = None, params={}) -> Any:
573
+ """
574
+ unWatches information on multiple orders made by the user
575
+
576
+ https://developer-pro.bitmart.com/en/spot/#private-order-progress
577
+ https://developer-pro.bitmart.com/en/futuresv2/#private-order-channel
578
+
579
+ :param str symbol: unified market symbol of the market orders were made in
580
+ :param dict [params]: extra parameters specific to the exchange API endpoint
581
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
582
+ """
583
+ await self.load_markets()
584
+ market = None
585
+ messageHash = 'unsubscribe::orders'
586
+ if symbol is not None:
587
+ symbol = self.symbol(symbol)
588
+ market = self.market(symbol)
589
+ if market['swap']:
590
+ raise NotSupported(self.id + ' unWatchOrders() does not support a symbol for swap markets, unWatch from all markets only')
591
+ messageHash += '::' + symbol
592
+ type = 'spot'
593
+ type, params = self.handle_market_type_and_params('watchOrders', market, params)
594
+ await self.authenticate(type, params)
595
+ request = None
596
+ if type == 'spot':
597
+ argsRequest = 'spot/user/order:'
598
+ if symbol is not None:
599
+ argsRequest += market['id']
600
+ else:
601
+ argsRequest = 'spot/user/orders:ALL_SYMBOLS'
602
+ request = {
603
+ 'op': 'unsubscribe',
604
+ 'args': [argsRequest],
605
+ }
606
+ else:
607
+ request = {
608
+ 'action': 'unsubscribe',
609
+ 'args': ['futures/order'],
610
+ }
611
+ url = self.implode_hostname(self.urls['api']['ws'][type]['private'])
612
+ return await self.watch(url, messageHash, self.deep_extend(request, params), messageHash)
613
+
614
+ def handle_orders(self, client: Client, message):
615
+ #
616
+ # spot
617
+ # {
618
+ # "data":[
619
+ # {
620
+ # "symbol": "LTC_USDT",
621
+ # "notional": '',
622
+ # "side": "buy",
623
+ # "last_fill_time": "0",
624
+ # "ms_t": "1646216634000",
625
+ # "type": "limit",
626
+ # "filled_notional": "0.000000000000000000000000000000",
627
+ # "last_fill_price": "0",
628
+ # "size": "0.500000000000000000000000000000",
629
+ # "price": "50.000000000000000000000000000000",
630
+ # "last_fill_count": "0",
631
+ # "filled_size": "0.000000000000000000000000000000",
632
+ # "margin_trading": "0",
633
+ # "state": "8",
634
+ # "order_id": "24807076628",
635
+ # "order_type": "0"
636
+ # }
637
+ # ],
638
+ # "table":"spot/user/order"
639
+ # }
640
+ # swap
641
+ # {
642
+ # "group":"futures/order",
643
+ # "data":[
644
+ # {
645
+ # "action":2,
646
+ # "order":{
647
+ # "order_id":"2312045036986775",
648
+ # "client_order_id":"",
649
+ # "price":"71.61707928",
650
+ # "size":"1",
651
+ # "symbol":"LTCUSDT",
652
+ # "state":1,
653
+ # "side":4,
654
+ # "type":"market",
655
+ # "leverage":"1",
656
+ # "open_type":"cross",
657
+ # "deal_avg_price":"0",
658
+ # "deal_size":"0",
659
+ # "create_time":1701625324646,
660
+ # "update_time":1701625324640,
661
+ # "plan_order_id":"",
662
+ # "last_trade":null
663
+ # }
664
+ # }
665
+ # ]
666
+ # }
667
+ #
668
+ orders = self.safe_list(message, 'data')
669
+ if orders is None:
670
+ return
671
+ ordersLength = len(orders)
672
+ newOrders = []
673
+ symbols: dict = {}
674
+ if ordersLength > 0:
675
+ limit = self.safe_integer(self.options, 'ordersLimit', 1000)
676
+ if self.orders is None:
677
+ self.orders = ArrayCacheBySymbolById(limit)
678
+ stored = self.orders
679
+ for i in range(0, len(orders)):
680
+ order = self.parse_ws_order(orders[i])
681
+ stored.append(order)
682
+ newOrders.append(order)
683
+ symbol = order['symbol']
684
+ symbols[symbol] = True
685
+ messageHash = 'orders'
686
+ symbolKeys = list(symbols.keys())
687
+ for i in range(0, len(symbolKeys)):
688
+ symbol = symbolKeys[i]
689
+ symbolSpecificMessageHash = messageHash + '::' + symbol
690
+ client.resolve(newOrders, symbolSpecificMessageHash)
691
+ client.resolve(newOrders, messageHash)
692
+
693
+ def parse_ws_order(self, order: dict, market: Market = None):
694
+ #
695
+ # spot
696
+ # {
697
+ # "symbol": "LTC_USDT",
698
+ # "notional": '',
699
+ # "side": "buy",
700
+ # "last_fill_time": "0",
701
+ # "ms_t": "1646216634000",
702
+ # "type": "limit",
703
+ # "filled_notional": "0.000000000000000000000000000000",
704
+ # "last_fill_price": "0",
705
+ # "size": "0.500000000000000000000000000000",
706
+ # "price": "50.000000000000000000000000000000",
707
+ # "last_fill_count": "0",
708
+ # "filled_size": "0.000000000000000000000000000000",
709
+ # "margin_trading": "0",
710
+ # "state": "8",
711
+ # "order_id": "24807076628",
712
+ # "order_type": "0"
713
+ # }
714
+ # swap
715
+ # {
716
+ # "action":2,
717
+ # "order":{
718
+ # "order_id":"2312045036986775",
719
+ # "client_order_id":"",
720
+ # "price":"71.61707928",
721
+ # "size":"1",
722
+ # "symbol":"LTCUSDT",
723
+ # "state":1,
724
+ # "side":4,
725
+ # "type":"market",
726
+ # "leverage":"1",
727
+ # "open_type":"cross",
728
+ # "deal_avg_price":"0",
729
+ # "deal_size":"0",
730
+ # "create_time":1701625324646,
731
+ # "update_time":1701625324640,
732
+ # "plan_order_id":"",
733
+ # "last_trade":null
734
+ # }
735
+ # }
736
+ #
737
+ action = self.safe_number(order, 'action')
738
+ isSpot = (action is None)
739
+ if isSpot:
740
+ marketId = self.safe_string(order, 'symbol')
741
+ market = self.safe_market(marketId, market, '_', 'spot')
742
+ id = self.safe_string(order, 'order_id')
743
+ clientOrderId = self.safe_string(order, 'clientOid')
744
+ price = self.safe_string(order, 'price')
745
+ filled = self.safe_string(order, 'filled_size')
746
+ amount = self.safe_string(order, 'size')
747
+ type = self.safe_string(order, 'type')
748
+ rawState = self.safe_string(order, 'state')
749
+ status = self.parse_order_status_by_type(market['type'], rawState)
750
+ timestamp = self.safe_integer(order, 'ms_t')
751
+ symbol = market['symbol']
752
+ side = self.safe_string_lower(order, 'side')
753
+ return self.safe_order({
754
+ 'info': order,
755
+ 'symbol': symbol,
756
+ 'id': id,
757
+ 'clientOrderId': clientOrderId,
758
+ 'timestamp': None,
759
+ 'datetime': None,
760
+ 'lastTradeTimestamp': timestamp,
761
+ 'type': type,
762
+ 'timeInForce': None,
763
+ 'postOnly': None,
764
+ 'side': side,
765
+ 'price': price,
766
+ 'stopPrice': None,
767
+ 'triggerPrice': None,
768
+ 'amount': amount,
769
+ 'cost': None,
770
+ 'average': None,
771
+ 'filled': filled,
772
+ 'remaining': None,
773
+ 'status': status,
774
+ 'fee': None,
775
+ 'trades': None,
776
+ }, market)
777
+ else:
778
+ orderInfo = self.safe_dict(order, 'order')
779
+ marketId = self.safe_string(orderInfo, 'symbol')
780
+ symbol = self.safe_symbol(marketId, market, '', 'swap')
781
+ orderId = self.safe_string(orderInfo, 'order_id')
782
+ timestamp = self.safe_integer(orderInfo, 'create_time')
783
+ updatedTimestamp = self.safe_integer(orderInfo, 'update_time')
784
+ lastTrade = self.safe_dict(orderInfo, 'last_trade')
785
+ cachedOrders = self.orders
786
+ orders = self.safe_value(cachedOrders.hashmap, symbol, {})
787
+ cachedOrder = self.safe_value(orders, orderId)
788
+ trades = None
789
+ if cachedOrder is not None:
790
+ trades = self.safe_value(order, 'trades')
791
+ if lastTrade is not None:
792
+ if trades is None:
793
+ trades = []
794
+ trades.append(lastTrade)
795
+ return self.safe_order({
796
+ 'info': order,
797
+ 'symbol': symbol,
798
+ 'id': orderId,
799
+ 'clientOrderId': self.safe_string(orderInfo, 'client_order_id'),
800
+ 'timestamp': timestamp,
801
+ 'datetime': self.iso8601(timestamp),
802
+ 'lastTradeTimestamp': updatedTimestamp,
803
+ 'type': self.safe_string(orderInfo, 'type'),
804
+ 'timeInForce': None,
805
+ 'postOnly': None,
806
+ 'side': self.parse_ws_order_side(self.safe_string(orderInfo, 'side')),
807
+ 'price': self.safe_string(orderInfo, 'price'),
808
+ 'stopPrice': None,
809
+ 'triggerPrice': None,
810
+ 'amount': self.safe_string(orderInfo, 'size'),
811
+ 'cost': None,
812
+ 'average': self.safe_string(orderInfo, 'deal_avg_price'),
813
+ 'filled': self.safe_string(orderInfo, 'deal_size'),
814
+ 'remaining': None,
815
+ 'status': self.parse_ws_order_status(self.safe_string(order, 'action')),
816
+ 'fee': None,
817
+ 'trades': trades,
818
+ }, market)
819
+
820
+ def parse_ws_order_status(self, statusId):
821
+ statuses: dict = {
822
+ '1': 'closed', # match deal
823
+ '2': 'open', # submit order
824
+ '3': 'canceled', # cancel order
825
+ '4': 'closed', # liquidate cancel order
826
+ '5': 'canceled', # adl cancel order
827
+ '6': 'open', # part liquidate
828
+ '7': 'open', # bankrupty order
829
+ '8': 'closed', # passive adl match deal
830
+ '9': 'closed', # active adl match deal
831
+ }
832
+ return self.safe_string(statuses, statusId, statusId)
833
+
834
+ def parse_ws_order_side(self, sideId):
835
+ sides: dict = {
836
+ '1': 'buy', # buy_open_long
837
+ '2': 'buy', # buy_close_short
838
+ '3': 'sell', # sell_close_long
839
+ '4': 'sell', # sell_open_short
840
+ }
841
+ return self.safe_string(sides, sideId, sideId)
842
+
843
+ async def watch_positions(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}) -> List[Position]:
844
+ """
845
+
846
+ https://developer-pro.bitmart.com/en/futures/#private-position-channel
847
+
848
+ watch all open positions
849
+ :param str[]|None symbols: list of unified market symbols
850
+ :param int [since]: the earliest time in ms to fetch positions
851
+ :param int [limit]: the maximum number of positions to retrieve
852
+ :param dict params: extra parameters specific to the exchange API endpoint
853
+ :returns dict[]: a list of `position structure <https://docs.ccxt.com/en/latest/manual.html#position-structure>`
854
+ """
855
+ await self.load_markets()
856
+ type = 'swap'
857
+ await self.authenticate(type, params)
858
+ symbols = self.market_symbols(symbols, 'swap', True, True, False)
859
+ messageHash = 'positions'
860
+ if symbols is not None:
861
+ messageHash += '::' + ','.join(symbols)
862
+ subscriptionHash = 'futures/position'
863
+ request: dict = {
864
+ 'action': 'subscribe',
865
+ 'args': ['futures/position'],
866
+ }
867
+ url = self.implode_hostname(self.urls['api']['ws'][type]['private'])
868
+ newPositions = await self.watch(url, messageHash, self.deep_extend(request, params), subscriptionHash)
869
+ if self.newUpdates:
870
+ return newPositions
871
+ return self.filter_by_symbols_since_limit(self.positions, symbols, since, limit)
872
+
873
+ async def un_watch_positions(self, symbols: Strings = None, params={}) -> Any:
874
+ """
875
+ unWatches all open positions
876
+
877
+ https://developer-pro.bitmart.com/en/futures/#private-position-channel
878
+
879
+ :param str[] [symbols]: list of unified market symbols
880
+ :param dict [params]: extra parameters specific to the exchange API endpoint
881
+ :returns dict: status of the unwatch request
882
+ """
883
+ if symbols is not None:
884
+ length = len(symbols)
885
+ if length > 0:
886
+ raise NotSupported(self.id + ' unWatchPositions() does not support a list of symbols, unWatch from all markets only')
887
+ await self.load_markets()
888
+ request: dict = {
889
+ 'action': 'unsubscribe',
890
+ 'args': ['futures/position'],
891
+ }
892
+ messageHash = 'unsubscribe::positions'
893
+ url = self.implode_hostname(self.urls['api']['ws']['swap']['private'])
894
+ return await self.watch(url, messageHash, self.deep_extend(request, params), messageHash)
895
+
896
+ def handle_positions(self, client: Client, message):
897
+ #
898
+ # {
899
+ # "group":"futures/position",
900
+ # "data":[
901
+ # {
902
+ # "symbol":"LTCUSDT",
903
+ # "hold_volume":"5",
904
+ # "position_type":2,
905
+ # "open_type":2,
906
+ # "frozen_volume":"0",
907
+ # "close_volume":"0",
908
+ # "hold_avg_price":"71.582",
909
+ # "close_avg_price":"0",
910
+ # "open_avg_price":"71.582",
911
+ # "liquidate_price":"0",
912
+ # "create_time":1701623327513,
913
+ # "update_time":1701627620439
914
+ # },
915
+ # {
916
+ # "symbol":"LTCUSDT",
917
+ # "hold_volume":"6",
918
+ # "position_type":1,
919
+ # "open_type":2,
920
+ # "frozen_volume":"0",
921
+ # "close_volume":"0",
922
+ # "hold_avg_price":"71.681666666666666667",
923
+ # "close_avg_price":"0",
924
+ # "open_avg_price":"71.681666666666666667",
925
+ # "liquidate_price":"0",
926
+ # "create_time":1701621167225,
927
+ # "update_time":1701628152614
928
+ # }
929
+ # ]
930
+ # }
931
+ #
932
+ data = self.safe_list(message, 'data', [])
933
+ if self.positions is None:
934
+ self.positions = ArrayCacheBySymbolBySide()
935
+ cache = self.positions
936
+ newPositions = []
937
+ for i in range(0, len(data)):
938
+ rawPosition = data[i]
939
+ position = self.parse_ws_position(rawPosition)
940
+ newPositions.append(position)
941
+ cache.append(position)
942
+ messageHashes = self.find_message_hashes(client, 'positions::')
943
+ for i in range(0, len(messageHashes)):
944
+ messageHash = messageHashes[i]
945
+ parts = messageHash.split('::')
946
+ symbolsString = parts[1]
947
+ symbols = symbolsString.split(',')
948
+ positions = self.filter_by_array(newPositions, 'symbol', symbols, False)
949
+ if not self.is_empty(positions):
950
+ client.resolve(positions, messageHash)
951
+ client.resolve(newPositions, 'positions')
952
+
953
+ def parse_ws_position(self, position, market: Market = None):
954
+ #
955
+ # {
956
+ # "symbol":"LTCUSDT",
957
+ # "hold_volume":"6",
958
+ # "position_type":1,
959
+ # "open_type":2,
960
+ # "frozen_volume":"0",
961
+ # "close_volume":"0",
962
+ # "hold_avg_price":"71.681666666666666667",
963
+ # "close_avg_price":"0",
964
+ # "open_avg_price":"71.681666666666666667",
965
+ # "liquidate_price":"0",
966
+ # "create_time":1701621167225,
967
+ # "update_time":1701628152614
968
+ # }
969
+ #
970
+ marketId = self.safe_string(position, 'symbol')
971
+ market = self.safe_market(marketId, market, None, 'swap')
972
+ symbol = market['symbol']
973
+ openTimestamp = self.safe_integer(position, 'create_time')
974
+ timestamp = self.safe_integer(position, 'update_time')
975
+ side = self.safe_integer(position, 'position_type')
976
+ marginModeId = self.safe_integer(position, 'open_type')
977
+ return self.safe_position({
978
+ 'info': position,
979
+ 'id': None,
980
+ 'symbol': symbol,
981
+ 'timestamp': openTimestamp,
982
+ 'datetime': self.iso8601(openTimestamp),
983
+ 'lastUpdateTimestamp': timestamp,
984
+ 'hedged': None,
985
+ 'side': 'long' if (side == 1) else 'short',
986
+ 'contracts': self.safe_number(position, 'hold_volume'),
987
+ 'contractSize': self.safe_number(market, 'contractSize'),
988
+ 'entryPrice': self.safe_number(position, 'open_avg_price'),
989
+ 'markPrice': self.safe_number(position, 'hold_avg_price'),
990
+ 'lastPrice': None,
991
+ 'notional': None,
992
+ 'leverage': None,
993
+ 'collateral': None,
994
+ 'initialMargin': None,
995
+ 'initialMarginPercentage': None,
996
+ 'maintenanceMargin': None,
997
+ 'maintenanceMarginPercentage': None,
998
+ 'unrealizedPnl': None,
999
+ 'realizedPnl': None,
1000
+ 'liquidationPrice': self.safe_number(position, 'liquidate_price'),
1001
+ 'marginMode': 'isolated' if (marginModeId == 1) else 'cross',
1002
+ 'percentage': None,
1003
+ 'marginRatio': None,
1004
+ 'stopLossPrice': None,
1005
+ 'takeProfitPrice': None,
1006
+ })
1007
+
1008
+ def handle_trade(self, client: Client, message):
1009
+ #
1010
+ # spot
1011
+ # {
1012
+ # "table": "spot/trade",
1013
+ # "data": [
1014
+ # {
1015
+ # "price": "52700.50",
1016
+ # "s_t": 1630982050,
1017
+ # "side": "buy",
1018
+ # "size": "0.00112",
1019
+ # "symbol": "BTC_USDT"
1020
+ # },
1021
+ # ]
1022
+ # }
1023
+ #
1024
+ # swap
1025
+ # {
1026
+ # "group":"futures/trade:BTCUSDT",
1027
+ # "data":[
1028
+ # {
1029
+ # "trade_id":6798697637,
1030
+ # "symbol":"BTCUSDT",
1031
+ # "deal_price":"39735.8",
1032
+ # "deal_vol":"2",
1033
+ # "way":1,
1034
+ # "created_at":"2023-12-03T15:48:23.517518538Z",
1035
+ # "m": True,
1036
+ # }
1037
+ # ]
1038
+ # }
1039
+ #
1040
+ data = self.safe_list(message, 'data')
1041
+ if data is None:
1042
+ return
1043
+ symbol = None
1044
+ length = len(data)
1045
+ isSwap = ('group' in message)
1046
+ if isSwap:
1047
+ # in swap, chronologically decreasing: 1709536849322, 1709536848954,
1048
+ for i in range(0, length):
1049
+ index = length - i - 1
1050
+ symbol = self.handle_trade_loop(data[index])
1051
+ else:
1052
+ # in spot, chronologically increasing: 1709536771200, 1709536771226,
1053
+ for i in range(0, length):
1054
+ symbol = self.handle_trade_loop(data[i])
1055
+ client.resolve(self.trades[symbol], 'trade:' + symbol)
1056
+
1057
+ def handle_trade_loop(self, entry):
1058
+ trade = self.parse_ws_trade(entry)
1059
+ symbol = trade['symbol']
1060
+ tradesLimit = self.safe_integer(self.options, 'tradesLimit', 1000)
1061
+ if self.safe_value(self.trades, symbol) is None:
1062
+ self.trades[symbol] = ArrayCache(tradesLimit)
1063
+ stored = self.trades[symbol]
1064
+ stored.append(trade)
1065
+ return symbol
1066
+
1067
+ def parse_ws_trade(self, trade: dict, market: Market = None):
1068
+ #
1069
+ # spot
1070
+ # {
1071
+ # "ms_t": 1740320841473,
1072
+ # "price": "2806.54",
1073
+ # "s_t": 1740320841,
1074
+ # "side": "sell",
1075
+ # "size": "0.77598",
1076
+ # "symbol": "ETH_USDT"
1077
+ # }
1078
+ #
1079
+ # swap
1080
+ # {
1081
+ # "trade_id": "3000000245258661",
1082
+ # "symbol": "ETHUSDT",
1083
+ # "deal_price": "2811.1",
1084
+ # "deal_vol": "1858",
1085
+ # "way": 2,
1086
+ # "m": True,
1087
+ # "created_at": "2025-02-23T13:59:59.646490751Z"
1088
+ # }
1089
+ #
1090
+ marketId = self.safe_string(trade, 'symbol')
1091
+ market = self.safe_market(marketId, market)
1092
+ timestamp = self.safe_integer(trade, 'ms_t')
1093
+ datetime: Str = None
1094
+ if timestamp is None:
1095
+ datetime = self.safe_string(trade, 'created_at')
1096
+ timestamp = self.parse8601(datetime)
1097
+ else:
1098
+ datetime = self.iso8601(timestamp)
1099
+ takerOrMaker = None # True for public trades
1100
+ side = self.safe_string(trade, 'side')
1101
+ buyerMaker = self.safe_bool(trade, 'm')
1102
+ if buyerMaker is not None:
1103
+ if side is None:
1104
+ if buyerMaker:
1105
+ side = 'sell'
1106
+ else:
1107
+ side = 'buy'
1108
+ takerOrMaker = 'taker'
1109
+ return self.safe_trade({
1110
+ 'info': trade,
1111
+ 'id': self.safe_string(trade, 'trade_id'),
1112
+ 'order': None,
1113
+ 'timestamp': timestamp,
1114
+ 'datetime': datetime,
1115
+ 'symbol': market['symbol'],
1116
+ 'type': None,
1117
+ 'side': side,
1118
+ 'price': self.safe_string_2(trade, 'price', 'deal_price'),
1119
+ 'amount': self.safe_string_2(trade, 'size', 'deal_vol'),
1120
+ 'cost': None,
1121
+ 'takerOrMaker': takerOrMaker,
1122
+ 'fee': None,
1123
+ }, market)
1124
+
1125
+ def handle_ticker(self, client: Client, message):
1126
+ #
1127
+ # {
1128
+ # "data": [
1129
+ # {
1130
+ # "base_volume_24h": "78615593.81",
1131
+ # "high_24h": "52756.97",
1132
+ # "last_price": "52638.31",
1133
+ # "low_24h": "50991.35",
1134
+ # "open_24h": "51692.03",
1135
+ # "s_t": 1630981727,
1136
+ # "symbol": "BTC_USDT"
1137
+ # }
1138
+ # ],
1139
+ # "table": "spot/ticker"
1140
+ # }
1141
+ #
1142
+ # {
1143
+ # "data": {
1144
+ # "symbol": "ETHUSDT",
1145
+ # "last_price": "2807.73",
1146
+ # "volume_24": "2227011952",
1147
+ # "range": "0.0273398194664491",
1148
+ # "mark_price": "2807.5",
1149
+ # "index_price": "2808.71047619",
1150
+ # "ask_price": "2808.04",
1151
+ # "ask_vol": "7371",
1152
+ # "bid_price": "2807.28",
1153
+ # "bid_vol": "3561"
1154
+ # },
1155
+ # "group": "futures/ticker:ETHUSDT@100ms"
1156
+ # }
1157
+ #
1158
+ self.handle_bid_ask(client, message)
1159
+ table = self.safe_string(message, 'table')
1160
+ isSpot = (table is not None)
1161
+ rawTickers = []
1162
+ if isSpot:
1163
+ rawTickers = self.safe_list(message, 'data', [])
1164
+ else:
1165
+ rawTickers = [self.safe_dict(message, 'data', {})]
1166
+ if not len(rawTickers):
1167
+ return
1168
+ for i in range(0, len(rawTickers)):
1169
+ ticker = self.parse_ticker(rawTickers[i]) if isSpot else self.parse_ws_swap_ticker(rawTickers[i])
1170
+ symbol = ticker['symbol']
1171
+ self.tickers[symbol] = ticker
1172
+ messageHash = 'ticker:' + symbol
1173
+ client.resolve(ticker, messageHash)
1174
+
1175
+ def parse_ws_swap_ticker(self, ticker, market: Market = None):
1176
+ #
1177
+ # {
1178
+ # "symbol": "ETHUSDT",
1179
+ # "last_price": "2807.73",
1180
+ # "volume_24": "2227011952",
1181
+ # "range": "0.0273398194664491",
1182
+ # "mark_price": "2807.5",
1183
+ # "index_price": "2808.71047619",
1184
+ # "ask_price": "2808.04",
1185
+ # "ask_vol": "7371",
1186
+ # "bid_price": "2807.28",
1187
+ # "bid_vol": "3561"
1188
+ # }
1189
+ #
1190
+ marketId = self.safe_string(ticker, 'symbol')
1191
+ return self.safe_ticker({
1192
+ 'symbol': self.safe_symbol(marketId, market, '', 'swap'),
1193
+ 'timestamp': None,
1194
+ 'datetime': None,
1195
+ 'high': None,
1196
+ 'low': None,
1197
+ 'bid': self.safe_string(ticker, 'bid_price'),
1198
+ 'bidVolume': self.safe_string(ticker, 'bid_vol'),
1199
+ 'ask': self.safe_string(ticker, 'ask_price'),
1200
+ 'askVolume': self.safe_string(ticker, 'ask_vol'),
1201
+ 'vwap': None,
1202
+ 'open': None,
1203
+ 'close': None,
1204
+ 'last': self.safe_string(ticker, 'last_price'),
1205
+ 'previousClose': None,
1206
+ 'change': None,
1207
+ 'percentage': None,
1208
+ 'average': None,
1209
+ 'baseVolume': None,
1210
+ 'quoteVolume': self.safe_string(ticker, 'volume_24'),
1211
+ 'info': ticker,
1212
+ 'markPrice': self.safe_string(ticker, 'mark_price'),
1213
+ 'indexPrice': self.safe_string(ticker, 'index_price'),
1214
+ }, market)
1215
+
1216
+ async def watch_ohlcv(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1217
+ """
1218
+
1219
+ https://developer-pro.bitmart.com/en/spot/#public-kline-channel
1220
+ https://developer-pro.bitmart.com/en/futuresv2/#public-klinebin-channel
1221
+
1222
+ watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1223
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
1224
+ :param str timeframe: the length of time each candle represents
1225
+ :param int [since]: timestamp in ms of the earliest candle to fetch
1226
+ :param int [limit]: the maximum amount of candles to fetch
1227
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1228
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
1229
+ """
1230
+ await self.load_markets()
1231
+ symbol = self.symbol(symbol)
1232
+ market = self.market(symbol)
1233
+ type = 'spot'
1234
+ type, params = self.handle_market_type_and_params('watchOHLCV', market, params)
1235
+ timeframes = self.safe_dict(self.options, 'timeframes', {})
1236
+ interval = self.safe_string(timeframes, timeframe)
1237
+ name = None
1238
+ if type == 'spot':
1239
+ name = 'kline' + interval
1240
+ else:
1241
+ name = 'klineBin' + interval
1242
+ ohlcv = await self.subscribe(name, symbol, type, params)
1243
+ if self.newUpdates:
1244
+ limit = ohlcv.getLimit(symbol, limit)
1245
+ return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
1246
+
1247
+ async def un_watch_ohlcv(self, symbol: str, timeframe: str = '1m', params={}) -> Any:
1248
+ """
1249
+ unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1250
+
1251
+ https://developer-pro.bitmart.com/en/spot/#public-kline-channel
1252
+ https://developer-pro.bitmart.com/en/futuresv2/#public-klinebin-channel
1253
+
1254
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
1255
+ :param str timeframe: the length of time each candle represents
1256
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1257
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
1258
+ """
1259
+ await self.load_markets()
1260
+ symbol = self.symbol(symbol)
1261
+ market = self.market(symbol)
1262
+ type = 'spot'
1263
+ type, params = self.handle_market_type_and_params('unWatchOHLCV', market, params)
1264
+ timeframes = self.safe_dict(self.options, 'timeframes', {})
1265
+ interval = self.safe_string(timeframes, timeframe)
1266
+ name = None
1267
+ if type == 'spot':
1268
+ name = 'kline' + interval
1269
+ else:
1270
+ name = 'klineBin' + interval
1271
+ params = self.extend(params, {'unsubscribe': True})
1272
+ return await self.subscribe(name, symbol, type, params)
1273
+
1274
+ def handle_ohlcv(self, client: Client, message):
1275
+ #
1276
+ # {
1277
+ # "data": [
1278
+ # {
1279
+ # "candle": [
1280
+ # 1631056350,
1281
+ # "46532.83",
1282
+ # "46555.71",
1283
+ # "46511.41",
1284
+ # "46555.71",
1285
+ # "0.25"
1286
+ # ],
1287
+ # "symbol": "BTC_USDT"
1288
+ # }
1289
+ # ],
1290
+ # "table": "spot/kline1m"
1291
+ # }
1292
+ # swap
1293
+ # {
1294
+ # "group":"futures/klineBin1m:BTCUSDT",
1295
+ # "data":{
1296
+ # "symbol":"BTCUSDT",
1297
+ # "items":[
1298
+ # {
1299
+ # "o":"39635.8",
1300
+ # "h":"39636",
1301
+ # "l":"39614.4",
1302
+ # "c":"39629.7",
1303
+ # "v":"31852",
1304
+ # "ts":1701617761
1305
+ # }
1306
+ # ]
1307
+ # }
1308
+ # }
1309
+ #
1310
+ channel = self.safe_string_2(message, 'table', 'group')
1311
+ isSpot = (channel.find('spot') >= 0)
1312
+ data = self.safe_value(message, 'data')
1313
+ if data is None:
1314
+ return
1315
+ parts = channel.split('/')
1316
+ part1 = self.safe_string(parts, 1, '')
1317
+ interval = part1.replace('kline', '')
1318
+ interval = interval.replace('Bin', '')
1319
+ intervalParts = interval.split(':')
1320
+ interval = self.safe_string(intervalParts, 0)
1321
+ # use a reverse lookup in a static map instead
1322
+ timeframes = self.safe_dict(self.options, 'timeframes', {})
1323
+ timeframe = self.find_timeframe(interval, timeframes)
1324
+ duration = self.parse_timeframe(timeframe)
1325
+ durationInMs = duration * 1000
1326
+ if isSpot:
1327
+ for i in range(0, len(data)):
1328
+ marketId = self.safe_string(data[i], 'symbol')
1329
+ market = self.safe_market(marketId)
1330
+ symbol = market['symbol']
1331
+ rawOHLCV = self.safe_list(data[i], 'candle')
1332
+ parsed = self.parse_ohlcv(rawOHLCV, market)
1333
+ parsed[0] = self.parse_to_int(parsed[0] / durationInMs) * durationInMs
1334
+ self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
1335
+ stored = self.safe_value(self.ohlcvs[symbol], timeframe)
1336
+ if stored is None:
1337
+ limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
1338
+ stored = ArrayCacheByTimestamp(limit)
1339
+ self.ohlcvs[symbol][timeframe] = stored
1340
+ stored.append(parsed)
1341
+ messageHash = channel + ':' + marketId
1342
+ client.resolve(stored, messageHash)
1343
+ else:
1344
+ marketId = self.safe_string(data, 'symbol')
1345
+ market = self.safe_market(marketId, None, None, 'swap')
1346
+ symbol = market['symbol']
1347
+ items = self.safe_list(data, 'items', [])
1348
+ self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
1349
+ stored = self.safe_value(self.ohlcvs[symbol], timeframe)
1350
+ if stored is None:
1351
+ limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
1352
+ stored = ArrayCacheByTimestamp(limit)
1353
+ self.ohlcvs[symbol][timeframe] = stored
1354
+ for i in range(0, len(items)):
1355
+ candle = items[i]
1356
+ parsed = self.parse_ohlcv(candle, market)
1357
+ stored.append(parsed)
1358
+ client.resolve(stored, channel)
1359
+
1360
+ async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
1361
+ """
1362
+
1363
+ https://developer-pro.bitmart.com/en/spot/#public-depth-all-channel
1364
+ https://developer-pro.bitmart.com/en/spot/#public-depth-increase-channel
1365
+ https://developer-pro.bitmart.com/en/futuresv2/#public-depth-channel
1366
+
1367
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1368
+ :param str symbol: unified symbol of the market to fetch the order book for
1369
+ :param int [limit]: the maximum amount of order book entries to return
1370
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1371
+ :param str [params.speed]: *futures only* '100ms' or '200ms'
1372
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/?id=order-book-structure>` indexed by market symbols
1373
+ """
1374
+ await self.load_markets()
1375
+ options = self.safe_dict(self.options, 'watchOrderBook', {})
1376
+ depth = self.safe_string(options, 'depth', 'depth/increase100')
1377
+ symbol = self.symbol(symbol)
1378
+ market = self.market(symbol)
1379
+ type = 'spot'
1380
+ type, params = self.handle_market_type_and_params('watchOrderBook', market, params)
1381
+ if type == 'swap' and depth == 'depth/increase100':
1382
+ depth = 'depth50'
1383
+ orderbook = await self.subscribe(depth, symbol, type, params)
1384
+ return orderbook.limit()
1385
+
1386
+ async def un_watch_order_book(self, symbol: str, params={}) -> Any:
1387
+ """
1388
+ unWatches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1389
+
1390
+ https://developer-pro.bitmart.com/en/spot/#public-depth-all-channel
1391
+ https://developer-pro.bitmart.com/en/spot/#public-depth-increase-channel
1392
+ https://developer-pro.bitmart.com/en/futuresv2/#public-depth-channel
1393
+
1394
+ :param str symbol: unified array of symbols
1395
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1396
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
1397
+ """
1398
+ await self.load_markets()
1399
+ options = self.safe_dict(self.options, 'watchOrderBook', {})
1400
+ depth = self.safe_string(options, 'depth', 'depth/increase100')
1401
+ symbol = self.symbol(symbol)
1402
+ market = self.market(symbol)
1403
+ type = 'spot'
1404
+ type, params = self.handle_market_type_and_params('unWatchOrderBook', market, params)
1405
+ if type == 'swap' and depth == 'depth/increase100':
1406
+ depth = 'depth50'
1407
+ params = self.extend(params, {'unsubscribe': True})
1408
+ return await self.subscribe(depth, symbol, type, params)
1409
+
1410
+ def handle_delta(self, bookside, delta):
1411
+ price = self.safe_float(delta, 0)
1412
+ amount = self.safe_float(delta, 1)
1413
+ bookside.store(price, amount)
1414
+
1415
+ def handle_deltas(self, bookside, deltas):
1416
+ for i in range(0, len(deltas)):
1417
+ self.handle_delta(bookside, deltas[i])
1418
+
1419
+ def handle_order_book_message(self, client: Client, message, orderbook):
1420
+ #
1421
+ # {
1422
+ # "asks": [
1423
+ # ['46828.38', "0.21847"],
1424
+ # ['46830.68', "0.08232"],
1425
+ # ['46832.08', "0.09285"],
1426
+ # ['46837.82', "0.02028"],
1427
+ # ['46839.43', "0.15068"]
1428
+ # ],
1429
+ # "bids": [
1430
+ # ['46820.78', "0.00444"],
1431
+ # ['46814.33', "0.00234"],
1432
+ # ['46813.50', "0.05021"],
1433
+ # ['46808.14', "0.00217"],
1434
+ # ['46808.04', "0.00013"]
1435
+ # ],
1436
+ # "ms_t": 1631044962431,
1437
+ # "symbol": "BTC_USDT"
1438
+ # }
1439
+ #
1440
+ asks = self.safe_list(message, 'asks', [])
1441
+ bids = self.safe_list(message, 'bids', [])
1442
+ self.handle_deltas(orderbook['asks'], asks)
1443
+ self.handle_deltas(orderbook['bids'], bids)
1444
+ timestamp = self.safe_integer(message, 'ms_t')
1445
+ marketId = self.safe_string(message, 'symbol')
1446
+ symbol = self.safe_symbol(marketId)
1447
+ orderbook['symbol'] = symbol
1448
+ orderbook['timestamp'] = timestamp
1449
+ orderbook['datetime'] = self.iso8601(timestamp)
1450
+ return orderbook
1451
+
1452
+ def handle_order_book(self, client: Client, message):
1453
+ #
1454
+ # spot depth-all
1455
+ #
1456
+ # {
1457
+ # "data": [
1458
+ # {
1459
+ # "asks": [
1460
+ # ['46828.38', "0.21847"],
1461
+ # ['46830.68', "0.08232"],
1462
+ # ...
1463
+ # ],
1464
+ # "bids": [
1465
+ # ['46820.78', "0.00444"],
1466
+ # ['46814.33', "0.00234"],
1467
+ # ...
1468
+ # ],
1469
+ # "ms_t": 1631044962431,
1470
+ # "symbol": "BTC_USDT"
1471
+ # }
1472
+ # ],
1473
+ # "table": "spot/depth5"
1474
+ # }
1475
+ #
1476
+ # spot increse depth snapshot
1477
+ #
1478
+ # {
1479
+ # "data":[
1480
+ # {
1481
+ # "asks":[
1482
+ # ["43652.52", "0.02039"],
1483
+ # ...
1484
+ # ],
1485
+ # "bids":[
1486
+ # ["43652.51", "0.00500"],
1487
+ # ...
1488
+ # ],
1489
+ # "ms_t":1703376836487,
1490
+ # "symbol":"BTC_USDT",
1491
+ # "type":"snapshot", # or update
1492
+ # "version":2141731
1493
+ # }
1494
+ # ],
1495
+ # "table":"spot/depth/increase100"
1496
+ # }
1497
+ #
1498
+ # swap
1499
+ #
1500
+ # {
1501
+ # "group":"futures/depth50:BTCUSDT",
1502
+ # "data":{
1503
+ # "symbol":"BTCUSDT",
1504
+ # "way":1,
1505
+ # "depths":[
1506
+ # {
1507
+ # "price":"39509.8",
1508
+ # "vol":"2379"
1509
+ # },
1510
+ # {
1511
+ # "price":"39509.6",
1512
+ # "vol":"6815"
1513
+ # },
1514
+ # ...
1515
+ # ],
1516
+ # "ms_t":1701566021194
1517
+ # }
1518
+ # }
1519
+ #
1520
+ isSpot = ('table' in message)
1521
+ datas = []
1522
+ if isSpot:
1523
+ datas = self.safe_list(message, 'data', datas)
1524
+ else:
1525
+ orderBookEntry = self.safe_dict(message, 'data')
1526
+ if orderBookEntry is not None:
1527
+ datas.append(orderBookEntry)
1528
+ length = len(datas)
1529
+ if length <= 0:
1530
+ return
1531
+ channelName = self.safe_string_2(message, 'table', 'group')
1532
+ # find limit subscribed to
1533
+ limitsToCheck = ['100', '50', '20', '10', '5']
1534
+ limit = 0
1535
+ for i in range(0, len(limitsToCheck)):
1536
+ limitString = limitsToCheck[i]
1537
+ if channelName.find(limitString) >= 0:
1538
+ limit = self.parse_to_int(limitString)
1539
+ break
1540
+ if isSpot:
1541
+ channel = channelName.replace('spot/', '')
1542
+ for i in range(0, len(datas)):
1543
+ update = datas[i]
1544
+ marketId = self.safe_string(update, 'symbol')
1545
+ symbol = self.safe_symbol(marketId)
1546
+ if not (symbol in self.orderbooks):
1547
+ ob = self.order_book({}, limit)
1548
+ ob['symbol'] = symbol
1549
+ self.orderbooks[symbol] = ob
1550
+ orderbook = self.orderbooks[symbol]
1551
+ type = self.safe_string(update, 'type')
1552
+ if (type == 'snapshot') or (not(channelName.find('increase') >= 0)):
1553
+ orderbook.reset({})
1554
+ self.handle_order_book_message(client, update, orderbook)
1555
+ timestamp = self.safe_integer(update, 'ms_t')
1556
+ if orderbook['timestamp'] is None:
1557
+ orderbook['timestamp'] = timestamp
1558
+ orderbook['datetime'] = self.iso8601(timestamp)
1559
+ messageHash = channelName + ':' + marketId
1560
+ client.resolve(orderbook, messageHash)
1561
+ # resolve ForSymbols
1562
+ messageHashForMulti = channel + ':' + symbol
1563
+ client.resolve(orderbook, messageHashForMulti)
1564
+ else:
1565
+ tableParts = channelName.split(':')
1566
+ channel = tableParts[0].replace('futures/', '')
1567
+ data = datas[0] # contract markets always contain only one member
1568
+ depths = data['depths']
1569
+ marketId = self.safe_string(data, 'symbol')
1570
+ symbol = self.safe_symbol(marketId)
1571
+ if not (symbol in self.orderbooks):
1572
+ ob = self.order_book({}, limit)
1573
+ ob['symbol'] = symbol
1574
+ self.orderbooks[symbol] = ob
1575
+ orderbook = self.orderbooks[symbol]
1576
+ way = self.safe_integer(data, 'way')
1577
+ side = 'bids' if (way == 1) else 'asks'
1578
+ if way == 1:
1579
+ orderbook[side] = Bids([], limit)
1580
+ else:
1581
+ orderbook[side] = Asks([], limit)
1582
+ for i in range(0, len(depths)):
1583
+ depth = depths[i]
1584
+ price = self.safe_number(depth, 'price')
1585
+ amount = self.safe_number(depth, 'vol')
1586
+ orderbookSide = self.safe_value(orderbook, side)
1587
+ orderbookSide.store(price, amount)
1588
+ bidsLength = len(orderbook['bids'])
1589
+ asksLength = len(orderbook['asks'])
1590
+ if (bidsLength == 0) or (asksLength == 0):
1591
+ return
1592
+ timestamp = self.safe_integer(data, 'ms_t')
1593
+ orderbook['timestamp'] = timestamp
1594
+ orderbook['datetime'] = self.iso8601(timestamp)
1595
+ messageHash = channelName
1596
+ client.resolve(orderbook, messageHash)
1597
+ # resolve ForSymbols
1598
+ messageHashForMulti = channel + ':' + symbol
1599
+ client.resolve(orderbook, messageHashForMulti)
1600
+
1601
+ async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
1602
+ """
1603
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1604
+
1605
+ https://developer-pro.bitmart.com/en/spot/#public-depth-increase-channel
1606
+
1607
+ :param str[] symbols: unified array of symbols
1608
+ :param int [limit]: the maximum amount of order book entries to return
1609
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1610
+ :param str [params.depth]: the type of order book to subscribe to, default is 'depth/increase100', also accepts 'depth5' or 'depth20' or depth50
1611
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/?id=order-book-structure>` indexed by market symbols
1612
+ """
1613
+ await self.load_markets()
1614
+ type = None
1615
+ symbols, type, params = self.get_params_for_multiple_sub('watchOrderBookForSymbols', symbols, limit, params)
1616
+ channel = None
1617
+ channel, params = self.handle_option_and_params(params, 'watchOrderBookForSymbols', 'depth', 'depth/increase100')
1618
+ if type == 'swap' and channel == 'depth/increase100':
1619
+ channel = 'depth50'
1620
+ orderbook = await self.subscribe_multiple(channel, type, symbols, params)
1621
+ return orderbook.limit()
1622
+
1623
+ async def un_watch_order_book_for_symbols(self, symbols: List[str], params={}) -> Any:
1624
+ """
1625
+ unWatches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1626
+
1627
+ https://developer-pro.bitmart.com/en/spot/#public-depth-increase-channel
1628
+
1629
+ :param str[] symbols: unified array of symbols
1630
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1631
+ :param str [params.depth]: the type of order book to subscribe to, default is 'depth/increase100', also accepts 'depth5' or 'depth20' or depth50
1632
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
1633
+ """
1634
+ await self.load_markets()
1635
+ type = None
1636
+ symbols, type, params = self.get_params_for_multiple_sub('unWatchOrderBookForSymbols', symbols, None, params)
1637
+ channel = None
1638
+ channel, params = self.handle_option_and_params(params, 'unWatchOrderBookForSymbols', 'depth', 'depth/increase100')
1639
+ if type == 'swap' and channel == 'depth/increase100':
1640
+ channel = 'depth50'
1641
+ params = self.extend(params, {'unsubscribe': True})
1642
+ return await self.subscribe_multiple(channel, type, symbols, params)
1643
+
1644
+ async def authenticate(self, type, params={}):
1645
+ self.check_required_credentials()
1646
+ url = self.implode_hostname(self.urls['api']['ws'][type]['private'])
1647
+ messageHash = 'authenticated'
1648
+ client = self.client(url)
1649
+ future = client.reusableFuture(messageHash)
1650
+ authenticated = self.safe_value(client.subscriptions, messageHash)
1651
+ if authenticated is None:
1652
+ timestamp = str(self.milliseconds())
1653
+ memo = self.uid
1654
+ path = 'bitmart.WebSocket'
1655
+ auth = timestamp + '#' + memo + '#' + path
1656
+ signature = self.hmac(self.encode(auth), self.encode(self.secret), hashlib.sha256)
1657
+ request = None
1658
+ if type == 'spot':
1659
+ request = {
1660
+ 'op': 'login',
1661
+ 'args': [
1662
+ self.apiKey,
1663
+ timestamp,
1664
+ signature,
1665
+ ],
1666
+ }
1667
+ else:
1668
+ request = {
1669
+ 'action': 'access',
1670
+ 'args': [
1671
+ self.apiKey,
1672
+ timestamp,
1673
+ signature,
1674
+ 'web',
1675
+ ],
1676
+ }
1677
+ message = self.extend(request, params)
1678
+ self.watch(url, messageHash, message, messageHash)
1679
+ return await future
1680
+
1681
+ def handle_subscription_status(self, client: Client, message):
1682
+ #
1683
+ # {"event":"subscribe","channel":"spot/depth:BTC-USDT"}
1684
+ #
1685
+ return message
1686
+
1687
+ def handle_authenticate(self, client: Client, message):
1688
+ #
1689
+ # spot
1690
+ # {event: "login"}
1691
+ # swap
1692
+ # {action: 'access', success: True}
1693
+ #
1694
+ messageHash = 'authenticated'
1695
+ future = self.safe_value(client.futures, messageHash)
1696
+ future.resolve(True)
1697
+
1698
+ def handle_error_message(self, client: Client, message) -> Bool:
1699
+ #
1700
+ # {event: "error", message: "Invalid sign", errorCode: 30013}
1701
+ # {"event":"error","message":"Unrecognized request: {\"event\":\"subscribe\",\"channel\":\"spot/depth:BTC-USDT\"}","errorCode":30039}
1702
+ # {
1703
+ # action: '',
1704
+ # group: 'futures/trade:BTCUSDT',
1705
+ # success: False,
1706
+ # request: {action: '', args: ['futures/trade:BTCUSDT']},
1707
+ # error: 'Invalid action [] for group [futures/trade:BTCUSDT]'
1708
+ # }
1709
+ #
1710
+ errorCode = self.safe_string(message, 'errorCode')
1711
+ error = self.safe_string(message, 'error')
1712
+ try:
1713
+ if errorCode is not None or error is not None:
1714
+ feedback = self.id + ' ' + self.json(message)
1715
+ self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
1716
+ messageString = self.safe_value(message, 'message', error)
1717
+ self.throw_broadly_matched_exception(self.exceptions['broad'], messageString, feedback)
1718
+ action = self.safe_string(message, 'action')
1719
+ if action == 'access':
1720
+ raise AuthenticationError(feedback)
1721
+ raise ExchangeError(feedback)
1722
+ return False
1723
+ except Exception as e:
1724
+ if (isinstance(e, AuthenticationError)):
1725
+ messageHash = 'authenticated'
1726
+ client.reject(e, messageHash)
1727
+ if messageHash in client.subscriptions:
1728
+ del client.subscriptions[messageHash]
1729
+ client.reject(e)
1730
+ return True
1731
+
1732
+ def handle_un_subscription(self, client: Client, message):
1733
+ #
1734
+ # spot
1735
+ # {
1736
+ # "topic": "spot/ticker:ETH_USDT",
1737
+ # "event": "unsubscribe"
1738
+ # }
1739
+ #
1740
+ # swap
1741
+ # {
1742
+ # "action": "unsubscribe",
1743
+ # "group": "futures/ticker:ETHUSDT",
1744
+ # "success": True,
1745
+ # "request": {
1746
+ # "action": "unsubscribe",
1747
+ # "args": [
1748
+ # "futures/ticker:ETHUSDT"
1749
+ # ]
1750
+ # }
1751
+ # }
1752
+ #
1753
+ messageTopic = self.safe_string_2(message, 'topic', 'group')
1754
+ unSubMessageTopic = 'unsubscribe::' + messageTopic
1755
+ # one message includes info about one unsubscription only even if we requested multiple
1756
+ # so we can not just create subscription object in unWatch method and use it here
1757
+ # we need to reconstruct subscription params from the messageTopic
1758
+ subscription = self.get_un_sub_params(messageTopic)
1759
+ subHash = self.safe_string(subscription, 'subHash')
1760
+ unsubHash = 'unsubscribe::' + subHash
1761
+ subHashIsPrefix = self.safe_bool(subscription, 'subHashIsPrefix', False)
1762
+ # clean up both ways of storing subscription and unsubscription
1763
+ self.clean_unsubscription(client, subHash, unsubHash, subHashIsPrefix)
1764
+ self.clean_unsubscription(client, messageTopic, unSubMessageTopic, subHashIsPrefix)
1765
+ self.clean_cache(subscription)
1766
+
1767
+ def get_un_sub_params(self, messageTopic):
1768
+ parts = messageTopic.split(':')
1769
+ channel = self.safe_string(parts, 0)
1770
+ marketTypeAndTopic = channel.split('/')
1771
+ rawMarketType = self.safe_string_lower(marketTypeAndTopic, 0)
1772
+ marketType = self.parse_market_type(rawMarketType)
1773
+ topic = self.safe_string(marketTypeAndTopic, 1)
1774
+ thirdPart = self.safe_string(marketTypeAndTopic, 2)
1775
+ if thirdPart is not None:
1776
+ topic += '/' + thirdPart
1777
+ marketId = self.safe_string(parts, 1)
1778
+ symbols = []
1779
+ symbol = None
1780
+ subHash = topic
1781
+ hashDelimiter = ':'
1782
+ subHashIsPrefix = False
1783
+ parsedTopic = self.parse_topic(topic)
1784
+ if (parsedTopic == 'orders') or (parsedTopic == 'positions'):
1785
+ subHash = parsedTopic
1786
+ hashDelimiter = '::'
1787
+ if (marketId is not None) and (marketId != 'ALL_SYMBOLS'):
1788
+ # if marketId is defined, we have a single symbol subscription
1789
+ delimiter = '_' if (marketType == 'spot') else ''
1790
+ market = self.safe_market(marketId, None, delimiter, marketType)
1791
+ symbol = market['symbol']
1792
+ subHash += hashDelimiter + symbol
1793
+ symbols.append(symbol)
1794
+ else:
1795
+ subHashIsPrefix = True # need to clean all subHashes with self prefix
1796
+ symbolsAndTimeframes = []
1797
+ if topic.startswith('kline'):
1798
+ interval = topic.replace('kline', '')
1799
+ if interval.startswith('Bin'):
1800
+ # swap market
1801
+ interval = interval.replace('Bin', '')
1802
+ timeframes = self.safe_dict(self.options, 'timeframes', {})
1803
+ timeframe = self.find_timeframe(interval, timeframes)
1804
+ symbolAndTimeframe = [symbol, timeframe]
1805
+ symbolsAndTimeframes.append(symbolAndTimeframe)
1806
+ result = {
1807
+ 'topic': parsedTopic,
1808
+ 'symbols': symbols,
1809
+ 'subHash': subHash,
1810
+ 'symbolsAndTimeframes': symbolsAndTimeframes,
1811
+ 'subHashIsPrefix': subHashIsPrefix,
1812
+ }
1813
+ return result
1814
+
1815
+ def parse_topic(self, topic):
1816
+ if topic.startswith('depth'):
1817
+ return 'orderbook'
1818
+ if topic.startswith('kline'):
1819
+ return 'ohlcv'
1820
+ topics = {
1821
+ 'ticker': 'ticker',
1822
+ 'trade': 'trades',
1823
+ 'user/order': 'orders',
1824
+ 'user/orders': 'orders',
1825
+ 'order': 'orders',
1826
+ 'position': 'positions',
1827
+ }
1828
+ return self.safe_string(topics, topic, topic)
1829
+
1830
+ def parse_market_type(self, marketType: str):
1831
+ types = {
1832
+ 'spot': 'spot',
1833
+ 'futures': 'swap',
1834
+ }
1835
+ return self.safe_string(types, marketType, marketType)
1836
+
1837
+ def handle_message(self, client: Client, message):
1838
+ if self.handle_error_message(client, message):
1839
+ return
1840
+ #
1841
+ # {"event":"error","message":"Unrecognized request: {\"event\":\"subscribe\",\"channel\":\"spot/depth:BTC-USDT\"}","errorCode":30039}
1842
+ #
1843
+ # subscribe events on spot:
1844
+ #
1845
+ # {"event":"subscribe", "topic":"spot/kline1m:BTC_USDT"}
1846
+ #
1847
+ # subscribe on contracts:
1848
+ #
1849
+ # {"action":"subscribe", "group":"futures/klineBin1m:BTCUSDT", "success":true, "request":{"action":"subscribe", "args":["futures/klineBin1m:BTCUSDT"]}}
1850
+ #
1851
+ # regular updates - spot
1852
+ #
1853
+ # {
1854
+ # "table": "spot/depth",
1855
+ # "action": "partial",
1856
+ # "data": [
1857
+ # {
1858
+ # "instrument_id": "BTC-USDT",
1859
+ # "asks": [
1860
+ # ["5301.8", "0.03763319", "1"],
1861
+ # ["5302.4", "0.00305", "2"],
1862
+ # ],
1863
+ # "bids": [
1864
+ # ["5301.7", "0.58911427", "6"],
1865
+ # ["5301.6", "0.01222922", "4"],
1866
+ # ],
1867
+ # "timestamp": "2020-03-16T03:25:00.440Z",
1868
+ # "checksum": -2088736623
1869
+ # }
1870
+ # ]
1871
+ # }
1872
+ #
1873
+ # regular updates - contracts
1874
+ #
1875
+ # {
1876
+ # group: "futures/klineBin1m:BTCUSDT",
1877
+ # data: {
1878
+ # symbol: "BTCUSDT",
1879
+ # items: [{o: "67944.7", "h": ....}],
1880
+ # },
1881
+ # }
1882
+ #
1883
+ # {data: '', table: "spot/user/order"}
1884
+ #
1885
+ # the only realiable way(for both spot & swap) is to check 'data' key
1886
+ isDataUpdate = ('data' in message)
1887
+ if not isDataUpdate:
1888
+ event = self.safe_string_2(message, 'event', 'action')
1889
+ if event is not None:
1890
+ methods: dict = {
1891
+ # 'info': self.handleSystemStatus,
1892
+ 'login': self.handle_authenticate,
1893
+ 'access': self.handle_authenticate,
1894
+ 'subscribe': self.handle_subscription_status,
1895
+ 'unsubscribe': self.handle_un_subscription,
1896
+ }
1897
+ method = self.safe_value(methods, event)
1898
+ if method is not None:
1899
+ method(client, message)
1900
+ else:
1901
+ channel = self.safe_string_2(message, 'table', 'group')
1902
+ methods: dict = {
1903
+ 'depth': self.handle_order_book,
1904
+ 'ticker': self.handle_ticker,
1905
+ 'trade': self.handle_trade,
1906
+ 'kline': self.handle_ohlcv,
1907
+ 'order': self.handle_orders,
1908
+ 'position': self.handle_positions,
1909
+ 'balance': self.handle_balance,
1910
+ 'asset': self.handle_balance,
1911
+ }
1912
+ keys = list(methods.keys())
1913
+ for i in range(0, len(keys)):
1914
+ key = keys[i]
1915
+ if channel.find(key) >= 0:
1916
+ method = self.safe_value(methods, key)
1917
+ method(client, message)