ccxt-ir 4.3.46.0.3__py2.py3-none-any.whl → 4.5.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (529) hide show
  1. ccxt/__init__.py +39 -35
  2. ccxt/abantether.py +8 -8
  3. ccxt/abstract/alpaca.py +4 -0
  4. ccxt/abstract/apex.py +31 -0
  5. ccxt/abstract/bigone.py +1 -1
  6. ccxt/abstract/binance.py +106 -48
  7. ccxt/abstract/binancecoinm.py +106 -48
  8. ccxt/abstract/binanceus.py +141 -83
  9. ccxt/abstract/binanceusdm.py +106 -48
  10. ccxt/abstract/bingx.py +50 -1
  11. ccxt/abstract/bitbank.py +5 -0
  12. ccxt/abstract/bitfinex.py +136 -65
  13. ccxt/abstract/bitflyer.py +1 -0
  14. ccxt/abstract/bitget.py +67 -0
  15. ccxt/abstract/bitmart.py +19 -1
  16. ccxt/abstract/bitopro.py +1 -0
  17. ccxt/abstract/bitrue.py +68 -68
  18. ccxt/abstract/bitstamp.py +1 -0
  19. ccxt/abstract/blofin.py +30 -0
  20. ccxt/abstract/btcbox.py +2 -0
  21. ccxt/abstract/bybit.py +28 -13
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbaseexchange.py +1 -0
  24. ccxt/abstract/coinbaseinternational.py +1 -1
  25. ccxt/abstract/cryptocom.py +16 -0
  26. ccxt/abstract/cryptomus.py +20 -0
  27. ccxt/abstract/defx.py +69 -0
  28. ccxt/abstract/deribit.py +1 -0
  29. ccxt/abstract/derive.py +117 -0
  30. ccxt/abstract/digifinex.py +1 -0
  31. ccxt/abstract/ellipx.py +25 -0
  32. ccxt/abstract/foxbit.py +26 -0
  33. ccxt/abstract/gate.py +19 -0
  34. ccxt/abstract/gateio.py +19 -0
  35. ccxt/abstract/gemini.py +1 -0
  36. ccxt/abstract/hibachi.py +26 -0
  37. ccxt/abstract/hyperliquid.py +1 -1
  38. ccxt/abstract/independentreserve.py +6 -0
  39. ccxt/abstract/kraken.py +1 -0
  40. ccxt/abstract/krakenfutures.py +4 -0
  41. ccxt/abstract/kucoin.py +10 -0
  42. ccxt/abstract/kucoinfutures.py +18 -0
  43. ccxt/abstract/lbank.py +2 -1
  44. ccxt/abstract/luno.py +1 -0
  45. ccxt/abstract/mexc.py +2 -0
  46. ccxt/abstract/modetrade.py +119 -0
  47. ccxt/abstract/myokx.py +349 -0
  48. ccxt/abstract/oceanex.py +5 -0
  49. ccxt/abstract/okx.py +25 -0
  50. ccxt/abstract/okxus.py +349 -0
  51. ccxt/abstract/onetrading.py +0 -12
  52. ccxt/abstract/paradex.py +23 -0
  53. ccxt/abstract/phemex.py +2 -0
  54. ccxt/abstract/poloniex.py +36 -0
  55. ccxt/abstract/tradeogre.py +3 -1
  56. ccxt/abstract/upbit.py +51 -34
  57. ccxt/abstract/whitebit.py +16 -0
  58. ccxt/abstract/woo.py +64 -6
  59. ccxt/abstract/xt.py +10 -5
  60. ccxt/afratether.py +7 -7
  61. ccxt/alpaca.py +828 -51
  62. ccxt/apex.py +1875 -0
  63. ccxt/arzinja.py +7 -7
  64. ccxt/arzplus.py +9 -9
  65. ccxt/ascendex.py +501 -306
  66. ccxt/async_support/__init__.py +39 -35
  67. ccxt/async_support/abantether.py +8 -8
  68. ccxt/async_support/afratether.py +9 -9
  69. ccxt/async_support/alpaca.py +828 -51
  70. ccxt/async_support/apex.py +1875 -0
  71. ccxt/async_support/arzinja.py +10 -10
  72. ccxt/async_support/arzplus.py +12 -12
  73. ccxt/async_support/ascendex.py +502 -306
  74. ccxt/async_support/base/exchange.py +303 -89
  75. ccxt/async_support/base/ws/cache.py +9 -3
  76. ccxt/async_support/base/ws/client.py +173 -38
  77. ccxt/async_support/base/ws/future.py +25 -37
  78. ccxt/async_support/bequant.py +5 -3
  79. ccxt/async_support/bigone.py +279 -144
  80. ccxt/async_support/binance.py +2347 -1158
  81. ccxt/async_support/binancecoinm.py +9 -3
  82. ccxt/async_support/binanceus.py +17 -3
  83. ccxt/async_support/binanceusdm.py +9 -4
  84. ccxt/async_support/bingx.py +2962 -920
  85. ccxt/async_support/bit2c.py +147 -27
  86. ccxt/async_support/bitbank.py +151 -23
  87. ccxt/async_support/bitbns.py +104 -30
  88. ccxt/async_support/bitfinex.py +3291 -1113
  89. ccxt/async_support/bitflyer.py +202 -27
  90. ccxt/async_support/bitget.py +3683 -1538
  91. ccxt/async_support/bithumb.py +195 -38
  92. ccxt/async_support/bitimen.py +12 -12
  93. ccxt/async_support/bitir.py +38 -38
  94. ccxt/async_support/bitmart.py +1288 -350
  95. ccxt/async_support/bitmex.py +260 -75
  96. ccxt/async_support/bitopro.py +262 -62
  97. ccxt/async_support/bitpin.py +17 -16
  98. ccxt/async_support/bitrue.py +459 -290
  99. ccxt/async_support/bitso.py +199 -54
  100. ccxt/async_support/bitstamp.py +230 -96
  101. ccxt/async_support/bitteam.py +167 -25
  102. ccxt/async_support/{huobijp.py → bittrade.py} +158 -30
  103. ccxt/async_support/bitvavo.py +213 -49
  104. ccxt/async_support/blockchaincom.py +160 -46
  105. ccxt/async_support/blofin.py +502 -120
  106. ccxt/async_support/btcalpha.py +169 -31
  107. ccxt/async_support/btcbox.py +292 -23
  108. ccxt/async_support/btcmarkets.py +211 -58
  109. ccxt/async_support/btcturk.py +161 -38
  110. ccxt/async_support/bybit.py +1775 -1030
  111. ccxt/async_support/cex.py +1440 -1303
  112. ccxt/async_support/coinbase.py +724 -212
  113. ccxt/async_support/coinbaseadvanced.py +2 -1
  114. ccxt/async_support/coinbaseexchange.py +388 -89
  115. ccxt/async_support/coinbaseinternational.py +412 -57
  116. ccxt/async_support/coincatch.py +177 -78
  117. ccxt/async_support/coincheck.py +135 -19
  118. ccxt/async_support/coinex.py +606 -232
  119. ccxt/async_support/coinmate.py +189 -63
  120. ccxt/async_support/coinmetro.py +195 -54
  121. ccxt/async_support/coinone.py +158 -51
  122. ccxt/async_support/coinsph.py +336 -61
  123. ccxt/async_support/coinspot.py +151 -52
  124. ccxt/async_support/cryptocom.py +661 -111
  125. ccxt/async_support/cryptomus.py +1137 -0
  126. ccxt/async_support/defx.py +2071 -0
  127. ccxt/async_support/delta.py +299 -99
  128. ccxt/async_support/deribit.py +348 -126
  129. ccxt/async_support/derive.py +2572 -0
  130. ccxt/async_support/digifinex.py +430 -214
  131. ccxt/async_support/ellipx.py +2029 -0
  132. ccxt/async_support/eterex.py +10 -10
  133. ccxt/async_support/excoino.py +31 -31
  134. ccxt/async_support/exir.py +14 -14
  135. ccxt/async_support/exmo.py +344 -131
  136. ccxt/async_support/exnovin.py +10 -10
  137. ccxt/async_support/farhadexchange.py +12 -12
  138. ccxt/async_support/fmfwio.py +2 -1
  139. ccxt/async_support/foxbit.py +1935 -0
  140. ccxt/async_support/gate.py +1351 -529
  141. ccxt/async_support/gateio.py +2 -1
  142. ccxt/async_support/gemini.py +144 -39
  143. ccxt/async_support/hashkey.py +152 -109
  144. ccxt/async_support/hibachi.py +2080 -0
  145. ccxt/async_support/hitbtc.py +395 -167
  146. ccxt/async_support/hitobit.py +12 -12
  147. ccxt/async_support/hollaex.py +307 -119
  148. ccxt/async_support/htx.py +851 -383
  149. ccxt/async_support/huobi.py +2 -1
  150. ccxt/async_support/hyperliquid.py +1848 -536
  151. ccxt/async_support/independentreserve.py +288 -15
  152. ccxt/async_support/indodax.py +190 -33
  153. ccxt/async_support/jibitex.py +12 -12
  154. ccxt/async_support/kraken.py +795 -351
  155. ccxt/async_support/krakenfutures.py +214 -62
  156. ccxt/async_support/kucoin.py +715 -396
  157. ccxt/async_support/kucoinfutures.py +652 -89
  158. ccxt/async_support/latoken.py +217 -113
  159. ccxt/async_support/lbank.py +425 -97
  160. ccxt/async_support/luno.py +382 -35
  161. ccxt/async_support/mercado.py +113 -6
  162. ccxt/async_support/mexc.py +874 -437
  163. ccxt/async_support/modetrade.py +2818 -0
  164. ccxt/async_support/myokx.py +54 -0
  165. ccxt/async_support/ndax.py +221 -64
  166. ccxt/async_support/nobitex.py +31 -37
  167. ccxt/async_support/novadax.py +190 -34
  168. ccxt/async_support/oceanex.py +217 -28
  169. ccxt/async_support/okcoin.py +253 -145
  170. ccxt/async_support/okexchange.py +11 -11
  171. ccxt/async_support/okx.py +1088 -351
  172. ccxt/async_support/okxus.py +54 -0
  173. ccxt/async_support/ompfinex.py +25 -24
  174. ccxt/async_support/onetrading.py +213 -392
  175. ccxt/async_support/oxfun.py +245 -166
  176. ccxt/async_support/p2b.py +151 -29
  177. ccxt/async_support/paradex.py +562 -49
  178. ccxt/async_support/paymium.py +82 -19
  179. ccxt/async_support/phemex.py +713 -172
  180. ccxt/async_support/poloniex.py +1602 -283
  181. ccxt/async_support/probit.py +224 -95
  182. ccxt/async_support/ramzinex.py +30 -27
  183. ccxt/async_support/sarmayex.py +9 -9
  184. ccxt/async_support/sarrafex.py +13 -13
  185. ccxt/async_support/tabdeal.py +14 -13
  186. ccxt/async_support/tetherland.py +9 -9
  187. ccxt/async_support/timex.py +210 -51
  188. ccxt/async_support/tokocrypto.py +167 -47
  189. ccxt/async_support/tradeogre.py +266 -31
  190. ccxt/async_support/twox.py +9 -9
  191. ccxt/async_support/ubitex.py +12 -12
  192. ccxt/async_support/upbit.py +568 -165
  193. ccxt/async_support/vertex.py +160 -32
  194. ccxt/async_support/wallex.py +12 -12
  195. ccxt/async_support/wavesexchange.py +165 -30
  196. ccxt/async_support/whitebit.py +975 -127
  197. ccxt/async_support/woo.py +1918 -1016
  198. ccxt/async_support/woofipro.py +433 -141
  199. ccxt/async_support/xt.py +649 -193
  200. ccxt/async_support/yobit.py +195 -70
  201. ccxt/async_support/zaif.py +91 -15
  202. ccxt/async_support/zonda.py +151 -36
  203. ccxt/base/decimal_to_precision.py +14 -10
  204. ccxt/base/errors.py +49 -18
  205. ccxt/base/exchange.py +1556 -450
  206. ccxt/base/precise.py +10 -0
  207. ccxt/base/types.py +114 -6
  208. ccxt/bequant.py +5 -3
  209. ccxt/bigone.py +279 -144
  210. ccxt/binance.py +2347 -1158
  211. ccxt/binancecoinm.py +9 -3
  212. ccxt/binanceus.py +17 -3
  213. ccxt/binanceusdm.py +9 -4
  214. ccxt/bingx.py +2962 -920
  215. ccxt/bit2c.py +147 -27
  216. ccxt/bitbank.py +151 -23
  217. ccxt/bitbns.py +104 -30
  218. ccxt/bitfinex.py +3290 -1113
  219. ccxt/bitflyer.py +202 -27
  220. ccxt/bitget.py +3683 -1538
  221. ccxt/bithumb.py +194 -38
  222. ccxt/bitimen.py +9 -9
  223. ccxt/bitir.py +35 -35
  224. ccxt/bitmart.py +1288 -350
  225. ccxt/bitmex.py +260 -75
  226. ccxt/bitopro.py +262 -62
  227. ccxt/bitpin.py +15 -14
  228. ccxt/bitrue.py +459 -290
  229. ccxt/bitso.py +199 -54
  230. ccxt/bitstamp.py +230 -96
  231. ccxt/bitteam.py +167 -25
  232. ccxt/{huobijp.py → bittrade.py} +158 -30
  233. ccxt/bitvavo.py +213 -49
  234. ccxt/blockchaincom.py +160 -46
  235. ccxt/blofin.py +502 -120
  236. ccxt/btcalpha.py +169 -31
  237. ccxt/btcbox.py +291 -23
  238. ccxt/btcmarkets.py +211 -58
  239. ccxt/btcturk.py +161 -38
  240. ccxt/bybit.py +1775 -1030
  241. ccxt/cex.py +1439 -1303
  242. ccxt/coinbase.py +724 -212
  243. ccxt/coinbaseadvanced.py +2 -1
  244. ccxt/coinbaseexchange.py +388 -89
  245. ccxt/coinbaseinternational.py +412 -57
  246. ccxt/coincatch.py +177 -78
  247. ccxt/coincheck.py +135 -19
  248. ccxt/coinex.py +606 -232
  249. ccxt/coinmate.py +189 -63
  250. ccxt/coinmetro.py +194 -54
  251. ccxt/coinone.py +158 -51
  252. ccxt/coinsph.py +336 -61
  253. ccxt/coinspot.py +151 -52
  254. ccxt/cryptocom.py +661 -111
  255. ccxt/cryptomus.py +1137 -0
  256. ccxt/defx.py +2070 -0
  257. ccxt/delta.py +299 -99
  258. ccxt/deribit.py +348 -126
  259. ccxt/derive.py +2571 -0
  260. ccxt/digifinex.py +430 -214
  261. ccxt/ellipx.py +2029 -0
  262. ccxt/eterex.py +7 -7
  263. ccxt/excoino.py +29 -29
  264. ccxt/exir.py +11 -11
  265. ccxt/exmo.py +343 -131
  266. ccxt/exnovin.py +8 -8
  267. ccxt/farhadexchange.py +10 -10
  268. ccxt/fmfwio.py +2 -1
  269. ccxt/foxbit.py +1935 -0
  270. ccxt/gate.py +1351 -529
  271. ccxt/gateio.py +2 -1
  272. ccxt/gemini.py +144 -39
  273. ccxt/hashkey.py +152 -109
  274. ccxt/hibachi.py +2079 -0
  275. ccxt/hitbtc.py +395 -167
  276. ccxt/hitobit.py +9 -9
  277. ccxt/hollaex.py +307 -119
  278. ccxt/htx.py +851 -383
  279. ccxt/huobi.py +2 -1
  280. ccxt/hyperliquid.py +1848 -536
  281. ccxt/independentreserve.py +287 -15
  282. ccxt/indodax.py +190 -33
  283. ccxt/jibitex.py +9 -9
  284. ccxt/kraken.py +794 -351
  285. ccxt/krakenfutures.py +214 -62
  286. ccxt/kucoin.py +715 -396
  287. ccxt/kucoinfutures.py +652 -89
  288. ccxt/latoken.py +217 -113
  289. ccxt/lbank.py +425 -97
  290. ccxt/luno.py +382 -35
  291. ccxt/mercado.py +113 -6
  292. ccxt/mexc.py +873 -437
  293. ccxt/modetrade.py +2818 -0
  294. ccxt/myokx.py +54 -0
  295. ccxt/ndax.py +221 -64
  296. ccxt/nobitex.py +29 -35
  297. ccxt/novadax.py +190 -34
  298. ccxt/oceanex.py +217 -28
  299. ccxt/okcoin.py +253 -145
  300. ccxt/okexchange.py +9 -9
  301. ccxt/okx.py +1088 -351
  302. ccxt/okxus.py +54 -0
  303. ccxt/ompfinex.py +22 -21
  304. ccxt/onetrading.py +213 -392
  305. ccxt/oxfun.py +245 -166
  306. ccxt/p2b.py +151 -29
  307. ccxt/paradex.py +562 -49
  308. ccxt/paymium.py +82 -19
  309. ccxt/phemex.py +712 -172
  310. ccxt/poloniex.py +1601 -283
  311. ccxt/pro/__init__.py +76 -17
  312. ccxt/pro/alpaca.py +21 -6
  313. ccxt/pro/apex.py +984 -0
  314. ccxt/pro/ascendex.py +58 -10
  315. ccxt/pro/bequant.py +6 -1
  316. ccxt/pro/binance.py +728 -156
  317. ccxt/pro/binancecoinm.py +6 -2
  318. ccxt/pro/binanceus.py +8 -4
  319. ccxt/pro/binanceusdm.py +7 -2
  320. ccxt/pro/bingx.py +333 -142
  321. ccxt/pro/bitfinex.py +727 -262
  322. ccxt/pro/bitget.py +570 -79
  323. ccxt/pro/bithumb.py +20 -6
  324. ccxt/pro/bitmart.py +216 -87
  325. ccxt/pro/bitmex.py +47 -9
  326. ccxt/pro/bitopro.py +26 -14
  327. ccxt/pro/bitrue.py +22 -22
  328. ccxt/pro/bitstamp.py +54 -21
  329. ccxt/pro/{huobijp.py → bittrade.py} +7 -6
  330. ccxt/pro/bitvavo.py +191 -67
  331. ccxt/pro/blockchaincom.py +21 -8
  332. ccxt/pro/blofin.py +9 -1
  333. ccxt/pro/bybit.py +632 -245
  334. ccxt/pro/cex.py +59 -24
  335. ccxt/pro/coinbase.py +102 -73
  336. ccxt/pro/coinbaseadvanced.py +2 -1
  337. ccxt/pro/coinbaseexchange.py +8 -8
  338. ccxt/pro/coinbaseinternational.py +181 -25
  339. ccxt/pro/coincatch.py +6 -7
  340. ccxt/pro/coincheck.py +11 -6
  341. ccxt/pro/coinex.py +967 -665
  342. ccxt/pro/coinone.py +16 -9
  343. ccxt/pro/cryptocom.py +448 -45
  344. ccxt/pro/defx.py +831 -0
  345. ccxt/pro/deribit.py +150 -14
  346. ccxt/pro/derive.py +704 -0
  347. ccxt/pro/exmo.py +239 -6
  348. ccxt/pro/gate.py +623 -65
  349. ccxt/pro/gateio.py +2 -1
  350. ccxt/pro/gemini.py +27 -11
  351. ccxt/pro/hashkey.py +2 -2
  352. ccxt/pro/hitbtc.py +196 -91
  353. ccxt/pro/hollaex.py +23 -7
  354. ccxt/pro/htx.py +51 -14
  355. ccxt/pro/huobi.py +2 -1
  356. ccxt/pro/hyperliquid.py +591 -27
  357. ccxt/pro/independentreserve.py +9 -6
  358. ccxt/pro/kraken.py +640 -320
  359. ccxt/pro/krakenfutures.py +62 -35
  360. ccxt/pro/kucoin.py +267 -46
  361. ccxt/pro/kucoinfutures.py +165 -21
  362. ccxt/pro/lbank.py +102 -21
  363. ccxt/pro/luno.py +12 -8
  364. ccxt/pro/mexc.py +877 -111
  365. ccxt/pro/modetrade.py +1271 -0
  366. ccxt/pro/myokx.py +38 -0
  367. ccxt/pro/ndax.py +15 -2
  368. ccxt/pro/okcoin.py +23 -4
  369. ccxt/pro/okx.py +573 -98
  370. ccxt/pro/okxus.py +38 -0
  371. ccxt/pro/onetrading.py +30 -13
  372. ccxt/pro/oxfun.py +131 -27
  373. ccxt/pro/p2b.py +88 -22
  374. ccxt/pro/paradex.py +3 -3
  375. ccxt/pro/phemex.py +75 -21
  376. ccxt/pro/poloniex.py +124 -41
  377. ccxt/pro/probit.py +87 -80
  378. ccxt/pro/tradeogre.py +272 -0
  379. ccxt/pro/upbit.py +152 -12
  380. ccxt/pro/vertex.py +8 -3
  381. ccxt/pro/whitebit.py +58 -5
  382. ccxt/pro/woo.py +228 -37
  383. ccxt/pro/woofipro.py +106 -18
  384. ccxt/pro/xt.py +111 -5
  385. ccxt/probit.py +224 -95
  386. ccxt/protobuf/__init__.py +0 -0
  387. ccxt/protobuf/mexc/PrivateAccountV3Api_pb2.py +37 -0
  388. ccxt/protobuf/mexc/PrivateDealsV3Api_pb2.py +37 -0
  389. ccxt/protobuf/mexc/PrivateOrdersV3Api_pb2.py +37 -0
  390. ccxt/protobuf/mexc/PublicAggreBookTickerV3Api_pb2.py +37 -0
  391. ccxt/protobuf/mexc/PublicAggreDealsV3Api_pb2.py +39 -0
  392. ccxt/protobuf/mexc/PublicAggreDepthsV3Api_pb2.py +39 -0
  393. ccxt/protobuf/mexc/PublicBookTickerBatchV3Api_pb2.py +38 -0
  394. ccxt/protobuf/mexc/PublicBookTickerV3Api_pb2.py +37 -0
  395. ccxt/protobuf/mexc/PublicDealsV3Api_pb2.py +39 -0
  396. ccxt/protobuf/mexc/PublicIncreaseDepthsBatchV3Api_pb2.py +38 -0
  397. ccxt/protobuf/mexc/PublicIncreaseDepthsV3Api_pb2.py +39 -0
  398. ccxt/protobuf/mexc/PublicLimitDepthsV3Api_pb2.py +39 -0
  399. ccxt/protobuf/mexc/PublicMiniTickerV3Api_pb2.py +37 -0
  400. ccxt/protobuf/mexc/PublicMiniTickersV3Api_pb2.py +38 -0
  401. ccxt/protobuf/mexc/PublicSpotKlineV3Api_pb2.py +37 -0
  402. ccxt/protobuf/mexc/PushDataV3ApiWrapper_pb2.py +52 -0
  403. ccxt/protobuf/mexc/__init__.py +0 -0
  404. ccxt/ramzinex.py +28 -25
  405. ccxt/sarmayex.py +7 -7
  406. ccxt/sarrafex.py +10 -10
  407. ccxt/static_dependencies/__init__.py +1 -1
  408. ccxt/static_dependencies/lark/py.typed +0 -0
  409. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  410. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  411. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  412. ccxt/tabdeal.py +12 -11
  413. ccxt/test/tests_async.py +261 -57
  414. ccxt/test/tests_helpers.py +1 -3
  415. ccxt/test/tests_init.py +4 -3
  416. ccxt/test/tests_sync.py +261 -57
  417. ccxt/tetherland.py +7 -7
  418. ccxt/timex.py +210 -51
  419. ccxt/tokocrypto.py +167 -47
  420. ccxt/tradeogre.py +266 -31
  421. ccxt/twox.py +7 -7
  422. ccxt/ubitex.py +9 -9
  423. ccxt/upbit.py +568 -165
  424. ccxt/vertex.py +160 -32
  425. ccxt/wallex.py +9 -9
  426. ccxt/wavesexchange.py +165 -30
  427. ccxt/whitebit.py +975 -127
  428. ccxt/woo.py +1917 -1016
  429. ccxt/woofipro.py +432 -141
  430. ccxt/xt.py +649 -193
  431. ccxt/yobit.py +194 -70
  432. ccxt/zaif.py +91 -15
  433. ccxt/zonda.py +151 -36
  434. {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.0.dist-info}/METADATA +225 -73
  435. ccxt_ir-4.5.0.dist-info/RECORD +743 -0
  436. {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.0.dist-info}/WHEEL +1 -1
  437. ccxt/__test__.py +0 -7
  438. ccxt/abstract/ace.py +0 -15
  439. ccxt/abstract/bitbay.py +0 -53
  440. ccxt/abstract/bitcoincom.py +0 -115
  441. ccxt/abstract/bitfinex2.py +0 -139
  442. ccxt/abstract/bitpanda.py +0 -35
  443. ccxt/abstract/bl3p.py +0 -19
  444. ccxt/abstract/coinlist.py +0 -54
  445. ccxt/abstract/currencycom.py +0 -68
  446. ccxt/abstract/hitbtc3.py +0 -115
  447. ccxt/abstract/idex.py +0 -26
  448. ccxt/abstract/kuna.py +0 -182
  449. ccxt/abstract/lykke.py +0 -29
  450. ccxt/abstract/poloniexfutures.py +0 -48
  451. ccxt/abstract/wazirx.py +0 -30
  452. ccxt/ace.py +0 -1012
  453. ccxt/async_support/ace.py +0 -1012
  454. ccxt/async_support/base/ws/aiohttp_client.py +0 -125
  455. ccxt/async_support/base/ws/fast_client.py +0 -96
  456. ccxt/async_support/bitbay.py +0 -17
  457. ccxt/async_support/bitcoincom.py +0 -17
  458. ccxt/async_support/bitfinex2.py +0 -3552
  459. ccxt/async_support/bitpanda.py +0 -16
  460. ccxt/async_support/bl3p.py +0 -485
  461. ccxt/async_support/coinlist.py +0 -2243
  462. ccxt/async_support/currencycom.py +0 -1950
  463. ccxt/async_support/hitbtc3.py +0 -16
  464. ccxt/async_support/idex.py +0 -1766
  465. ccxt/async_support/kuna.py +0 -1841
  466. ccxt/async_support/lykke.py +0 -1270
  467. ccxt/async_support/poloniexfutures.py +0 -1717
  468. ccxt/async_support/wazirx.py +0 -1224
  469. ccxt/bitbay.py +0 -17
  470. ccxt/bitcoincom.py +0 -17
  471. ccxt/bitfinex2.py +0 -3552
  472. ccxt/bitpanda.py +0 -16
  473. ccxt/bl3p.py +0 -485
  474. ccxt/coinlist.py +0 -2243
  475. ccxt/currencycom.py +0 -1950
  476. ccxt/hitbtc3.py +0 -16
  477. ccxt/idex.py +0 -1766
  478. ccxt/kuna.py +0 -1841
  479. ccxt/lykke.py +0 -1270
  480. ccxt/poloniexfutures.py +0 -1717
  481. ccxt/pro/bitcoincom.py +0 -34
  482. ccxt/pro/bitfinex2.py +0 -1083
  483. ccxt/pro/bitpanda.py +0 -15
  484. ccxt/pro/currencycom.py +0 -536
  485. ccxt/pro/idex.py +0 -672
  486. ccxt/pro/poloniexfutures.py +0 -990
  487. ccxt/pro/wazirx.py +0 -749
  488. ccxt/test/base/__init__.py +0 -29
  489. ccxt/test/base/test_account.py +0 -26
  490. ccxt/test/base/test_balance.py +0 -56
  491. ccxt/test/base/test_borrow_interest.py +0 -35
  492. ccxt/test/base/test_borrow_rate.py +0 -32
  493. ccxt/test/base/test_calculate_fee.py +0 -51
  494. ccxt/test/base/test_crypto.py +0 -127
  495. ccxt/test/base/test_currency.py +0 -76
  496. ccxt/test/base/test_datetime.py +0 -109
  497. ccxt/test/base/test_decimal_to_precision.py +0 -392
  498. ccxt/test/base/test_deep_extend.py +0 -68
  499. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  500. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  501. ccxt/test/base/test_funding_rate_history.py +0 -29
  502. ccxt/test/base/test_last_price.py +0 -31
  503. ccxt/test/base/test_ledger_entry.py +0 -45
  504. ccxt/test/base/test_ledger_item.py +0 -48
  505. ccxt/test/base/test_leverage_tier.py +0 -33
  506. ccxt/test/base/test_liquidation.py +0 -50
  507. ccxt/test/base/test_margin_mode.py +0 -24
  508. ccxt/test/base/test_margin_modification.py +0 -35
  509. ccxt/test/base/test_market.py +0 -193
  510. ccxt/test/base/test_number.py +0 -411
  511. ccxt/test/base/test_ohlcv.py +0 -33
  512. ccxt/test/base/test_open_interest.py +0 -32
  513. ccxt/test/base/test_order.py +0 -64
  514. ccxt/test/base/test_order_book.py +0 -69
  515. ccxt/test/base/test_position.py +0 -60
  516. ccxt/test/base/test_shared_methods.py +0 -353
  517. ccxt/test/base/test_status.py +0 -24
  518. ccxt/test/base/test_throttle.py +0 -126
  519. ccxt/test/base/test_ticker.py +0 -92
  520. ccxt/test/base/test_trade.py +0 -47
  521. ccxt/test/base/test_trading_fee.py +0 -26
  522. ccxt/test/base/test_transaction.py +0 -39
  523. ccxt/test/test_async.py +0 -1649
  524. ccxt/test/test_sync.py +0 -1648
  525. ccxt/wazirx.py +0 -1224
  526. ccxt_ir-4.3.46.0.3.dist-info/RECORD +0 -773
  527. /ccxt/abstract/{huobijp.py → bittrade.py} +0 -0
  528. {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.0.dist-info/licenses}/LICENSE.txt +0 -0
  529. {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.0.dist-info}/top_level.txt +0 -0
