ccxt 4.2.77__py2.py3-none-any.whl → 4.4.49__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (546) hide show
  1. ccxt/__init__.py +36 -14
  2. ccxt/abstract/alpaca.py +4 -0
  3. ccxt/abstract/bigone.py +1 -1
  4. ccxt/abstract/binance.py +112 -48
  5. ccxt/abstract/binancecoinm.py +112 -48
  6. ccxt/abstract/binanceus.py +147 -83
  7. ccxt/abstract/binanceusdm.py +112 -48
  8. ccxt/abstract/bingx.py +133 -78
  9. ccxt/abstract/bitbank.py +5 -0
  10. ccxt/abstract/bitfinex.py +136 -65
  11. ccxt/abstract/bitfinex1.py +69 -0
  12. ccxt/abstract/bitflyer.py +1 -0
  13. ccxt/abstract/bitget.py +8 -1
  14. ccxt/abstract/bitmart.py +13 -1
  15. ccxt/abstract/bitopro.py +1 -0
  16. ccxt/abstract/bitpanda.py +0 -12
  17. ccxt/abstract/bitrue.py +3 -3
  18. ccxt/abstract/bitstamp.py +26 -3
  19. ccxt/abstract/blofin.py +24 -0
  20. ccxt/abstract/btcbox.py +1 -0
  21. ccxt/abstract/bybit.py +29 -14
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbase.py +6 -0
  24. ccxt/abstract/coinbaseadvanced.py +94 -0
  25. ccxt/abstract/{coinbasepro.py → coinbaseexchange.py} +1 -0
  26. ccxt/abstract/coinbaseinternational.py +1 -1
  27. ccxt/abstract/coincatch.py +94 -0
  28. ccxt/abstract/coinex.py +233 -123
  29. ccxt/abstract/coinmetro.py +1 -0
  30. ccxt/abstract/cryptocom.py +14 -0
  31. ccxt/abstract/defx.py +69 -0
  32. ccxt/abstract/deribit.py +1 -0
  33. ccxt/abstract/digifinex.py +1 -0
  34. ccxt/abstract/ellipx.py +25 -0
  35. ccxt/abstract/gate.py +20 -0
  36. ccxt/abstract/gateio.py +20 -0
  37. ccxt/abstract/gemini.py +1 -0
  38. ccxt/abstract/hashkey.py +67 -0
  39. ccxt/abstract/hyperliquid.py +1 -1
  40. ccxt/abstract/independentreserve.py +6 -0
  41. ccxt/abstract/kraken.py +4 -3
  42. ccxt/abstract/krakenfutures.py +4 -0
  43. ccxt/abstract/kucoin.py +24 -0
  44. ccxt/abstract/kucoinfutures.py +34 -0
  45. ccxt/abstract/luno.py +2 -0
  46. ccxt/abstract/mexc.py +4 -0
  47. ccxt/abstract/myokx.py +340 -0
  48. ccxt/abstract/oceanex.py +5 -0
  49. ccxt/abstract/okx.py +30 -0
  50. ccxt/abstract/onetrading.py +0 -12
  51. ccxt/abstract/oxfun.py +34 -0
  52. ccxt/abstract/paradex.py +40 -0
  53. ccxt/abstract/phemex.py +1 -0
  54. ccxt/abstract/upbit.py +4 -0
  55. ccxt/abstract/vertex.py +19 -0
  56. ccxt/abstract/whitebit.py +31 -1
  57. ccxt/abstract/woo.py +6 -2
  58. ccxt/abstract/woofipro.py +119 -0
  59. ccxt/abstract/xt.py +153 -0
  60. ccxt/abstract/zonda.py +6 -0
  61. ccxt/ace.py +164 -60
  62. ccxt/alpaca.py +727 -63
  63. ccxt/ascendex.py +395 -249
  64. ccxt/async_support/__init__.py +36 -14
  65. ccxt/async_support/ace.py +164 -60
  66. ccxt/async_support/alpaca.py +727 -63
  67. ccxt/async_support/ascendex.py +396 -249
  68. ccxt/async_support/base/exchange.py +531 -155
  69. ccxt/async_support/base/ws/aiohttp_client.py +28 -5
  70. ccxt/async_support/base/ws/cache.py +3 -2
  71. ccxt/async_support/base/ws/client.py +26 -5
  72. ccxt/async_support/base/ws/fast_client.py +4 -3
  73. ccxt/async_support/base/ws/functions.py +1 -1
  74. ccxt/async_support/base/ws/future.py +40 -31
  75. ccxt/async_support/base/ws/order_book_side.py +3 -0
  76. ccxt/async_support/bequant.py +1 -1
  77. ccxt/async_support/bigone.py +329 -202
  78. ccxt/async_support/binance.py +3030 -1087
  79. ccxt/async_support/binancecoinm.py +2 -1
  80. ccxt/async_support/binanceus.py +12 -1
  81. ccxt/async_support/binanceusdm.py +3 -1
  82. ccxt/async_support/bingx.py +3205 -937
  83. ccxt/async_support/bit2c.py +119 -38
  84. ccxt/async_support/bitbank.py +215 -76
  85. ccxt/async_support/bitbns.py +124 -53
  86. ccxt/async_support/bitfinex.py +3236 -1078
  87. ccxt/async_support/bitfinex1.py +1711 -0
  88. ccxt/async_support/bitflyer.py +238 -49
  89. ccxt/async_support/bitget.py +1525 -573
  90. ccxt/async_support/bithumb.py +199 -65
  91. ccxt/async_support/bitmart.py +1320 -435
  92. ccxt/async_support/bitmex.py +308 -111
  93. ccxt/async_support/bitopro.py +256 -96
  94. ccxt/async_support/bitrue.py +365 -233
  95. ccxt/async_support/bitso.py +201 -89
  96. ccxt/async_support/bitstamp.py +438 -269
  97. ccxt/async_support/bitteam.py +179 -73
  98. ccxt/async_support/bitvavo.py +180 -70
  99. ccxt/async_support/bl3p.py +92 -25
  100. ccxt/async_support/blockchaincom.py +193 -79
  101. ccxt/async_support/blofin.py +392 -148
  102. ccxt/async_support/btcalpha.py +161 -55
  103. ccxt/async_support/btcbox.py +250 -34
  104. ccxt/async_support/btcmarkets.py +232 -85
  105. ccxt/async_support/btcturk.py +159 -60
  106. ccxt/async_support/bybit.py +2231 -1193
  107. ccxt/async_support/cex.py +1409 -1329
  108. ccxt/async_support/coinbase.py +1454 -287
  109. ccxt/async_support/coinbaseadvanced.py +17 -0
  110. ccxt/async_support/{coinbasepro.py → coinbaseexchange.py} +233 -99
  111. ccxt/async_support/coinbaseinternational.py +428 -88
  112. ccxt/async_support/coincatch.py +5152 -0
  113. ccxt/async_support/coincheck.py +121 -38
  114. ccxt/async_support/coinex.py +4020 -3339
  115. ccxt/async_support/coinlist.py +273 -116
  116. ccxt/async_support/coinmate.py +204 -97
  117. ccxt/async_support/coinmetro.py +203 -110
  118. ccxt/async_support/coinone.py +142 -68
  119. ccxt/async_support/coinsph.py +223 -97
  120. ccxt/async_support/coinspot.py +137 -62
  121. ccxt/async_support/cryptocom.py +515 -185
  122. ccxt/async_support/currencycom.py +203 -85
  123. ccxt/async_support/defx.py +2066 -0
  124. ccxt/async_support/delta.py +404 -109
  125. ccxt/async_support/deribit.py +639 -323
  126. ccxt/async_support/digifinex.py +465 -233
  127. ccxt/async_support/ellipx.py +1887 -0
  128. ccxt/async_support/exmo.py +317 -128
  129. ccxt/async_support/gate.py +1472 -463
  130. ccxt/async_support/gemini.py +206 -84
  131. ccxt/async_support/hashkey.py +4164 -0
  132. ccxt/async_support/hitbtc.py +433 -178
  133. ccxt/async_support/hollaex.py +207 -83
  134. ccxt/async_support/htx.py +1095 -563
  135. ccxt/async_support/huobijp.py +178 -56
  136. ccxt/async_support/hyperliquid.py +1678 -292
  137. ccxt/async_support/idex.py +219 -95
  138. ccxt/async_support/independentreserve.py +300 -31
  139. ccxt/async_support/indodax.py +226 -62
  140. ccxt/async_support/kraken.py +871 -354
  141. ccxt/async_support/krakenfutures.py +324 -100
  142. ccxt/async_support/kucoin.py +917 -357
  143. ccxt/async_support/kucoinfutures.py +1004 -149
  144. ccxt/async_support/kuna.py +198 -107
  145. ccxt/async_support/latoken.py +199 -79
  146. ccxt/async_support/lbank.py +360 -113
  147. ccxt/async_support/luno.py +185 -62
  148. ccxt/async_support/lykke.py +168 -55
  149. ccxt/async_support/mercado.py +101 -29
  150. ccxt/async_support/mexc.py +995 -429
  151. ccxt/async_support/myokx.py +53 -0
  152. ccxt/async_support/ndax.py +234 -82
  153. ccxt/async_support/novadax.py +195 -75
  154. ccxt/async_support/oceanex.py +244 -59
  155. ccxt/async_support/okcoin.py +301 -165
  156. ccxt/async_support/okx.py +1776 -454
  157. ccxt/async_support/onetrading.py +198 -414
  158. ccxt/async_support/oxfun.py +2898 -0
  159. ccxt/async_support/p2b.py +142 -52
  160. ccxt/async_support/paradex.py +2085 -0
  161. ccxt/async_support/paymium.py +56 -32
  162. ccxt/async_support/phemex.py +572 -196
  163. ccxt/async_support/poloniex.py +218 -95
  164. ccxt/async_support/poloniexfutures.py +260 -92
  165. ccxt/async_support/probit.py +143 -110
  166. ccxt/async_support/timex.py +123 -70
  167. ccxt/async_support/tokocrypto.py +129 -93
  168. ccxt/async_support/tradeogre.py +39 -25
  169. ccxt/async_support/upbit.py +322 -113
  170. ccxt/async_support/vertex.py +2983 -0
  171. ccxt/async_support/wavesexchange.py +227 -173
  172. ccxt/async_support/wazirx.py +145 -65
  173. ccxt/async_support/whitebit.py +533 -138
  174. ccxt/async_support/woo.py +1137 -296
  175. ccxt/async_support/woofipro.py +2716 -0
  176. ccxt/async_support/xt.py +4628 -0
  177. ccxt/async_support/yobit.py +160 -92
  178. ccxt/async_support/zaif.py +80 -33
  179. ccxt/async_support/zonda.py +140 -69
  180. ccxt/base/errors.py +51 -20
  181. ccxt/base/exchange.py +1722 -480
  182. ccxt/base/precise.py +10 -0
  183. ccxt/base/types.py +223 -4
  184. ccxt/bequant.py +1 -1
  185. ccxt/bigone.py +329 -202
  186. ccxt/binance.py +3030 -1087
  187. ccxt/binancecoinm.py +2 -1
  188. ccxt/binanceus.py +12 -1
  189. ccxt/binanceusdm.py +3 -1
  190. ccxt/bingx.py +3205 -937
  191. ccxt/bit2c.py +119 -38
  192. ccxt/bitbank.py +215 -76
  193. ccxt/bitbns.py +124 -53
  194. ccxt/bitfinex.py +3235 -1078
  195. ccxt/bitfinex1.py +1710 -0
  196. ccxt/bitflyer.py +238 -49
  197. ccxt/bitget.py +1525 -573
  198. ccxt/bithumb.py +198 -65
  199. ccxt/bitmart.py +1320 -435
  200. ccxt/bitmex.py +308 -111
  201. ccxt/bitopro.py +256 -96
  202. ccxt/bitrue.py +365 -233
  203. ccxt/bitso.py +201 -89
  204. ccxt/bitstamp.py +438 -269
  205. ccxt/bitteam.py +179 -73
  206. ccxt/bitvavo.py +180 -70
  207. ccxt/bl3p.py +92 -25
  208. ccxt/blockchaincom.py +193 -79
  209. ccxt/blofin.py +392 -148
  210. ccxt/btcalpha.py +161 -55
  211. ccxt/btcbox.py +250 -34
  212. ccxt/btcmarkets.py +232 -85
  213. ccxt/btcturk.py +159 -60
  214. ccxt/bybit.py +2231 -1193
  215. ccxt/cex.py +1408 -1329
  216. ccxt/coinbase.py +1454 -287
  217. ccxt/coinbaseadvanced.py +17 -0
  218. ccxt/{coinbasepro.py → coinbaseexchange.py} +233 -99
  219. ccxt/coinbaseinternational.py +428 -88
  220. ccxt/coincatch.py +5152 -0
  221. ccxt/coincheck.py +121 -38
  222. ccxt/coinex.py +4020 -3339
  223. ccxt/coinlist.py +273 -116
  224. ccxt/coinmate.py +204 -97
  225. ccxt/coinmetro.py +203 -110
  226. ccxt/coinone.py +142 -68
  227. ccxt/coinsph.py +223 -97
  228. ccxt/coinspot.py +137 -62
  229. ccxt/cryptocom.py +515 -185
  230. ccxt/currencycom.py +203 -85
  231. ccxt/defx.py +2065 -0
  232. ccxt/delta.py +404 -109
  233. ccxt/deribit.py +639 -323
  234. ccxt/digifinex.py +465 -233
  235. ccxt/ellipx.py +1887 -0
  236. ccxt/exmo.py +317 -128
  237. ccxt/gate.py +1472 -463
  238. ccxt/gemini.py +206 -84
  239. ccxt/hashkey.py +4164 -0
  240. ccxt/hitbtc.py +433 -178
  241. ccxt/hollaex.py +207 -83
  242. ccxt/htx.py +1095 -563
  243. ccxt/huobijp.py +178 -56
  244. ccxt/hyperliquid.py +1677 -292
  245. ccxt/idex.py +219 -95
  246. ccxt/independentreserve.py +299 -31
  247. ccxt/indodax.py +226 -62
  248. ccxt/kraken.py +871 -354
  249. ccxt/krakenfutures.py +324 -100
  250. ccxt/kucoin.py +917 -357
  251. ccxt/kucoinfutures.py +1004 -149
  252. ccxt/kuna.py +198 -107
  253. ccxt/latoken.py +199 -79
  254. ccxt/lbank.py +360 -113
  255. ccxt/luno.py +185 -62
  256. ccxt/lykke.py +168 -55
  257. ccxt/mercado.py +101 -29
  258. ccxt/mexc.py +994 -429
  259. ccxt/myokx.py +53 -0
  260. ccxt/ndax.py +234 -82
  261. ccxt/novadax.py +195 -75
  262. ccxt/oceanex.py +244 -59
  263. ccxt/okcoin.py +301 -165
  264. ccxt/okx.py +1776 -454
  265. ccxt/onetrading.py +198 -414
  266. ccxt/oxfun.py +2897 -0
  267. ccxt/p2b.py +142 -52
  268. ccxt/paradex.py +2085 -0
  269. ccxt/paymium.py +56 -32
  270. ccxt/phemex.py +572 -196
  271. ccxt/poloniex.py +218 -95
  272. ccxt/poloniexfutures.py +260 -92
  273. ccxt/pro/__init__.py +29 -5
  274. ccxt/pro/alpaca.py +32 -17
  275. ccxt/pro/ascendex.py +62 -14
  276. ccxt/pro/bequant.py +4 -0
  277. ccxt/pro/binance.py +1596 -329
  278. ccxt/pro/binancecoinm.py +1 -0
  279. ccxt/pro/binanceus.py +2 -9
  280. ccxt/pro/binanceusdm.py +2 -0
  281. ccxt/pro/bingx.py +527 -134
  282. ccxt/pro/bitcoincom.py +4 -1
  283. ccxt/pro/bitfinex.py +731 -266
  284. ccxt/pro/bitfinex1.py +635 -0
  285. ccxt/pro/bitget.py +726 -357
  286. ccxt/pro/bithumb.py +380 -0
  287. ccxt/pro/bitmart.py +143 -39
  288. ccxt/pro/bitmex.py +199 -40
  289. ccxt/pro/bitopro.py +25 -13
  290. ccxt/pro/bitrue.py +31 -32
  291. ccxt/pro/bitstamp.py +7 -6
  292. ccxt/pro/bitvavo.py +203 -81
  293. ccxt/pro/blockchaincom.py +30 -17
  294. ccxt/pro/blofin.py +692 -0
  295. ccxt/pro/bybit.py +791 -82
  296. ccxt/pro/cex.py +99 -51
  297. ccxt/pro/coinbase.py +220 -30
  298. ccxt/{async_support/hitbtc3.py → pro/coinbaseadvanced.py} +5 -5
  299. ccxt/pro/{coinbasepro.py → coinbaseexchange.py} +19 -19
  300. ccxt/pro/coinbaseinternational.py +193 -30
  301. ccxt/pro/coincatch.py +1464 -0
  302. ccxt/pro/coincheck.py +11 -6
  303. ccxt/pro/coinex.py +965 -665
  304. ccxt/pro/coinone.py +17 -10
  305. ccxt/pro/cryptocom.py +446 -66
  306. ccxt/pro/currencycom.py +11 -10
  307. ccxt/pro/defx.py +832 -0
  308. ccxt/pro/deribit.py +167 -31
  309. ccxt/pro/exmo.py +252 -20
  310. ccxt/pro/gate.py +729 -64
  311. ccxt/pro/gemini.py +44 -26
  312. ccxt/pro/hashkey.py +802 -0
  313. ccxt/pro/hitbtc.py +208 -103
  314. ccxt/pro/hollaex.py +25 -9
  315. ccxt/pro/htx.py +83 -39
  316. ccxt/pro/huobijp.py +17 -16
  317. ccxt/pro/hyperliquid.py +502 -31
  318. ccxt/pro/idex.py +28 -13
  319. ccxt/pro/independentreserve.py +21 -16
  320. ccxt/pro/kraken.py +298 -51
  321. ccxt/pro/krakenfutures.py +166 -75
  322. ccxt/pro/kucoin.py +395 -77
  323. ccxt/pro/kucoinfutures.py +400 -99
  324. ccxt/pro/lbank.py +52 -31
  325. ccxt/pro/luno.py +12 -10
  326. ccxt/pro/mexc.py +400 -50
  327. ccxt/pro/myokx.py +28 -0
  328. ccxt/pro/ndax.py +25 -12
  329. ccxt/pro/okcoin.py +28 -9
  330. ccxt/pro/okx.py +935 -124
  331. ccxt/pro/onetrading.py +41 -24
  332. ccxt/pro/oxfun.py +1054 -0
  333. ccxt/pro/p2b.py +100 -24
  334. ccxt/pro/paradex.py +352 -0
  335. ccxt/pro/phemex.py +92 -33
  336. ccxt/pro/poloniex.py +128 -49
  337. ccxt/pro/poloniexfutures.py +53 -32
  338. ccxt/pro/probit.py +92 -85
  339. ccxt/pro/upbit.py +401 -8
  340. ccxt/pro/vertex.py +943 -0
  341. ccxt/pro/wazirx.py +46 -28
  342. ccxt/pro/whitebit.py +65 -12
  343. ccxt/pro/woo.py +437 -65
  344. ccxt/pro/woofipro.py +1271 -0
  345. ccxt/pro/xt.py +1067 -0
  346. ccxt/probit.py +143 -110
  347. ccxt/static_dependencies/__init__.py +1 -1
  348. ccxt/static_dependencies/lark/__init__.py +38 -0
  349. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  350. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  351. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  352. ccxt/static_dependencies/lark/common.py +86 -0
  353. ccxt/static_dependencies/lark/exceptions.py +292 -0
  354. ccxt/static_dependencies/lark/grammar.py +130 -0
  355. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  356. ccxt/static_dependencies/lark/indenter.py +143 -0
  357. ccxt/static_dependencies/lark/lark.py +658 -0
  358. ccxt/static_dependencies/lark/lexer.py +678 -0
  359. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  360. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  361. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  362. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  363. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  364. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  365. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  366. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  367. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  368. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  369. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  370. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  371. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  372. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  373. ccxt/static_dependencies/lark/py.typed +0 -0
  374. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  375. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  376. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  377. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  378. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  379. ccxt/static_dependencies/lark/tree.py +267 -0
  380. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  381. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  382. ccxt/static_dependencies/lark/utils.py +343 -0
  383. ccxt/static_dependencies/lark/visitors.py +596 -0
  384. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  385. ccxt/static_dependencies/marshmallow/base.py +65 -0
  386. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  387. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  388. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  389. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  390. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  391. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  392. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  393. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  394. ccxt/static_dependencies/marshmallow/types.py +12 -0
  395. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  396. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  397. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  398. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  399. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  400. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  401. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  402. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  403. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  404. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  405. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  406. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  407. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  408. ccxt/static_dependencies/starknet/__init__.py +0 -0
  409. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  410. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  411. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  412. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  413. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  414. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  415. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  416. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  417. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  418. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  419. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  420. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  421. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  422. ccxt/static_dependencies/starknet/common.py +15 -0
  423. ccxt/static_dependencies/starknet/constants.py +39 -0
  424. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  425. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  426. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  427. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  428. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  429. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  430. ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  431. ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  432. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  433. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  434. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  435. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  436. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  437. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  438. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  439. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  440. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  441. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  442. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  443. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  444. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  445. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  446. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  447. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  448. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  449. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  450. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  451. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  452. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  453. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  454. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  455. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  456. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  457. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  458. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  459. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  460. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  461. ccxt/static_dependencies/starkware/__init__.py +0 -0
  462. ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  463. ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  464. ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  465. ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  466. ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  467. ccxt/static_dependencies/sympy/__init__.py +0 -0
  468. ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  469. ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  470. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  471. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  472. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  473. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  474. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  475. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  476. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  477. ccxt/test/{test_async.py → tests_async.py} +456 -391
  478. ccxt/test/tests_helpers.py +285 -0
  479. ccxt/test/tests_init.py +39 -0
  480. ccxt/test/{test_sync.py → tests_sync.py} +456 -393
  481. ccxt/timex.py +123 -70
  482. ccxt/tokocrypto.py +129 -93
  483. ccxt/tradeogre.py +39 -25
  484. ccxt/upbit.py +322 -113
  485. ccxt/vertex.py +2983 -0
  486. ccxt/wavesexchange.py +227 -173
  487. ccxt/wazirx.py +145 -65
  488. ccxt/whitebit.py +533 -138
  489. ccxt/woo.py +1137 -296
  490. ccxt/woofipro.py +2716 -0
  491. ccxt/xt.py +4627 -0
  492. ccxt/yobit.py +159 -92
  493. ccxt/zaif.py +80 -33
  494. ccxt/zonda.py +140 -69
  495. ccxt-4.4.49.dist-info/LICENSE.txt +21 -0
  496. ccxt-4.4.49.dist-info/METADATA +646 -0
  497. ccxt-4.4.49.dist-info/RECORD +669 -0
  498. {ccxt-4.2.77.dist-info → ccxt-4.4.49.dist-info}/WHEEL +1 -1
  499. ccxt/abstract/bitbay.py +0 -47
  500. ccxt/abstract/bitfinex2.py +0 -139
  501. ccxt/abstract/hitbtc3.py +0 -115
  502. ccxt/async_support/bitbay.py +0 -17
  503. ccxt/async_support/bitfinex2.py +0 -3496
  504. ccxt/async_support/flowbtc.py +0 -34
  505. ccxt/bitbay.py +0 -17
  506. ccxt/bitfinex2.py +0 -3496
  507. ccxt/flowbtc.py +0 -34
  508. ccxt/hitbtc3.py +0 -16
  509. ccxt/pro/bitfinex2.py +0 -1081
  510. ccxt/test/base/__init__.py +0 -28
  511. ccxt/test/base/test_account.py +0 -26
  512. ccxt/test/base/test_balance.py +0 -56
  513. ccxt/test/base/test_borrow_interest.py +0 -35
  514. ccxt/test/base/test_borrow_rate.py +0 -32
  515. ccxt/test/base/test_calculate_fee.py +0 -51
  516. ccxt/test/base/test_crypto.py +0 -127
  517. ccxt/test/base/test_currency.py +0 -76
  518. ccxt/test/base/test_datetime.py +0 -103
  519. ccxt/test/base/test_decimal_to_precision.py +0 -392
  520. ccxt/test/base/test_deep_extend.py +0 -68
  521. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  522. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  523. ccxt/test/base/test_funding_rate_history.py +0 -29
  524. ccxt/test/base/test_last_price.py +0 -32
  525. ccxt/test/base/test_ledger_entry.py +0 -45
  526. ccxt/test/base/test_ledger_item.py +0 -48
  527. ccxt/test/base/test_leverage_tier.py +0 -33
  528. ccxt/test/base/test_margin_mode.py +0 -24
  529. ccxt/test/base/test_margin_modification.py +0 -35
  530. ccxt/test/base/test_market.py +0 -190
  531. ccxt/test/base/test_number.py +0 -411
  532. ccxt/test/base/test_ohlcv.py +0 -32
  533. ccxt/test/base/test_open_interest.py +0 -32
  534. ccxt/test/base/test_order.py +0 -64
  535. ccxt/test/base/test_order_book.py +0 -63
  536. ccxt/test/base/test_position.py +0 -60
  537. ccxt/test/base/test_shared_methods.py +0 -345
  538. ccxt/test/base/test_status.py +0 -24
  539. ccxt/test/base/test_throttle.py +0 -126
  540. ccxt/test/base/test_ticker.py +0 -86
  541. ccxt/test/base/test_trade.py +0 -47
  542. ccxt/test/base/test_trading_fee.py +0 -26
  543. ccxt/test/base/test_transaction.py +0 -39
  544. ccxt-4.2.77.dist-info/METADATA +0 -626
  545. ccxt-4.2.77.dist-info/RECORD +0 -534
  546. {ccxt-4.2.77.dist-info → ccxt-4.4.49.dist-info}/top_level.txt +0 -0