ccxt/pro/gate.py CHANGED
@@ -6,23 +6,47 @@
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, Liquidation, Order, OrderBook, Position, Str, Strings, Ticker, Tickers, Trade
9
+ from ccxt.base.types import Any, Balances, Bool, 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 ccxt.base.errors import ExchangeError
12
13
  from ccxt.base.errors import AuthenticationError
13
14
  from ccxt.base.errors import ArgumentsRequired
14
15
  from ccxt.base.errors import BadRequest
15
- from ccxt.base.errors import InvalidNonce
16
+ from ccxt.base.errors import NotSupported
17
+ from ccxt.base.errors import ChecksumError
16
18
  from ccxt.base.precise import Precise
17
19
 
18
20
 
19
21
  class gate(ccxt.async_support.gate):
20
22
 
21
- def describe(self):
23
+ def describe(self) -> Any:
22
24
  return self.deep_extend(super(gate, self).describe(), {
23
25
  'has': {
24
26
  'ws': True,
27
+ 'cancelAllOrdersWs': True,
28
+ 'cancelOrderWs': True,
29
+ 'createMarketBuyOrderWithCostWs': True,
30
+ 'createMarketOrderWs': True,
31
+ 'createMarketOrderWithCostWs': False,
32
+ 'createMarketSellOrderWithCostWs': False,
33
+ 'createOrderWs': True,
34
+ 'createOrdersWs': True,
35
+ 'createPostOnlyOrderWs': True,
36
+ 'createReduceOnlyOrderWs': True,
37
+ 'createStopLimitOrderWs': True,
38
+ 'createStopLossOrderWs': True,
39
+ 'createStopMarketOrderWs': False,
40
+ 'createStopOrderWs': True,
41
+ 'createTakeProfitOrderWs': True,
42
+ 'createTriggerOrderWs': True,
43
+ 'editOrderWs': True,
44
+ 'fetchOrderWs': True,
45
+ 'fetchOrdersWs': False,
46
+ 'fetchOpenOrdersWs': True,
47
+ 'fetchClosedOrdersWs': True,
25
48
  'watchOrderBook': True,
49
+ 'watchBidsAsks': True,
26
50
  'watchTicker': True,
27
51
  'watchTickers': True,
28
52
  'watchTrades': True,
@@ -82,6 +106,7 @@ class gate(ccxt.async_support.gate):
82
106
  'interval': '100ms',
83
107
  'snapshotDelay': 10, # how many deltas to cache before fetching a snapshot
84
108
  'snapshotMaxRetries': 3,
109
+ 'checksum': True,
85
110
  },
86
111
  'watchBalance': {
87
112
  'settle': 'usdt', # or btc
@@ -95,18 +120,258 @@ class gate(ccxt.async_support.gate):
95
120
  'exceptions': {
96
121
  'ws': {
97
122
  'exact': {
123
+ '1': BadRequest,
98
124
  '2': BadRequest,
99
125
  '4': AuthenticationError,
100
126
  '6': AuthenticationError,
101
127
  '11': AuthenticationError,
102
128
  },
129
+ 'broad': {},
103
130
  },
104
131
  },
105
132
  })
106
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
+
107
365
  async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
108
366
  """
109
367
  watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
368
+
369
+ https://www.gate.com/docs/developers/apiv4/ws/en/#order-book-channel
370
+ https://www.gate.com/docs/developers/apiv4/ws/en/#order-book-v2-api
371
+ https://www.gate.com/docs/developers/futures/ws/en/#order-book-api
372
+ https://www.gate.com/docs/developers/futures/ws/en/#order-book-v2-api
373
+ https://www.gate.com/docs/developers/delivery/ws/en/#order-book-api
374
+
110
375
  :param str symbol: unified symbol of the market to fetch the order book for
111
376
  :param int [limit]: the maximum amount of order book entries to return
112
377
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -123,7 +388,7 @@ class gate(ccxt.async_support.gate):
123
388
  url = self.get_url_by_market(market)
124
389
  payload = [marketId, interval]
125
390
  if limit is None:
126
- limit = 100
391
+ limit = 100 # max 100 atm
127
392
  if market['contract']:
128
393
  stringLimit = str(limit)
129
394
  payload.append(stringLimit)
@@ -134,6 +399,31 @@ class gate(ccxt.async_support.gate):
134
399
  orderbook = await self.subscribe_public(url, messageHash, payload, channel, query, subscription)
135
400
  return orderbook.limit()
136
401
 
402
+ async def un_watch_order_book(self, symbol: str, params={}) -> Any:
403
+ """
404
+ unWatches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
405
+ :param str symbol: unified symbol of the market to fetch the order book for
406
+ :param dict [params]: extra parameters specific to the exchange API endpoint
407
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
408
+ """
409
+ await self.load_markets()
410
+ market = self.market(symbol)
411
+ symbol = market['symbol']
412
+ marketId = market['id']
413
+ interval = '100ms'
414
+ interval, params = self.handle_option_and_params(params, 'watchOrderBook', 'interval', interval)
415
+ messageType = self.get_type_by_market(market)
416
+ channel = messageType + '.order_book_update'
417
+ subMessageHash = 'orderbook' + ':' + symbol
418
+ messageHash = 'unsubscribe:orderbook' + ':' + symbol
419
+ url = self.get_url_by_market(market)
420
+ payload = [marketId, interval]
421
+ limit = self.safe_integer(params, 'limit', 100)
422
+ if market['contract']:
423
+ stringLimit = str(limit)
424
+ payload.append(stringLimit)
425
+ return await self.un_subscribe_public_multiple(url, 'orderbook', [symbol], [messageHash], [subMessageHash], payload, channel, params)
426
+
137
427
  def handle_order_book_subscription(self, client: Client, message, subscription):
138
428
  symbol = self.safe_string(subscription, 'symbol')
139
429
  limit = self.safe_integer(subscription, 'limit')
@@ -224,10 +514,12 @@ class gate(ccxt.async_support.gate):
224
514
  elif nonce >= deltaStart - 1:
225
515
  self.handle_delta(storedOrderBook, delta)
226
516
  else:
227
- error = InvalidNonce(self.id + ' orderbook update has a nonce bigger than u')
228
517
  del client.subscriptions[messageHash]
229
518
  del self.orderbooks[symbol]
230
- client.reject(error, messageHash)
519
+ checksum = self.handle_option('watchOrderBook', 'checksum', True)
520
+ if checksum:
521
+ error = ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
522
+ client.reject(error, messageHash)
231
523
  client.resolve(storedOrderBook, messageHash)
232
524
 
233
525
  def get_cache_index(self, orderBook, cache):
@@ -268,7 +560,9 @@ class gate(ccxt.async_support.gate):
268
560
 
269
561
  async def watch_ticker(self, symbol: str, params={}) -> Ticker:
270
562
  """
271
- :see: https://www.gate.io/docs/developers/apiv4/ws/en/#tickers-channel
563
+
564
+ https://www.gate.io/docs/developers/apiv4/ws/en/#tickers-channel
565
+
272
566
  watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
273
567
  :param str symbol: unified symbol of the market to fetch the ticker for
274
568
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -283,7 +577,9 @@ class gate(ccxt.async_support.gate):
283
577
 
284
578
  async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
285
579
  """
286
- :see: https://www.gate.io/docs/developers/apiv4/ws/en/#tickers-channel
580
+
581
+ https://www.gate.io/docs/developers/apiv4/ws/en/#tickers-channel
582
+
287
583
  watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
288
584
  :param str[] symbols: unified symbol of the market to fetch the ticker for
289
585
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -314,8 +610,10 @@ class gate(ccxt.async_support.gate):
314
610
 
315
611
  async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
316
612
  """
317
- :see: https://www.gate.io/docs/developers/apiv4/ws/en/#best-bid-or-ask-price
318
- :see: https://www.gate.io/docs/developers/apiv4/ws/en/#order-book-channel
613
+
614
+ https://www.gate.io/docs/developers/apiv4/ws/en/#best-bid-or-ask-price
615
+ https://www.gate.io/docs/developers/apiv4/ws/en/#order-book-channel
616
+
319
617
  watches best bid & ask for symbols
320
618
  :param str[] symbols: unified symbol of the market to fetch the ticker for
321
619
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -408,7 +706,7 @@ class gate(ccxt.async_support.gate):
408
706
  async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
409
707
  """
410
708
  get the list of most recent trades for a particular symbol
411
- :param str symbol: unified symbol of the market to fetch trades for
709
+ :param str[] symbols: unified symbol of the market to fetch trades for
412
710
  :param int [since]: timestamp in ms of the earliest trade to fetch
413
711
  :param int [limit]: the maximum amount of trades to fetch
414
712
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -432,6 +730,37 @@ class gate(ccxt.async_support.gate):
432
730
  limit = trades.getLimit(tradeSymbol, limit)
433
731
  return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
434
732
 
733
+ async def un_watch_trades_for_symbols(self, symbols: List[str], params={}) -> Any:
734
+ """
735
+ get the list of most recent trades for a particular symbol
736
+ :param str[] symbols: unified symbol of the market to fetch trades for
737
+ :param dict [params]: extra parameters specific to the exchange API endpoint
738
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
739
+ """
740
+ await self.load_markets()
741
+ symbols = self.market_symbols(symbols)
742
+ marketIds = self.market_ids(symbols)
743
+ market = self.market(symbols[0])
744
+ messageType = self.get_type_by_market(market)
745
+ channel = messageType + '.trades'
746
+ subMessageHashes = []
747
+ messageHashes = []
748
+ for i in range(0, len(symbols)):
749
+ symbol = symbols[i]
750
+ subMessageHashes.append('trades:' + symbol)
751
+ messageHashes.append('unsubscribe:trades:' + symbol)
752
+ url = self.get_url_by_market(market)
753
+ return await self.un_subscribe_public_multiple(url, 'trades', symbols, messageHashes, subMessageHashes, marketIds, channel, params)
754
+
755
+ async def un_watch_trades(self, symbol: str, params={}) -> Any:
756
+ """
757
+ get the list of most recent trades for a particular symbol
758
+ :param str symbol: unified symbol of the market to fetch trades for
759
+ :param dict [params]: extra parameters specific to the exchange API endpoint
760
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
761
+ """
762
+ return await self.un_watch_trades_for_symbols([symbol], params)
763
+
435
764
  def handle_trades(self, client: Client, message):
436
765
  #
437
766
  # {
@@ -549,7 +878,7 @@ class gate(ccxt.async_support.gate):
549
878
  :param int [since]: the earliest time in ms to fetch trades for
550
879
  :param int [limit]: the maximum number of trade structures to retrieve
551
880
  :param dict [params]: extra parameters specific to the exchange API endpoint
552
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
881
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
553
882
  """
554
883
  await self.load_markets()
555
884
  subType = None
@@ -739,11 +1068,15 @@ class gate(ccxt.async_support.gate):
739
1068
 
740
1069
  async def watch_positions(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}) -> List[Position]:
741
1070
  """
742
- :see: https://www.gate.io/docs/developers/futures/ws/en/#positions-subscription
743
- :see: https://www.gate.io/docs/developers/delivery/ws/en/#positions-subscription
744
- :see: https://www.gate.io/docs/developers/options/ws/en/#positions-channel
1071
+
1072
+ https://www.gate.io/docs/developers/futures/ws/en/#positions-subscription
1073
+ https://www.gate.io/docs/developers/delivery/ws/en/#positions-subscription
1074
+ https://www.gate.io/docs/developers/options/ws/en/#positions-channel
1075
+
745
1076
  watch all open positions
746
- :param str[]|None symbols: list of unified market symbols
1077
+ :param str[] [symbols]: list of unified market symbols to watch positions for
1078
+ :param int [since]: the earliest time in ms to fetch positions for
1079
+ :param int [limit]: the maximum number of positions to retrieve
747
1080
  :param dict params: extra parameters specific to the exchange API endpoint
748
1081
  :returns dict[]: a list of `position structure <https://docs.ccxt.com/en/latest/manual.html#position-structure>`
749
1082
  """
@@ -774,7 +1107,7 @@ class gate(ccxt.async_support.gate):
774
1107
  client = self.client(url)
775
1108
  self.set_positions_cache(client, type, symbols)
776
1109
  fetchPositionsSnapshot = self.handle_option('watchPositions', 'fetchPositionsSnapshot', True)
777
- awaitPositionsSnapshot = self.safe_bool('watchPositions', 'awaitPositionsSnapshot', True)
1110
+ awaitPositionsSnapshot = self.handle_option('watchPositions', 'awaitPositionsSnapshot', True)
778
1111
  cache = self.safe_value(self.positions, type)
779
1112
  if fetchPositionsSnapshot and awaitPositionsSnapshot and cache is None:
780
1113
  return await client.future(type + ':fetchPositionsSnapshot')
@@ -803,7 +1136,9 @@ class gate(ccxt.async_support.gate):
803
1136
  cache = self.positions[type]
804
1137
  for i in range(0, len(positions)):
805
1138
  position = positions[i]
806
- cache.append(position)
1139
+ contracts = self.safe_number(position, 'contracts', 0)
1140
+ if contracts > 0:
1141
+ cache.append(position)
807
1142
  # don't remove the future from the .futures cache
808
1143
  future = client.futures[messageHash]
809
1144
  future.resolve(cache)
@@ -847,8 +1182,28 @@ class gate(ccxt.async_support.gate):
847
1182
  for i in range(0, len(data)):
848
1183
  rawPosition = data[i]