ccxt/pro/gate.py CHANGED
@@ -6,13 +6,17 @@
6
6
  import ccxt.async_support
7
7
  from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Int, Order, OrderBook, Position, Str, Strings, Ticker, Tickers, Trade
9
+ from ccxt.base.types import Balances, Int, Liquidation, Market, MarketType, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
10
10
  from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
+ from typing import Any
13
+ from ccxt.base.errors import ExchangeError
14
+ from ccxt.base.errors import AuthenticationError
12
15
  from ccxt.base.errors import ArgumentsRequired
13
16
  from ccxt.base.errors import BadRequest
14
- from ccxt.base.errors import InvalidNonce
15
- from ccxt.base.errors import AuthenticationError
17
+ from ccxt.base.errors import NotSupported
18
+ from ccxt.base.errors import ChecksumError
19
+ from ccxt.base.precise import Precise
16
20
 
17
21
 
18
22
  class gate(ccxt.async_support.gate):
@@ -21,6 +25,27 @@ class gate(ccxt.async_support.gate):
21
25
  return self.deep_extend(super(gate, self).describe(), {
22
26
  'has': {
23
27
  'ws': True,
28
+ 'cancelAllOrdersWs': True,
29
+ 'cancelOrderWs': True,
30
+ 'createMarketBuyOrderWithCostWs': True,
31
+ 'createMarketOrderWs': True,
32
+ 'createMarketOrderWithCostWs': False,
33
+ 'createMarketSellOrderWithCostWs': False,
34
+ 'createOrderWs': True,
35
+ 'createOrdersWs': True,
36
+ 'createPostOnlyOrderWs': True,
37
+ 'createReduceOnlyOrderWs': True,
38
+ 'createStopLimitOrderWs': True,
39
+ 'createStopLossOrderWs': True,
40
+ 'createStopMarketOrderWs': False,
41
+ 'createStopOrderWs': True,
42
+ 'createTakeProfitOrderWs': True,
43
+ 'createTriggerOrderWs': True,
44
+ 'editOrderWs': True,
45
+ 'fetchOrderWs': True,
46
+ 'fetchOrdersWs': False,
47
+ 'fetchOpenOrdersWs': True,
48
+ 'fetchClosedOrdersWs': True,
24
49
  'watchOrderBook': True,
25
50
  'watchTicker': True,
26
51
  'watchTickers': True,
@@ -30,6 +55,10 @@ class gate(ccxt.async_support.gate):
30
55
  'watchOHLCV': True,
31
56
  'watchBalance': True,
32
57
  'watchOrders': True,
58
+ 'watchLiquidations': False,
59
+ 'watchLiquidationsForSymbols': False,
60
+ 'watchMyLiquidations': True,
61
+ 'watchMyLiquidationsForSymbols': True,
33
62
  'watchPositions': True,
34
63
  },
35
64
  'urls': {
@@ -77,6 +106,7 @@ class gate(ccxt.async_support.gate):
77
106
  'interval': '100ms',
78
107
  'snapshotDelay': 10, # how many deltas to cache before fetching a snapshot
79
108
  'snapshotMaxRetries': 3,
109
+ 'checksum': True,
80
110
  },
81
111
  'watchBalance': {
82
112
  'settle': 'usdt', # or btc
@@ -90,15 +120,248 @@ class gate(ccxt.async_support.gate):
90
120
  'exceptions': {
91
121
  'ws': {
92
122
  'exact': {
123
+ '1': BadRequest,
93
124
  '2': BadRequest,
94
125
  '4': AuthenticationError,
95
126
  '6': AuthenticationError,
96
127
  '11': AuthenticationError,
97
128
  },
129
+ 'broad': {},
98
130
  },
99
131
  },
100
132
  })
101
133
 
134
+ async def create_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
135
+ """
136
+
137
+ https://www.gate.io/docs/developers/apiv4/ws/en/#order-place
138
+ https://www.gate.io/docs/developers/futures/ws/en/#order-place
139
+
140
+ Create an order on the exchange
141
+ :param str symbol: Unified CCXT market symbol
142
+ :param str type: 'limit' or 'market' *"market" is contract only*
143
+ :param str side: 'buy' or 'sell'
144
+ :param float amount: the amount of currency to trade
145
+ :param float [price]: *ignored in "market" orders* the price at which the order is to be fulfilled at in units of the quote currency
146
+ :param dict [params]: extra parameters specific to the exchange API endpoint
147
+ :param float [params.stopPrice]: The price at which a trigger order is triggered at
148
+ :param str [params.timeInForce]: "GTC", "IOC", or "PO"
149
+ :param float [params.stopLossPrice]: The price at which a stop loss order is triggered at
150
+ :param float [params.takeProfitPrice]: The price at which a take profit order is triggered at
151
+ :param str [params.marginMode]: 'cross' or 'isolated' - marginMode for margin trading if not provided self.options['defaultMarginMode'] is used
152
+ :param int [params.iceberg]: Amount to display for the iceberg order, Null or 0 for normal orders, Set to -1 to hide the order completely
153
+ :param str [params.text]: User defined information
154
+ :param str [params.account]: *spot and margin only* "spot", "margin" or "cross_margin"
155
+ :param bool [params.auto_borrow]: *margin only* Used in margin or cross margin trading to allow automatic loan of insufficient amount if balance is not enough
156
+ :param str [params.settle]: *contract only* Unified Currency Code for settle currency
157
+ :param bool [params.reduceOnly]: *contract only* Indicates if self order is to reduce the size of a position
158
+ :param bool [params.close]: *contract only* Set to close the position, with size set to 0
159
+ :param bool [params.auto_size]: *contract only* Set side to close dual-mode position, close_long closes the long side, while close_short the short one, size also needs to be set to 0
160
+ :param int [params.price_type]: *contract only* 0 latest deal price, 1 mark price, 2 index price
161
+ :param float [params.cost]: *spot market buy only* the quote quantity that can be used alternative for the amount
162
+ :returns dict|None: `An order structure <https://docs.ccxt.com/#/?id=order-structure>`
163
+ """
164
+ await self.load_markets()
165
+ market = self.market(symbol)
166
+ symbol = market['symbol']
167
+ messageType = self.get_type_by_market(market)
168
+ channel = messageType + '.order_place'
169
+ url = self.get_url_by_market(market)
170
+ params['textIsRequired'] = True
171
+ request = self.create_order_request(symbol, type, side, amount, price, params)
172
+ await self.authenticate(url, messageType)
173
+ rawOrder = await self.request_private(url, request, channel)
174
+ order = self.parse_order(rawOrder, market)
175
+ return order
176
+
177
+ async def create_orders_ws(self, orders: List[OrderRequest], params={}):
178
+ """
179
+ create a list of trade orders
180
+
181
+ https://www.gate.io/docs/developers/futures/ws/en/#order-batch-place
182
+
183
+ :param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
184
+ :param dict [params]: extra parameters specific to the exchange API endpoint
185
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
186
+ """
187
+ await self.load_markets()
188
+ request = self.createOrdersRequest(orders, params)
189
+ firstOrder = orders[0]
190
+ market = self.market(firstOrder['symbol'])
191
+ if market['swap'] is not True:
192
+ raise NotSupported(self.id + ' createOrdersWs is not supported for swap markets')
193
+ messageType = self.get_type_by_market(market)
194
+ channel = messageType + '.order_batch_place'
195
+ url = self.get_url_by_market(market)
196
+ await self.authenticate(url, messageType)
197
+ rawOrders = await self.request_private(url, request, channel)
198
+ return self.parse_orders(rawOrders, market)
199
+
200
+ async def cancel_all_orders_ws(self, symbol: Str = None, params={}):
201
+ """
202
+ cancel all open orders
203
+
204
+ https://www.gate.io/docs/developers/futures/ws/en/#cancel-all-open-orders-matched
205
+ https://www.gate.io/docs/developers/apiv4/ws/en/#order-cancel-all-with-specified-currency-pair
206
+
207
+ :param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
208
+ :param dict [params]: extra parameters specific to the exchange API endpoint
209
+ :param str [params.channel]: the channel to use, defaults to spot.order_cancel_cp or futures.order_cancel_cp
210
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
211
+ """
212
+ await self.load_markets()
213
+ market = None if (symbol is None) else self.market(symbol)
214
+ trigger = self.safe_bool_2(params, 'stop', 'trigger')
215
+ messageType = self.get_type_by_market(market)
216
+ channel = messageType + '.order_cancel_cp'
217
+ channel, params = self.handle_option_and_params(params, 'cancelAllOrdersWs', 'channel', channel)
218
+ url = self.get_url_by_market(market)
219
+ params = self.omit(params, ['stop', 'trigger'])
220
+ type, query = self.handle_market_type_and_params('cancelAllOrders', market, params)
221
+ request, requestParams = self.multiOrderSpotPrepareRequest(market, trigger, query) if (type == 'spot') else self.prepareRequest(market, type, query)
222
+ await self.authenticate(url, messageType)
223
+ rawOrders = await self.request_private(url, self.extend(request, requestParams), channel)
224
+ return self.parse_orders(rawOrders, market)
225
+
226
+ async def cancel_order_ws(self, id: str, symbol: Str = None, params={}):
227
+ """
228
+ Cancels an open order
229
+
230
+ https://www.gate.io/docs/developers/apiv4/ws/en/#order-cancel
231
+ https://www.gate.io/docs/developers/futures/ws/en/#order-cancel
232
+
233
+ :param str id: Order id
234
+ :param str symbol: Unified market symbol
235
+ :param dict [params]: Parameters specified by the exchange api
236
+ :param bool [params.trigger]: True if the order to be cancelled is a trigger order
237
+ :returns: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
238
+ """
239
+ await self.load_markets()
240
+ market = None if (symbol is None) else self.market(symbol)
241
+ trigger = self.safe_value_n(params, ['is_stop_order', 'stop', 'trigger'], False)
242
+ params = self.omit(params, ['is_stop_order', 'stop', 'trigger'])
243
+ type, query = self.handle_market_type_and_params('cancelOrder', market, params)
244
+ request, requestParams = self.spotOrderPrepareRequest(market, trigger, query) if (type == 'spot' or type == 'margin') else self.prepareRequest(market, type, query)
245
+ messageType = self.get_type_by_market(market)
246
+ channel = messageType + '.order_cancel'
247
+ url = self.get_url_by_market(market)
248
+ await self.authenticate(url, messageType)
249
+ request['order_id'] = str(id)
250
+ res = await self.request_private(url, self.extend(request, requestParams), channel)
251
+ return self.parse_order(res, market)
252
+
253
+ async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
254
+ """
255
+ edit a trade order, gate currently only supports the modification of the price or amount fields
256
+
257
+ https://www.gate.io/docs/developers/apiv4/ws/en/#order-amend
258
+ https://www.gate.io/docs/developers/futures/ws/en/#order-amend
259
+
260
+ :param str id: order id
261
+ :param str symbol: unified symbol of the market to create an order in
262
+ :param str type: 'market' or 'limit'
263
+ :param str side: 'buy' or 'sell'
264
+ :param float amount: how much of the currency you want to trade in units of the base currency
265
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
266
+ :param dict [params]: extra parameters specific to the exchange API endpoint
267
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
268
+ """
269
+ await self.load_markets()
270
+ market = self.market(symbol)
271
+ extendedRequest = self.edit_order_request(id, symbol, type, side, amount, price, params)
272
+ messageType = self.get_type_by_market(market)
273
+ channel = messageType + '.order_amend'
274
+ url = self.get_url_by_market(market)
275
+ await self.authenticate(url, messageType)
276
+ rawOrder = await self.request_private(url, extendedRequest, channel)
277
+ return self.parse_order(rawOrder, market)
278
+
279
+ async def fetch_order_ws(self, id: str, symbol: Str = None, params={}):
280
+ """
281
+ Retrieves information on an order
282
+
283
+ https://www.gate.io/docs/developers/apiv4/ws/en/#order-status
284
+ https://www.gate.io/docs/developers/futures/ws/en/#order-status
285
+
286
+ :param str id: Order id
287
+ :param str symbol: Unified market symbol, *required for spot and margin*
288
+ :param dict [params]: Parameters specified by the exchange api
289
+ :param bool [params.trigger]: True if the order being fetched is a trigger order
290
+ :param str [params.marginMode]: 'cross' or 'isolated' - marginMode for margin trading if not provided self.options['defaultMarginMode'] is used
291
+ :param str [params.type]: 'spot', 'swap', or 'future', if not provided self.options['defaultMarginMode'] is used
292
+ :param str [params.settle]: 'btc' or 'usdt' - settle currency for perpetual swap and future - market settle currency is used if symbol is not None, default="usdt" for swap and "btc" for future
293
+ :returns: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
294
+ """
295
+ await self.load_markets()
296
+ market = None if (symbol is None) else self.market(symbol)
297
+ request, requestParams = self.fetchOrderRequest(id, symbol, params)
298
+ messageType = self.get_type_by_market(market)
299
+ channel = messageType + '.order_status'
300
+ url = self.get_url_by_market(market)
301
+ await self.authenticate(url, messageType)
302
+ rawOrder = await self.request_private(url, self.extend(request, requestParams), channel)
303
+ return self.parse_order(rawOrder, market)
304
+
305
+ async def fetch_open_orders_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
306
+ """
307
+ fetch all unfilled currently open orders
308
+
309
+ https://www.gate.io/docs/developers/futures/ws/en/#order-list
310
+
311
+ :param str symbol: unified market symbol
312
+ :param int [since]: the earliest time in ms to fetch open orders for
313
+ :param int [limit]: the maximum number of open orders structures to retrieve
314
+ :param dict [params]: extra parameters specific to the exchange API endpoint
315
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
316
+ """
317
+ return await self.fetch_orders_by_status_ws('open', symbol, since, limit, params)
318
+
319
+ async def fetch_closed_orders_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
320
+ """
321
+ fetches information on multiple closed orders made by the user
322
+
323
+ https://www.gate.io/docs/developers/futures/ws/en/#order-list
324
+
325
+ :param str symbol: unified market symbol of the market orders were made in
326
+ :param int [since]: the earliest time in ms to fetch orders for
327
+ :param int [limit]: the maximum number of order structures to retrieve
328
+ :param dict [params]: extra parameters specific to the exchange API endpoint
329
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
330
+ """
331
+ return await self.fetch_orders_by_status_ws('finished', symbol, since, limit, params)
332
+
333
+ async def fetch_orders_by_status_ws(self, status: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
334
+ """
335
+
336
+ https://www.gate.io/docs/developers/futures/ws/en/#order-list
337
+
338
+ fetches information on multiple orders made by the user by status
339
+ :param str status: requested order status
340
+ :param str symbol: unified market symbol of the market orders were made in
341
+ :param int|None [since]: the earliest time in ms to fetch orders for
342
+ :param int|None [limit]: the maximum number of order structures to retrieve
343
+ :param dict [params]: extra parameters specific to the exchange API endpoint
344
+ :param int [params.orderId]: order id to begin at
345
+ :param int [params.limit]: the maximum number of order structures to retrieve
346
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
347
+ """
348
+ await self.load_markets()
349
+ market = None
350
+ if symbol is not None:
351
+ market = self.market(symbol)
352
+ symbol = market['symbol']
353
+ if market['swap'] is not True:
354
+ raise NotSupported(self.id + ' fetchOrdersByStatusWs is only supported by swap markets. Use rest API for other markets')
355
+ request, requestParams = self.prepareOrdersByStatusRequest(status, symbol, since, limit, params)
356
+ newRequest = self.omit(request, ['settle'])
357
+ messageType = self.get_type_by_market(market)
358
+ channel = messageType + '.order_list'
359
+ url = self.get_url_by_market(market)
360
+ await self.authenticate(url, messageType)
361
+ rawOrders = await self.request_private(url, self.extend(newRequest, requestParams), channel)
362
+ orders = self.parse_orders(rawOrders, market)
363
+ return self.filter_by_symbol_since_limit(orders, symbol, since, limit)
364
+
102
365
  async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
103
366
  """
104
367
  watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
@@ -122,13 +385,38 @@ class gate(ccxt.async_support.gate):
122
385
  if market['contract']:
123
386
  stringLimit = str(limit)
124
387
  payload.append(stringLimit)
125
- subscription = {
388
+ subscription: dict = {
126
389
  'symbol': symbol,
127
390
  'limit': limit,
128
391
  }
129
392
  orderbook = await self.subscribe_public(url, messageHash, payload, channel, query, subscription)
130
393
  return orderbook.limit()
131
394
 
395
+ async def un_watch_order_book(self, symbol: str, params={}) -> Any:
396
+ """
397
+ unWatches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
398
+ :param str symbol: unified symbol of the market to fetch the order book for
399
+ :param dict [params]: extra parameters specific to the exchange API endpoint
400
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
401
+ """
402
+ await self.load_markets()
403
+ market = self.market(symbol)
404
+ symbol = market['symbol']
405
+ marketId = market['id']
406
+ interval = '100ms'
407
+ interval, params = self.handle_option_and_params(params, 'watchOrderBook', 'interval', interval)
408
+ messageType = self.get_type_by_market(market)
409
+ channel = messageType + '.order_book_update'
410
+ subMessageHash = 'orderbook' + ':' + symbol
411
+ messageHash = 'unsubscribe:orderbook' + ':' + symbol
412
+ url = self.get_url_by_market(market)
413
+ payload = [marketId, interval]
414
+ limit = self.safe_integer(params, 'limit', 100)
415
+ if market['contract']:
416
+ stringLimit = str(limit)
417
+ payload.append(stringLimit)
418
+ return await self.un_subscribe_public_multiple(url, 'orderbook', [symbol], [messageHash], [subMessageHash], payload, channel, params)
419
+
132
420
  def handle_order_book_subscription(self, client: Client, message, subscription):
133
421
  symbol = self.safe_string(subscription, 'symbol')
134
422
  limit = self.safe_integer(subscription, 'limit')
@@ -219,10 +507,12 @@ class gate(ccxt.async_support.gate):
219
507
  elif nonce >= deltaStart - 1:
220
508
  self.handle_delta(storedOrderBook, delta)
221
509
  else:
222
- error = InvalidNonce(self.id + ' orderbook update has a nonce bigger than u')
223
510
  del client.subscriptions[messageHash]
224
511
  del self.orderbooks[symbol]
225
- client.reject(error, messageHash)
512
+ checksum = self.handle_option('watchOrderBook', 'checksum', True)
513
+ if checksum:
514
+ error = ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
515
+ client.reject(error, messageHash)
226
516
  client.resolve(storedOrderBook, messageHash)
227
517
 
228
518
  def get_cache_index(self, orderBook, cache):
@@ -263,7 +553,9 @@ class gate(ccxt.async_support.gate):
263
553
 
264
554
  async def watch_ticker(self, symbol: str, params={}) -> Ticker:
265
555
  """
266
- :see: https://www.gate.io/docs/developers/apiv4/ws/en/#tickers-channel
556
+
557
+ https://www.gate.io/docs/developers/apiv4/ws/en/#tickers-channel
558
+
267
559
  watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
268
560
  :param str symbol: unified symbol of the market to fetch the ticker for
269
561
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -278,7 +570,9 @@ class gate(ccxt.async_support.gate):
278
570
 
279
571
  async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
280
572
  """
281
- :see: https://www.gate.io/docs/developers/apiv4/ws/en/#tickers-channel
573
+
574
+ https://www.gate.io/docs/developers/apiv4/ws/en/#tickers-channel
575
+
282
576
  watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
283
577
  :param str[] symbols: unified symbol of the market to fetch the ticker for
284
578
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -309,8 +603,10 @@ class gate(ccxt.async_support.gate):
309
603
 
310
604
  async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
311
605
  """
312
- :see: https://www.gate.io/docs/developers/apiv4/ws/en/#best-bid-or-ask-price
313
- :see: https://www.gate.io/docs/developers/apiv4/ws/en/#order-book-channel
606
+
607
+ https://www.gate.io/docs/developers/apiv4/ws/en/#best-bid-or-ask-price
608
+ https://www.gate.io/docs/developers/apiv4/ws/en/#order-book-channel
609
+
314
610
  watches best bid & ask for symbols
315
611
  :param str[] symbols: unified symbol of the market to fetch the ticker for
316
612
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -357,7 +653,7 @@ class gate(ccxt.async_support.gate):
357
653
  messageHashes.append(prefix + ':' + symbol)
358
654
  tickerOrBidAsk = await self.subscribe_public_multiple(url, messageHashes, marketIds, channel, params)
359
655
  if self.newUpdates:
360
- items = {}
656
+ items: dict = {}
361
657
  items[tickerOrBidAsk['symbol']] = tickerOrBidAsk
362
658
  return items
363
659
  result = self.tickers if isWatchTickers else self.bidsasks
@@ -403,7 +699,7 @@ class gate(ccxt.async_support.gate):
403
699
  async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
404
700
  """
405
701
  get the list of most recent trades for a particular symbol
406
- :param str symbol: unified symbol of the market to fetch trades for
702
+ :param str[] symbols: unified symbol of the market to fetch trades for
407
703
  :param int [since]: timestamp in ms of the earliest trade to fetch
408
704
  :param int [limit]: the maximum amount of trades to fetch
409
705
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -427,6 +723,37 @@ class gate(ccxt.async_support.gate):
427
723
  limit = trades.getLimit(tradeSymbol, limit)
428
724
  return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
429
725
 
726
+ async def un_watch_trades_for_symbols(self, symbols: List[str], params={}) -> Any:
727
+ """
728
+ get the list of most recent trades for a particular symbol
729
+ :param str[] symbols: unified symbol of the market to fetch trades for
730
+ :param dict [params]: extra parameters specific to the exchange API endpoint
731
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
732
+ """
733
+ await self.load_markets()
734
+ symbols = self.market_symbols(symbols)
735
+ marketIds = self.market_ids(symbols)
736
+ market = self.market(symbols[0])
737
+ messageType = self.get_type_by_market(market)
738
+ channel = messageType + '.trades'
739
+ subMessageHashes = []
740
+ messageHashes = []
741
+ for i in range(0, len(symbols)):
742
+ symbol = symbols[i]
743
+ subMessageHashes.append('trades:' + symbol)
744
+ messageHashes.append('unsubscribe:trades:' + symbol)
745
+ url = self.get_url_by_market(market)
746
+ return await self.un_subscribe_public_multiple(url, 'trades', symbols, messageHashes, subMessageHashes, marketIds, channel, params)
747
+
748
+ async def un_watch_trades(self, symbol: str, params={}) -> Any:
749
+ """
750
+ get the list of most recent trades for a particular symbol
751
+ :param str symbol: unified symbol of the market to fetch trades for
752
+ :param dict [params]: extra parameters specific to the exchange API endpoint
753
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
754
+ """
755
+ return await self.un_watch_trades_for_symbols([symbol], params)
756
+
430
757
  def handle_trades(self, client: Client, message):
431
758
  #
432
759
  # {
@@ -509,7 +836,7 @@ class gate(ccxt.async_support.gate):
509
836
  result = self.safe_value(message, 'result')
510
837
  if not isinstance(result, list):
511
838
  result = [result]
512
- marketIds = {}
839
+ marketIds: dict = {}
513
840
  for i in range(0, len(result)):
514
841
  ohlcv = result[i]
515
842
  subscription = self.safe_string(ohlcv, 'n', '')
@@ -544,7 +871,7 @@ class gate(ccxt.async_support.gate):
544
871
  :param int [since]: the earliest time in ms to fetch trades for
545
872
  :param int [limit]: the maximum number of trade structures to retrieve
546
873
  :param dict [params]: extra parameters specific to the exchange API endpoint
547
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
874
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
548
875
  """
549
876
  await self.load_markets()
550
877
  subType = None
@@ -608,7 +935,7 @@ class gate(ccxt.async_support.gate):
608
935
  cachedTrades = ArrayCacheBySymbolById(limit)
609
936
  self.myTrades = cachedTrades
610
937
  parsed = self.parse_trades(result)
611
- marketIds = {}
938
+ marketIds: dict = {}
612
939
  for i in range(0, len(parsed)):
613
940
  trade = parsed[i]
614
941
  cachedTrades.append(trade)
@@ -734,11 +1061,15 @@ class gate(ccxt.async_support.gate):
734
1061
 
735
1062
  async def watch_positions(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}) -> List[Position]:
736
1063
  """
737
- :see: https://www.gate.io/docs/developers/futures/ws/en/#positions-subscription
738
- :see: https://www.gate.io/docs/developers/delivery/ws/en/#positions-subscription
739
- :see: https://www.gate.io/docs/developers/options/ws/en/#positions-channel
1064
+
1065
+ https://www.gate.io/docs/developers/futures/ws/en/#positions-subscription
1066
+ https://www.gate.io/docs/developers/delivery/ws/en/#positions-subscription
1067
+ https://www.gate.io/docs/developers/options/ws/en/#positions-channel
1068
+
740
1069
  watch all open positions
741
- :param str[]|None symbols: list of unified market symbols
1070
+ :param str[] [symbols]: list of unified market symbols to watch positions for
1071
+ :param int [since]: the earliest time in ms to fetch positions for
1072
+ :param int [limit]: the maximum number of positions to retrieve
742
1073
  :param dict params: extra parameters specific to the exchange API endpoint
743
1074
  :returns dict[]: a list of `position structure <https://docs.ccxt.com/en/latest/manual.html#position-structure>`
744
1075
  """
@@ -769,7 +1100,7 @@ class gate(ccxt.async_support.gate):
769
1100
  client = self.client(url)
770
1101
  self.set_positions_cache(client, type, symbols)
771
1102
  fetchPositionsSnapshot = self.handle_option('watchPositions', 'fetchPositionsSnapshot', True)
772
- awaitPositionsSnapshot = self.safe_bool('watchPositions', 'awaitPositionsSnapshot', True)
1103
+ awaitPositionsSnapshot = self.handle_option('watchPositions', 'awaitPositionsSnapshot', True)
773
1104
  cache = self.safe_value(self.positions, type)
774
1105
  if fetchPositionsSnapshot and awaitPositionsSnapshot and cache is None:
775
1106
  return await client.future(type + ':fetchPositionsSnapshot')
@@ -864,7 +1195,7 @@ class gate(ccxt.async_support.gate):
864
1195
  :param dict [params]: extra parameters specific to the exchange API endpoint
865
1196
  :param str [params.type]: spot, margin, swap, future, or option. Required if listening to all symbols.
866
1197
  :param boolean [params.isInverse]: if future, listen to inverse or linear contracts
867
- :returns dict[]: a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure
1198
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
868
1199
  """
869
1200
  await self.load_markets()
870
1201
  market = None
@@ -939,7 +1270,7 @@ class gate(ccxt.async_support.gate):
939
1270
  if self.orders is None:
940
1271
  self.orders = ArrayCacheBySymbolById(limit)
941
1272
  stored = self.orders
942
- marketIds = {}
1273
+ marketIds: dict = {}
943
1274
  parsedOrders = self.parse_orders(orders)
944
1275
  for i in range(0, len(parsedOrders)):
945
1276
  parsed = parsedOrders[i]
@@ -951,7 +1282,7 @@ class gate(ccxt.async_support.gate):
951
1282
  elif event == 'finish':
952
1283
  status = self.safe_string(parsed, 'status')
953
1284
  if status is None:
954
- left = self.safe_number(info, 'left')
1285
+ left = self.safe_integer(info, 'left')
955
1286
  parsed['status'] = 'closed' if (left == 0) else 'canceled'
956
1287
  stored.append(parsed)
957
1288
  symbol = parsed['symbol']
@@ -963,38 +1294,226 @@ class gate(ccxt.async_support.gate):
963
1294
  client.resolve(self.orders, messageHash)
964
1295
  client.resolve(self.orders, 'orders')
965
1296
 
1297
+ async def watch_my_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
1298
+ """
1299
+ watch the public liquidations of a trading pair
1300
+
1301
+ https://www.gate.io/docs/developers/futures/ws/en/#liquidates-api
1302
+ https://www.gate.io/docs/developers/delivery/ws/en/#liquidates-api
1303
+ https://www.gate.io/docs/developers/options/ws/en/#liquidates-channel
1304
+
1305
+ :param str symbol: unified CCXT market symbol
1306
+ :param int [since]: the earliest time in ms to fetch liquidations for
1307
+ :param int [limit]: the maximum number of liquidation structures to retrieve
1308
+ :param dict [params]: exchange specific parameters for the bitmex api endpoint
1309
+ :returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
1310
+ """
1311
+ return self.watch_my_liquidations_for_symbols([symbol], since, limit, params)
1312
+
1313
+ async def watch_my_liquidations_for_symbols(self, symbols: List[str] = None, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
1314
+ """
1315
+ watch the private liquidations of a trading pair
1316
+
1317
+ https://www.gate.io/docs/developers/futures/ws/en/#liquidates-api
1318
+ https://www.gate.io/docs/developers/delivery/ws/en/#liquidates-api
1319
+ https://www.gate.io/docs/developers/options/ws/en/#liquidates-channel
1320
+
1321
+ :param str[] symbols: unified CCXT market symbols
1322
+ :param int [since]: the earliest time in ms to fetch liquidations for
1323
+ :param int [limit]: the maximum number of liquidation structures to retrieve
1324
+ :param dict [params]: exchange specific parameters for the gate api endpoint
1325
+ :returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
1326
+ """
1327
+ await self.load_markets()
1328
+ symbols = self.market_symbols(symbols, None, True, True)
1329
+ market = self.get_market_from_symbols(symbols)
1330
+ type = None
1331
+ query = None
1332
+ type, query = self.handle_market_type_and_params('watchMyLiquidationsForSymbols', market, params)
1333
+ typeId = self.get_supported_mapping(type, {
1334
+ 'future': 'futures',
1335
+ 'swap': 'futures',
1336
+ 'option': 'options',
1337
+ })
1338
+ subType = None
1339
+ subType, query = self.handle_sub_type_and_params('watchMyLiquidationsForSymbols', market, query)
1340
+ isInverse = (subType == 'inverse')
1341
+ url = self.get_url_by_market_type(type, isInverse)
1342
+ payload = []
1343
+ messageHash = ''
1344
+ if self.is_empty(symbols):
1345
+ if typeId != 'futures' and not isInverse:
1346
+ raise BadRequest(self.id + ' watchMyLiquidationsForSymbols() does not support listening to all symbols, you must call watchMyLiquidations() instead for each symbol you wish to watch.')
1347
+ messageHash = 'myLiquidations'
1348
+ payload.append('not all')
1349
+ else:
1350
+ symbolsLength = len(symbols)
1351
+ if symbolsLength != 1:
1352
+ raise BadRequest(self.id + ' watchMyLiquidationsForSymbols() only allows one symbol at a time. To listen to several symbols call watchMyLiquidationsForSymbols() several times.')
1353
+ messageHash = 'myLiquidations::' + symbols[0]
1354
+ payload.append(market['id'])
1355
+ channel = typeId + '.liquidates'
1356
+ newLiquidations = await self.subscribe_private(url, messageHash, payload, channel, query, True)
1357
+ if self.newUpdates:
1358
+ return newLiquidations
1359
+ return self.filter_by_symbols_since_limit(self.liquidations, symbols, since, limit, True)
1360
+
1361
+ def handle_liquidation(self, client: Client, message):
1362
+ #
1363
+ # future / delivery
1364
+ # {
1365
+ # "channel":"futures.liquidates",
1366
+ # "event":"update",
1367
+ # "time":1541505434,
1368
+ # "time_ms":1541505434123,
1369
+ # "result":[
1370
+ # {
1371
+ # "entry_price":209,
1372
+ # "fill_price":215.1,
1373
+ # "left":0,
1374
+ # "leverage":0.0,
1375
+ # "liq_price":213,
1376
+ # "margin":0.007816722941,
1377
+ # "mark_price":213,
1378
+ # "order_id":4093362,
1379
+ # "order_price":215.1,
1380
+ # "size":-124,
1381
+ # "time":1541486601,
1382
+ # "time_ms":1541486601123,
1383
+ # "contract":"BTC_USD",
1384
+ # "user":"1040xxxx"
1385
+ # }
1386
+ # ]
1387
+ # }
1388
+ # option
1389
+ # {
1390
+ # "channel":"options.liquidates",
1391
+ # "event":"update",
1392
+ # "time":1630654851,
1393
+ # "result":[
1394
+ # {
1395
+ # "user":"1xxxx",
1396
+ # "init_margin":1190,
1397
+ # "maint_margin":1042.5,
1398
+ # "order_margin":0,
1399
+ # "time":1639051907,
1400
+ # "time_ms":1639051907000
1401
+ # }
1402
+ # ]
1403
+ # }
1404
+ #
1405
+ rawLiquidations = self.safe_list(message, 'result', [])
1406
+ newLiquidations = []
1407
+ for i in range(0, len(rawLiquidations)):
1408
+ rawLiquidation = rawLiquidations[i]
1409
+ liquidation = self.parse_ws_liquidation(rawLiquidation)
1410
+ symbol = self.safe_string(liquidation, 'symbol')
1411
+ liquidations = self.safe_value(self.liquidations, symbol)
1412
+ if liquidations is None:
1413
+ limit = self.safe_integer(self.options, 'liquidationsLimit', 1000)
1414
+ liquidations = ArrayCache(limit)
1415
+ liquidations.append(liquidation)
1416
+ self.liquidations[symbol] = liquidations
1417
+ client.resolve(liquidations, 'myLiquidations::' + symbol)
1418
+ client.resolve(newLiquidations, 'myLiquidations')
1419
+
1420
+ def parse_ws_liquidation(self, liquidation, market=None):
1421
+ #
1422
+ # future / delivery
1423
+ # {
1424
+ # "entry_price": 209,
1425
+ # "fill_price": 215.1,
1426
+ # "left": 0,
1427
+ # "leverage": 0.0,
1428
+ # "liq_price": 213,
1429
+ # "margin": 0.007816722941,
1430
+ # "mark_price": 213,
1431
+ # "order_id": 4093362,
1432
+ # "order_price": 215.1,
1433
+ # "size": -124,
1434
+ # "time": 1541486601,
1435
+ # "time_ms": 1541486601123,
1436
+ # "contract": "BTC_USD",
1437
+ # "user": "1040xxxx"
1438
+ # }
1439
+ # option
1440
+ # {
1441
+ # "user": "1xxxx",
1442
+ # "init_margin": 1190,
1443
+ # "maint_margin": 1042.5,
1444
+ # "order_margin": 0,
1445
+ # "time": 1639051907,
1446
+ # "time_ms": 1639051907000
1447
+ # }
1448
+ #
1449
+ marketId = self.safe_string(liquidation, 'contract')
1450
+ market = self.safe_market(marketId, market)
1451
+ timestamp = self.safe_integer(liquidation, 'time_ms')
1452
+ originalSize = self.safe_string(liquidation, 'size')
1453
+ left = self.safe_string(liquidation, 'left')
1454
+ amount = Precise.string_abs(Precise.string_sub(originalSize, left))
1455
+ return self.safe_liquidation({
1456
+ 'info': liquidation,
1457
+ 'symbol': self.safe_symbol(marketId, market),
1458
+ 'contracts': self.parse_number(amount),
1459
+ 'contractSize': self.safe_number(market, 'contractSize'),
1460
+ 'price': self.safe_number(liquidation, 'fill_price'),
1461
+ 'baseValue': None,
1462
+ 'quoteValue': None,
1463
+ 'timestamp': timestamp,
1464
+ 'datetime': self.iso8601(timestamp),
1465
+ })
1466
+
966
1467
  def handle_error_message(self, client: Client, message):
967
- # {
968
- # "time": 1647274664,
969
- # "channel": "futures.orders",
970
- # "event": "subscribe",
971
- # "error": {code: 2, message: "unknown contract BTC_USDT_20220318"},
972
- # }
973
- # {
974
- # "time": 1647276473,
975
- # "channel": "futures.orders",
976
- # "event": "subscribe",
977
- # "error": {
978
- # "code": 4,
979
- # "message": "{"label":"INVALID_KEY","message":"Invalid key provided"}\n"
980
- # },
981
- # "result": null
982
- # }
983
- error = self.safe_value(message, 'error')
984
- code = self.safe_integer(error, 'code')
985
- id = self.safe_string(message, 'id')
986
- if id is None:
987
- return False
988
- if code is not None:
1468
+ #
1469
+ # {
1470
+ # "time": 1647274664,
1471
+ # "channel": "futures.orders",
1472
+ # "event": "subscribe",
1473
+ # "error": {code: 2, message: "unknown contract BTC_USDT_20220318"},
1474
+ # }
1475
+ # {
1476
+ # "time": 1647276473,
1477
+ # "channel": "futures.orders",
1478
+ # "event": "subscribe",
1479
+ # "error": {
1480
+ # "code": 4,
1481
+ # "message": "{"label":"INVALID_KEY","message":"Invalid key provided"}\n"
1482
+ # },
1483
+ # "result": null
1484
+ # }
1485
+ # {
1486
+ # header: {
1487
+ # response_time: '1718551891329',
1488
+ # status: '400',
1489
+ # channel: 'spot.order_place',
1490
+ # event: 'api',
1491
+ # client_id: '81.34.68.6-0xc16375e2c0',
1492
+ # conn_id: '9539116e0e09678f'
1493
+ # },
1494
+ # data: {errs: {label: 'AUTHENTICATION_FAILED', message: 'Not login'}},
1495
+ # request_id: '10406147'
1496
+ # }
1497
+ #
1498
+ data = self.safe_dict(message, 'data')
1499
+ errs = self.safe_dict(data, 'errs')
1500
+ error = self.safe_dict(message, 'error', errs)
1501
+ code = self.safe_string_2(error, 'code', 'label')
1502
+ id = self.safe_string_n(message, ['id', 'requestId', 'request_id'])
1503
+ if error is not None:
989
1504
  messageHash = self.safe_string(client.subscriptions, id)
990
- if messageHash is not None:
991
- try:
992
- self.throw_exactly_matched_exception(self.exceptions['ws']['exact'], code, self.json(message))
993
- except Exception as e:
994
- client.reject(e, messageHash)
995
- if messageHash in client.subscriptions:
996
- del client.subscriptions[messageHash]
997
- del client.subscriptions[id]
1505
+ try:
1506
+ self.throw_exactly_matched_exception(self.exceptions['ws']['exact'], code, self.json(message))
1507
+ self.throw_exactly_matched_exception(self.exceptions['exact'], code, self.json(errs))
1508
+ errorMessage = self.safe_string(error, 'message', self.safe_string(errs, 'message'))
1509
+ self.throw_broadly_matched_exception(self.exceptions['ws']['broad'], errorMessage, self.json(message))
1510
+ raise ExchangeError(self.json(message))
1511
+ except Exception as e:
1512
+ client.reject(e, messageHash)
1513
+ if (messageHash is not None) and (messageHash in client.subscriptions):
1514
+ del client.subscriptions[messageHash]
1515
+ if (id is not None) and (id in client.subscriptions):
1516
+ del client.subscriptions[id]
998
1517
  return True
999
1518
  return False
1000
1519
 
@@ -1003,7 +1522,7 @@ class gate(ccxt.async_support.gate):
1003
1522
 
1004
1523
  def handle_subscription_status(self, client: Client, message):
1005
1524
  channel = self.safe_string(message, 'channel')
1006
- methods = {
1525
+ methods: dict = {
1007
1526
  'balance': self.handle_balance_subscription,
1008
1527
  'spot.order_book_update': self.handle_order_book_subscription,
1009
1528
  'futures.order_book_update': self.handle_order_book_subscription,
@@ -1017,6 +1536,73 @@ class gate(ccxt.async_support.gate):
1017
1536
  if id in client.subscriptions:
1018
1537
  del client.subscriptions[id]
1019
1538
 
1539
+ def handle_un_subscribe(self, client: Client, message):
1540
+ #
1541
+ # {
1542
+ # "time":1725534679,
1543
+ # "time_ms":1725534679786,
1544
+ # "id":2,
1545
+ # "conn_id":"fac539b443fd7002",
1546
+ # "trace_id":"efe1d282b630b4aa266b84bee177791a",
1547
+ # "channel":"spot.trades",
1548
+ # "event":"unsubscribe",
1549
+ # "payload":[
1550
+ # "LTC_USDT"
1551
+ # ],
1552
+ # "result":{
1553
+ # "status":"success"
1554
+ # },
1555
+ # "requestId":"efe1d282b630b4aa266b84bee177791a"
1556
+ # }
1557
+ #
1558
+ id = self.safe_string(message, 'id')
1559
+ keys = list(client.subscriptions.keys())
1560
+ for i in range(0, len(keys)):
1561
+ messageHash = keys[i]
1562
+ if not (messageHash in client.subscriptions):
1563
+ continue
1564
+ # the previous iteration can have deleted the messageHash from the subscriptions
1565
+ if messageHash.startswith('unsubscribe'):
1566
+ subscription = client.subscriptions[messageHash]
1567
+ subId = self.safe_string(subscription, 'id')
1568
+ if id != subId:
1569
+ continue
1570
+ messageHashes = self.safe_list(subscription, 'messageHashes', [])
1571
+ subMessageHashes = self.safe_list(subscription, 'subMessageHashes', [])
1572
+ for j in range(0, len(messageHashes)):
1573
+ unsubHash = messageHashes[j]
1574
+ subHash = subMessageHashes[j]
1575
+ self.clean_unsubscription(client, subHash, unsubHash)
1576
+ self.clean_cache(subscription)
1577
+
1578
+ def clean_cache(self, subscription: dict):
1579
+ topic = self.safe_string(subscription, 'topic', '')
1580
+ symbols = self.safe_list(subscription, 'symbols', [])
1581
+ symbolsLength = len(symbols)
1582
+ if topic == 'ohlcv':
1583
+ symbolsAndTimeFrames = self.safe_list(subscription, 'symbolsAndTimeframes', [])
1584
+ for i in range(0, len(symbolsAndTimeFrames)):
1585
+ symbolAndTimeFrame = symbolsAndTimeFrames[i]
1586
+ symbol = self.safe_string(symbolAndTimeFrame, 0)
1587
+ timeframe = self.safe_string(symbolAndTimeFrame, 1)
1588
+ del self.ohlcvs[symbol][timeframe]
1589
+ elif symbolsLength > 0:
1590
+ for i in range(0, len(symbols)):
1591
+ symbol = symbols[i]
1592
+ if topic.endswith('trades'):
1593
+ del self.trades[symbol]
1594
+ elif topic == 'orderbook':
1595
+ del self.orderbooks[symbol]
1596
+ elif topic == 'ticker':
1597
+ del self.tickers[symbol]
1598
+ else:
1599
+ if topic.endswith('trades'):
1600
+ # don't reset self.myTrades directly here
1601
+ # because in c# we need to use a different object
1602
+ keys = list(self.trades.keys())
1603
+ for i in range(0, len(keys)):
1604
+ del self.trades[keys[i]]
1605
+
1020
1606
  def handle_message(self, client: Client, message):
1021
1607
  #
1022
1608
  # subscribe
@@ -1113,10 +1699,13 @@ class gate(ccxt.async_support.gate):
1113
1699
  if event == 'subscribe':
1114
1700
  self.handle_subscription_status(client, message)
1115
1701
  return
1702
+ if event == 'unsubscribe':
1703
+ self.handle_un_subscribe(client, message)
1704
+ return
1116
1705
  channel = self.safe_string(message, 'channel', '')
1117
1706
  channelParts = channel.split('.')
1118
1707
  channelType = self.safe_value(channelParts, 1)
1119
- v4Methods = {
1708
+ v4Methods: dict = {
1120
1709
  'usertrades': self.handle_my_trades,
1121
1710
  'candlesticks': self.handle_ohlcv,
1122
1711
  'orders': self.handle_order,
@@ -1126,10 +1715,22 @@ class gate(ccxt.async_support.gate):
1126
1715
  'trades': self.handle_trades,
1127
1716
  'order_book_update': self.handle_order_book,
1128
1717
  'balances': self.handle_balance,
1718
+ 'liquidates': self.handle_liquidation,
1129
1719
  }
1130
1720
  method = self.safe_value(v4Methods, channelType)
1131
1721
  if method is not None:
1132
1722
  method(client, message)
1723
+ requestId = self.safe_string(message, 'request_id')
1724
+ if requestId == 'authenticated':
1725
+ self.handle_authentication_message(client, message)
1726
+ return
1727
+ if requestId is not None:
1728
+ data = self.safe_dict(message, 'data')
1729
+ # use safeValue may be Array or an Object
1730
+ result = self.safe_value(data, 'result')
1731
+ ack = self.safe_bool(message, 'ack')
1732
+ if ack is not True:
1733
+ client.resolve(result, requestId)
1133
1734
 
1134
1735
  def get_url_by_market(self, market):
1135
1736
  baseUrl = self.urls['api'][market['type']]
@@ -1138,7 +1739,7 @@ class gate(ccxt.async_support.gate):
1138
1739
  else:
1139
1740
  return baseUrl
1140
1741
 
1141
- def get_type_by_market(self, market):
1742
+ def get_type_by_market(self, market: Market):
1142
1743
  if market['spot']:
1143
1744
  return 'spot'
1144
1745
  elif market['option']:
@@ -1146,7 +1747,7 @@ class gate(ccxt.async_support.gate):
1146
1747
  else:
1147
1748
  return 'futures'
1148
1749
 
1149
- def get_url_by_market_type(self, type, isInverse=False):
1750
+ def get_url_by_market_type(self, type: MarketType, isInverse=False):
1150
1751
  api = self.urls['api']
1151
1752
  url = api[type]
1152
1753
  if (type == 'swap') or (type == 'future'):
@@ -1155,7 +1756,7 @@ class gate(ccxt.async_support.gate):
1155
1756
  return url
1156
1757
 
1157
1758
  def get_market_type_by_url(self, url: str):
1158
- findBy = {
1759
+ findBy: dict = {
1159
1760
  'op-': 'option',
1160
1761
  'delivery': 'future',
1161
1762
  'fx': 'swap',
@@ -1177,7 +1778,7 @@ class gate(ccxt.async_support.gate):
1177
1778
  async def subscribe_public(self, url, messageHash, payload, channel, params={}, subscription=None):
1178
1779
  requestId = self.request_id()
1179
1780
  time = self.seconds()
1180
- request = {
1781
+ request: dict = {
1181
1782
  'id': requestId,
1182
1783
  'time': time,
1183
1784
  'channel': channel,
@@ -1195,7 +1796,7 @@ class gate(ccxt.async_support.gate):
1195
1796
  async def subscribe_public_multiple(self, url, messageHashes, payload, channel, params={}):
1196
1797
  requestId = self.request_id()
1197
1798
  time = self.seconds()
1198
- request = {
1799
+ request: dict = {
1199
1800
  'id': requestId,
1200
1801
  'time': time,
1201
1802
  'channel': channel,
@@ -1205,6 +1806,70 @@ class gate(ccxt.async_support.gate):
1205
1806
  message = self.extend(request, params)
1206
1807
  return await self.watch_multiple(url, messageHashes, message, messageHashes)
1207
1808
 
1809
+ async def un_subscribe_public_multiple(self, url, topic, symbols, messageHashes, subMessageHashes, payload, channel, params={}):
1810
+ requestId = self.request_id()
1811
+ time = self.seconds()
1812
+ request: dict = {
1813
+ 'id': requestId,
1814
+ 'time': time,
1815
+ 'channel': channel,
1816
+ 'event': 'unsubscribe',
1817
+ 'payload': payload,
1818
+ }
1819
+ sub = {
1820
+ 'id': str(requestId),
1821
+ 'topic': topic,
1822
+ 'unsubscribe': True,
1823
+ 'messageHashes': messageHashes,
1824
+ 'subMessageHashes': subMessageHashes,
1825
+ 'symbols': symbols,
1826
+ }
1827
+ message = self.extend(request, params)
1828
+ return await self.watch_multiple(url, messageHashes, message, messageHashes, sub)
1829
+
1830
+ async def authenticate(self, url, messageType):
1831
+ channel = messageType + '.login'
1832
+ client = self.client(url)
1833
+ messageHash = 'authenticated'
1834
+ future = client.future(messageHash)
1835
+ authenticated = self.safe_value(client.subscriptions, messageHash)
1836
+ if authenticated is None:
1837
+ return await self.request_private(url, {}, channel, messageHash)
1838
+ return future
1839
+
1840
+ def handle_authentication_message(self, client: Client, message):
1841
+ messageHash = 'authenticated'
1842
+ future = self.safe_value(client.futures, messageHash)
1843
+ future.resolve(True)
1844
+
1845
+ async def request_private(self, url, reqParams, channel, requestId: Str = None):
1846
+ self.check_required_credentials()
1847
+ # uid is required for some subscriptions only so it's not a part of required credentials
1848
+ event = 'api'
1849
+ if requestId is None:
1850
+ reqId = self.request_id()
1851
+ requestId = str(reqId)
1852
+ messageHash = requestId
1853
+ time = self.seconds()
1854
+ # unfortunately, PHP demands double quotes for the escaped newline symbol
1855
+ signatureString = "\n".join([event, channel, self.json(reqParams), str(time)]) # eslint-disable-line quotes
1856
+ signature = self.hmac(self.encode(signatureString), self.encode(self.secret), hashlib.sha512, 'hex')
1857
+ payload: dict = {
1858
+ 'req_id': requestId,
1859
+ 'timestamp': str(time),
1860
+ 'api_key': self.apiKey,
1861
+ 'signature': signature,
1862
+ 'req_param': reqParams,
1863
+ }
1864
+ request: dict = {
1865
+ 'id': requestId,
1866
+ 'time': time,
1867
+ 'channel': channel,
1868
+ 'event': event,
1869
+ 'payload': payload,
1870
+ }
1871
+ return await self.watch(url, messageHash, request, messageHash, requestId)
1872
+
1208
1873
  async def subscribe_private(self, url, messageHash, payload, channel, params, requiresUid=False):
1209
1874
  self.check_required_credentials()
1210
1875
  # uid is required for some subscriptions only so it's not a part of required credentials
@@ -1220,17 +1885,17 @@ class gate(ccxt.async_support.gate):
1220
1885
  event = 'subscribe'
1221
1886
  signaturePayload = 'channel=' + channel + '&' + 'event=' + event + '&' + 'time=' + str(time)
1222
1887
  signature = self.hmac(self.encode(signaturePayload), self.encode(self.secret), hashlib.sha512, 'hex')
1223
- auth = {
1888
+ auth: dict = {
1224
1889
  'method': 'api_key',
1225
1890
  'KEY': self.apiKey,
1226
1891
  'SIGN': signature,
1227
1892
  }
1228
1893
  requestId = self.request_id()
1229
- request = {
1894
+ request: dict = {
1230
1895
  'id': requestId,
1231
1896
  'time': time,
1232
1897
  'channel': channel,
1233
- 'event': 'subscribe',
1898
+ 'event': event,
1234
1899
  'auth': auth,
1235
1900
  }
1236
1901
  if payload is not None:
@@ -1241,4 +1906,4 @@ class gate(ccxt.async_support.gate):
1241
1906
  # in case of authenticationError we will throw
1242
1907
  client.subscriptions[tempSubscriptionHash] = messageHash
1243
1908
  message = self.extend(request, params)
1244
- return await self.watch(url, messageHash, message, messageHash)
1909
+ return await self.watch(url, messageHash, message, messageHash, messageHash)