849
1184
  position = self.parse_position(rawPosition)
850
- newPositions.append(position)
851
- cache.append(position)
1185
+ symbol = self.safe_string(position, 'symbol')
1186
+ side = self.safe_string(position, 'side')
1187
+ # Control when position is closed no side is returned
1188
+ if side is None:
1189
+ prevLongPosition = self.safe_dict(cache, symbol + 'long')
1190
+ if prevLongPosition is not None:
1191
+ position['side'] = prevLongPosition['side']
1192
+ newPositions.append(position)
1193
+ cache.append(position)
1194
+ prevShortPosition = self.safe_dict(cache, symbol + 'short')
1195
+ if prevShortPosition is not None:
1196
+ position['side'] = prevShortPosition['side']
1197
+ newPositions.append(position)
1198
+ cache.append(position)
1199
+ # if no prev position is found, default to long
1200
+ if prevLongPosition is None and prevShortPosition is None:
1201
+ position['side'] = 'long'
1202
+ newPositions.append(position)
1203
+ cache.append(position)
1204
+ else:
1205
+ newPositions.append(position)
1206
+ cache.append(position)
852
1207
  messageHashes = self.find_message_hashes(client, type + ':positions::')
853
1208
  for i in range(0, len(messageHashes)):
854
1209
  messageHash = messageHashes[i]
@@ -869,7 +1224,7 @@ class gate(ccxt.async_support.gate):
869
1224
  :param dict [params]: extra parameters specific to the exchange API endpoint
870
1225
  :param str [params.type]: spot, margin, swap, future, or option. Required if listening to all symbols.
871
1226
  :param boolean [params.isInverse]: if future, listen to inverse or linear contracts
872
- :returns dict[]: a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure
1227
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
873
1228
  """
874
1229
  await self.load_markets()
875
1230
  market = None
@@ -956,7 +1311,7 @@ class gate(ccxt.async_support.gate):
956
1311
  elif event == 'finish':
957
1312
  status = self.safe_string(parsed, 'status')
958
1313
  if status is None:
959
- left = self.safe_number(info, 'left')
1314
+ left = self.safe_integer(info, 'left')
960
1315
  parsed['status'] = 'closed' if (left == 0) else 'canceled'
961
1316
  stored.append(parsed)
962
1317
  symbol = parsed['symbol']
@@ -971,9 +1326,11 @@ class gate(ccxt.async_support.gate):
971
1326
  async def watch_my_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
972
1327
  """
973
1328
  watch the public liquidations of a trading pair
974
- :see: https://www.gate.io/docs/developers/futures/ws/en/#liquidates-api
975
- :see: https://www.gate.io/docs/developers/delivery/ws/en/#liquidates-api
976
- :see: https://www.gate.io/docs/developers/options/ws/en/#liquidates-channel
1329
+
1330
+ https://www.gate.io/docs/developers/futures/ws/en/#liquidates-api
1331
+ https://www.gate.io/docs/developers/delivery/ws/en/#liquidates-api
1332
+ https://www.gate.io/docs/developers/options/ws/en/#liquidates-channel
1333
+
977
1334
  :param str symbol: unified CCXT market symbol
978
1335
  :param int [since]: the earliest time in ms to fetch liquidations for
979
1336
  :param int [limit]: the maximum number of liquidation structures to retrieve
@@ -982,13 +1339,15 @@ class gate(ccxt.async_support.gate):
982
1339
  """
983
1340
  return self.watch_my_liquidations_for_symbols([symbol], since, limit, params)
984
1341
 
985
- async def watch_my_liquidations_for_symbols(self, symbols: List[str] = None, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
1342
+ async def watch_my_liquidations_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
986
1343
  """
987
1344
  watch the private liquidations of a trading pair
988
- :see: https://www.gate.io/docs/developers/futures/ws/en/#liquidates-api
989
- :see: https://www.gate.io/docs/developers/delivery/ws/en/#liquidates-api
990
- :see: https://www.gate.io/docs/developers/options/ws/en/#liquidates-channel
991
- :param str symbol: unified CCXT market symbol
1345
+
1346
+ https://www.gate.io/docs/developers/futures/ws/en/#liquidates-api
1347
+ https://www.gate.io/docs/developers/delivery/ws/en/#liquidates-api
1348
+ https://www.gate.io/docs/developers/options/ws/en/#liquidates-channel
1349
+
1350
+ :param str[] symbols: unified CCXT market symbols
992
1351
  :param int [since]: the earliest time in ms to fetch liquidations for
993
1352
  :param int [limit]: the maximum number of liquidation structures to retrieve
994
1353
  :param dict [params]: exchange specific parameters for the gate api endpoint
@@ -1134,38 +1493,88 @@ class gate(ccxt.async_support.gate):
1134
1493
  'datetime': self.iso8601(timestamp),
1135
1494
  })
1136
1495
 
1137
- def handle_error_message(self, client: Client, message):
1138
- # {
1139
- # "time": 1647274664,
1140
- # "channel": "futures.orders",
1141
- # "event": "subscribe",
1142
- # "error": {code: 2, message: "unknown contract BTC_USDT_20220318"},
1143
- # }
1144
- # {
1145
- # "time": 1647276473,
1146
- # "channel": "futures.orders",
1147
- # "event": "subscribe",
1148
- # "error": {
1149
- # "code": 4,
1150
- # "message": "{"label":"INVALID_KEY","message":"Invalid key provided"}\n"
1151
- # },
1152
- # "result": null
1153
- # }
1154
- error = self.safe_value(message, 'error')
1155
- code = self.safe_integer(error, 'code')
1156
- id = self.safe_string(message, 'id')
1157
- if id is None:
1158
- return False
1159
- if code is not None:
1496
+ def handle_error_message(self, client: Client, message) -> Bool:
1497
+ #
1498
+ # {
1499
+ # "time": 1647274664,
1500
+ # "channel": "futures.orders",
1501
+ # "event": "subscribe",
1502
+ # "error": {code: 2, message: "unknown contract BTC_USDT_20220318"},
1503
+ # }
1504
+ # {
1505
+ # "time": 1647276473,
1506
+ # "channel": "futures.orders",
1507
+ # "event": "subscribe",
1508
+ # "error": {
1509
+ # "code": 4,
1510
+ # "message": "{"label":"INVALID_KEY","message":"Invalid key provided"}\n"
1511
+ # },
1512
+ # "result": null
1513
+ # }
1514
+ # {
1515
+ # header: {
1516
+ # response_time: '1718551891329',
1517
+ # status: '400',
1518
+ # channel: 'spot.order_place',
1519
+ # event: 'api',
1520
+ # client_id: '81.34.68.6-0xc16375e2c0',
1521
+ # conn_id: '9539116e0e09678f'
1522
+ # },
1523
+ # data: {errs: {label: 'AUTHENTICATION_FAILED', message: 'Not login'}},
1524
+ # request_id: '10406147'
1525
+ # }
1526
+ # {
1527
+ # "time": 1739853211,
1528
+ # "time_ms": 1739853211201,
1529
+ # "id": 1,
1530
+ # "conn_id": "62f2c1dabbe186d7",
1531
+ # "trace_id": "cdb02a8c0b61086b2fe6f8fad2f98c54",
1532
+ # "channel": "spot.trades",
1533
+ # "event": "subscribe",
1534
+ # "payload": [
1535
+ # "LUNARLENS_USDT",
1536
+ # "ETH_USDT"
1537
+ # ],
1538
+ # "error": {
1539
+ # "code": 2,
1540
+ # "message": "unknown currency pair: LUNARLENS_USDT"
1541
+ # },
1542
+ # "result": {
1543
+ # "status": "fail"
1544
+ # },
1545
+ # "requestId": "cdb02a8c0b61086b2fe6f8fad2f98c54"
1546
+ # }
1547
+ #
1548
+ data = self.safe_dict(message, 'data')
1549
+ errs = self.safe_dict(data, 'errs')
1550
+ error = self.safe_dict(message, 'error', errs)
1551
+ code = self.safe_string_2(error, 'code', 'label')
1552
+ id = self.safe_string_n(message, ['id', 'requestId', 'request_id'])
1553
+ if error is not None:
1160
1554
  messageHash = self.safe_string(client.subscriptions, id)
1161
- if messageHash is not None:
1162
- try:
1163
- self.throw_exactly_matched_exception(self.exceptions['ws']['exact'], code, self.json(message))
1164
- except Exception as e:
1165
- client.reject(e, messageHash)
1166
- if messageHash in client.subscriptions:
1167
- del client.subscriptions[messageHash]
1168
- del client.subscriptions[id]
1555
+ try:
1556
+ self.throw_exactly_matched_exception(self.exceptions['ws']['exact'], code, self.json(message))
1557
+ self.throw_exactly_matched_exception(self.exceptions['exact'], code, self.json(errs))
1558
+ errorMessage = self.safe_string(error, 'message', self.safe_string(errs, 'message'))
1559
+ self.throw_broadly_matched_exception(self.exceptions['ws']['broad'], errorMessage, self.json(message))
1560
+ raise ExchangeError(self.json(message))
1561
+ except Exception as e:
1562
+ client.reject(e, messageHash)
1563
+ if (messageHash is not None) and (messageHash in client.subscriptions):
1564
+ del client.subscriptions[messageHash]
1565
+ # remove subscriptions for watchSymbols
1566
+ channel = self.safe_string(message, 'channel')
1567
+ if (channel is not None) and (channel.find('.') > 0):
1568
+ parsedChannel = channel.split('.')
1569
+ payload = self.safe_list(message, 'payload', [])
1570
+ for i in range(0, len(payload)):
1571
+ marketType = parsedChannel[0] == 'swap' if 'futures' else parsedChannel[0]
1572
+ symbol = self.safe_symbol(payload[i], None, '_', marketType)
1573
+ messageHashSymbol = parsedChannel[1] + ':' + symbol
1574
+ if (messageHashSymbol is not None) and (messageHashSymbol in client.subscriptions):
1575
+ del client.subscriptions[messageHashSymbol]
1576
+ if (id is not None) and (id in client.subscriptions):
1577
+ del client.subscriptions[id]
1169
1578
  return True
1170
1579
  return False
1171
1580
 
@@ -1188,6 +1597,73 @@ class gate(ccxt.async_support.gate):
1188
1597
  if id in client.subscriptions:
1189
1598
  del client.subscriptions[id]
1190
1599
 
1600
+ def handle_un_subscribe(self, client: Client, message):
1601
+ #
1602
+ # {
1603
+ # "time":1725534679,
1604
+ # "time_ms":1725534679786,
1605
+ # "id":2,
1606
+ # "conn_id":"fac539b443fd7002",
1607
+ # "trace_id":"efe1d282b630b4aa266b84bee177791a",
1608
+ # "channel":"spot.trades",
1609
+ # "event":"unsubscribe",
1610
+ # "payload":[
1611
+ # "LTC_USDT"
1612
+ # ],
1613
+ # "result":{
1614
+ # "status":"success"
1615
+ # },
1616
+ # "requestId":"efe1d282b630b4aa266b84bee177791a"
1617
+ # }
1618
+ #
1619
+ id = self.safe_string(message, 'id')
1620
+ keys = list(client.subscriptions.keys())
1621
+ for i in range(0, len(keys)):
1622
+ messageHash = keys[i]
1623
+ if not (messageHash in client.subscriptions):
1624
+ continue
1625
+ # the previous iteration can have deleted the messageHash from the subscriptions
1626
+ if messageHash.startswith('unsubscribe'):
1627
+ subscription = client.subscriptions[messageHash]
1628
+ subId = self.safe_string(subscription, 'id')
1629
+ if id != subId:
1630
+ continue
1631
+ messageHashes = self.safe_list(subscription, 'messageHashes', [])
1632
+ subMessageHashes = self.safe_list(subscription, 'subMessageHashes', [])
1633
+ for j in range(0, len(messageHashes)):
1634
+ unsubHash = messageHashes[j]
1635
+ subHash = subMessageHashes[j]
1636
+ self.clean_unsubscription(client, subHash, unsubHash)
1637
+ self.clean_cache(subscription)
1638
+
1639
+ def clean_cache(self, subscription: dict):
1640
+ topic = self.safe_string(subscription, 'topic', '')
1641
+ symbols = self.safe_list(subscription, 'symbols', [])
1642
+ symbolsLength = len(symbols)
1643
+ if topic == 'ohlcv':
1644
+ symbolsAndTimeFrames = self.safe_list(subscription, 'symbolsAndTimeframes', [])
1645
+ for i in range(0, len(symbolsAndTimeFrames)):
1646
+ symbolAndTimeFrame = symbolsAndTimeFrames[i]
1647
+ symbol = self.safe_string(symbolAndTimeFrame, 0)
1648
+ timeframe = self.safe_string(symbolAndTimeFrame, 1)
1649
+ del self.ohlcvs[symbol][timeframe]
1650
+ elif symbolsLength > 0:
1651
+ for i in range(0, len(symbols)):
1652
+ symbol = symbols[i]
1653
+ if topic.endswith('trades'):
1654
+ del self.trades[symbol]
1655
+ elif topic == 'orderbook':
1656
+ del self.orderbooks[symbol]
1657
+ elif topic == 'ticker':
1658
+ del self.tickers[symbol]
1659
+ else:
1660
+ if topic.endswith('trades'):
1661
+ # don't reset self.myTrades directly here
1662
+ # because in c# we need to use a different object
1663
+ keys = list(self.trades.keys())
1664
+ for i in range(0, len(keys)):
1665
+ del self.trades[keys[i]]
1666
+
1191
1667
  def handle_message(self, client: Client, message):
1192
1668
  #
1193
1669
  # subscribe
@@ -1284,6 +1760,9 @@ class gate(ccxt.async_support.gate):
1284
1760
  if event == 'subscribe':
1285
1761
  self.handle_subscription_status(client, message)
1286
1762
  return
1763
+ if event == 'unsubscribe':
1764
+ self.handle_un_subscribe(client, message)
1765
+ return
1287
1766
  channel = self.safe_string(message, 'channel', '')
1288
1767
  channelParts = channel.split('.')
1289
1768
  channelType = self.safe_value(channelParts, 1)
@@ -1302,6 +1781,17 @@ class gate(ccxt.async_support.gate):
1302
1781
  method = self.safe_value(v4Methods, channelType)
1303
1782
  if method is not None:
1304
1783
  method(client, message)
1784
+ requestId = self.safe_string(message, 'request_id')
1785
+ if requestId == 'authenticated':
1786
+ self.handle_authentication_message(client, message)
1787
+ return
1788
+ if requestId is not None:
1789
+ data = self.safe_dict(message, 'data')
1790
+ # use safeValue may be Array or an Object
1791
+ result = self.safe_value(data, 'result')
1792
+ ack = self.safe_bool(message, 'ack')
1793
+ if ack is not True:
1794
+ client.resolve(result, requestId)
1305
1795
 
1306
1796
  def get_url_by_market(self, market):
1307
1797
  baseUrl = self.urls['api'][market['type']]
@@ -1310,7 +1800,7 @@ class gate(ccxt.async_support.gate):
1310
1800
  else:
1311
1801
  return baseUrl
1312
1802
 
1313
- def get_type_by_market(self, market):
1803
+ def get_type_by_market(self, market: Market):
1314
1804
  if market['spot']:
1315
1805
  return 'spot'
1316
1806
  elif market['option']:
@@ -1318,7 +1808,7 @@ class gate(ccxt.async_support.gate):
1318
1808
  else:
1319
1809
  return 'futures'
1320
1810
 
1321
- def get_url_by_market_type(self, type, isInverse=False):
1811
+ def get_url_by_market_type(self, type: MarketType, isInverse=False):
1322
1812
  api = self.urls['api']
1323
1813
  url = api[type]
1324
1814
  if (type == 'swap') or (type == 'future'):
@@ -1377,6 +1867,74 @@ class gate(ccxt.async_support.gate):
1377
1867
  message = self.extend(request, params)
1378
1868
  return await self.watch_multiple(url, messageHashes, message, messageHashes)
1379
1869
 
1870
+ async def un_subscribe_public_multiple(self, url, topic, symbols, messageHashes, subMessageHashes, payload, channel, params={}):
1871
+ requestId = self.request_id()
1872
+ time = self.seconds()
1873
+ request: dict = {
1874
+ 'id': requestId,
1875
+ 'time': time,
1876
+ 'channel': channel,
1877
+ 'event': 'unsubscribe',
1878
+ 'payload': payload,
1879
+ }
1880
+ sub = {
1881
+ 'id': str(requestId),
1882
+ 'topic': topic,
1883
+ 'unsubscribe': True,
1884
+ 'messageHashes': messageHashes,
1885
+ 'subMessageHashes': subMessageHashes,
1886
+ 'symbols': symbols,
1887
+ }
1888
+ message = self.extend(request, params)
1889
+ return await self.watch_multiple(url, messageHashes, message, messageHashes, sub)
1890
+
1891
+ async def authenticate(self, url, messageType):
1892
+ channel = messageType + '.login'
1893
+ client = self.client(url)
1894
+ messageHash = 'authenticated'
1895
+ future = client.future(messageHash)
1896
+ authenticated = self.safe_value(client.subscriptions, messageHash)
1897
+ if authenticated is None:
1898
+ return await self.request_private(url, {}, channel, messageHash)
1899
+ return future
1900
+
1901
+ def handle_authentication_message(self, client: Client, message):
1902
+ messageHash = 'authenticated'
1903
+ future = self.safe_value(client.futures, messageHash)
1904
+ future.resolve(True)
1905
+
1906
+ async def request_private(self, url, reqParams, channel, requestId: Str = None):
1907
+ self.check_required_credentials()
1908
+ # uid is required for some subscriptions only so it's not a part of required credentials
1909
+ event = 'api'
1910
+ if requestId is None:
1911
+ reqId = self.request_id()
1912
+ requestId = str(reqId)
1913
+ messageHash = requestId
1914
+ time = self.seconds()
1915
+ # unfortunately, PHP demands double quotes for the escaped newline symbol
1916
+ signatureString = "\n".join([event, channel, self.json(reqParams), str(time)]) # eslint-disable-line quotes
1917
+ signature = self.hmac(self.encode(signatureString), self.encode(self.secret), hashlib.sha512, 'hex')
1918
+ payload: dict = {
1919
+ 'req_id': requestId,
1920
+ 'timestamp': str(time),
1921
+ 'api_key': self.apiKey,
1922
+ 'signature': signature,
1923
+ 'req_param': reqParams,
1924
+ }
1925
+ if (channel == 'spot.order_place') or (channel == 'futures.order_place'):
1926
+ payload['req_header'] = {
1927
+ 'X-Gate-Channel-Id': 'ccxt',
1928
+ }
1929
+ request: dict = {
1930
+ 'id': requestId,
1931
+ 'time': time,
1932
+ 'channel': channel,
1933
+ 'event': event,
1934
+ 'payload': payload,
1935
+ }
1936
+ return await self.watch(url, messageHash, request, messageHash, requestId)
1937
+
1380
1938
  async def subscribe_private(self, url, messageHash, payload, channel, params, requiresUid=False):
1381
1939
  self.check_required_credentials()
1382
1940
  # uid is required for some subscriptions only so it's not a part of required credentials
@@ -1402,7 +1960,7 @@ class gate(ccxt.async_support.gate):
1402
1960
  'id': requestId,
1403
1961
  'time': time,
1404
1962
  'channel': channel,
1405
- 'event': 'subscribe',
1963
+ 'event': event,
1406
1964
  'auth': auth,
1407
1965
  }
1408
1966
  if payload is not None:
@@ -1413,4 +1971,4 @@ class gate(ccxt.async_support.gate):
1413
1971
  # in case of authenticationError we will throw
1414
1972
  client.subscriptions[tempSubscriptionHash] = messageHash
1415
1973
  message = self.extend(request, params)
1416
- return await self.watch(url, messageHash, message, messageHash)
1974
+ return await self.watch(url, messageHash, message, messageHash, messageHash)