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/woofipro.py ADDED
@@ -0,0 +1,1271 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+
6
+ import ccxt.async_support
7
+ from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
8
+ from ccxt.base.types import Balances, Int, Order, OrderBook, Position, Str, Strings, Ticker, Tickers, Trade
9
+ from ccxt.async_support.base.ws.client import Client
10
+ from typing import List
11
+ from ccxt.base.errors import AuthenticationError
12
+ from ccxt.base.errors import NotSupported
13
+ from ccxt.base.precise import Precise
14
+
15
+
16
+ class woofipro(ccxt.async_support.woofipro):
17
+
18
+ def describe(self):
19
+ return self.deep_extend(super(woofipro, self).describe(), {
20
+ 'has': {
21
+ 'ws': True,
22
+ 'watchBalance': True,
23
+ 'watchMyTrades': True,
24
+ 'watchOHLCV': True,
25
+ 'watchOrderBook': True,
26
+ 'watchOrders': True,
27
+ 'watchTicker': True,
28
+ 'watchTickers': True,
29
+ 'watchBidsAsks': True,
30
+ 'watchTrades': True,
31
+ 'watchTradesForSymbols': False,
32
+ 'watchPositions': True,
33
+ },
34
+ 'urls': {
35
+ 'api': {
36
+ 'ws': {
37
+ 'public': 'wss://ws-evm.orderly.org/ws/stream',
38
+ 'private': 'wss://ws-private-evm.orderly.org/v2/ws/private/stream',
39
+ },
40
+ },
41
+ 'test': {
42
+ 'ws': {
43
+ 'public': 'wss://testnet-ws-evm.orderly.org/ws/stream',
44
+ 'private': 'wss://testnet-ws-private-evm.orderly.org/v2/ws/private/stream',
45
+ },
46
+ },
47
+ },
48
+ 'requiredCredentials': {
49
+ 'apiKey': True,
50
+ 'secret': True,
51
+ 'accountId': True,
52
+ },
53
+ 'options': {
54
+ 'tradesLimit': 1000,
55
+ 'ordersLimit': 1000,
56
+ 'requestId': {},
57
+ 'watchPositions': {
58
+ 'fetchPositionsSnapshot': True, # or False
59
+ 'awaitPositionsSnapshot': True, # whether to wait for the positions snapshot before providing updates
60
+ },
61
+ },
62
+ 'streaming': {
63
+ 'ping': self.ping,
64
+ 'keepAlive': 10000,
65
+ },
66
+ 'exceptions': {
67
+ 'ws': {
68
+ 'exact': {
69
+ 'Auth is needed.': AuthenticationError,
70
+ },
71
+ },
72
+ },
73
+ })
74
+
75
+ def request_id(self, url):
76
+ options = self.safe_dict(self.options, 'requestId', {})
77
+ previousValue = self.safe_integer(options, url, 0)
78
+ newValue = self.sum(previousValue, 1)
79
+ self.options['requestId'][url] = newValue
80
+ return newValue
81
+
82
+ async def watch_public(self, messageHash, message):
83
+ # the default id
84
+ id = 'OqdphuyCtYWxwzhxyLLjOWNdFP7sQt8RPWzmb5xY'
85
+ if self.accountId is not None:
86
+ id = self.accountId
87
+ url = self.urls['api']['ws']['public'] + '/' + id
88
+ requestId = self.request_id(url)
89
+ subscribe: dict = {
90
+ 'id': requestId,
91
+ }
92
+ request = self.extend(subscribe, message)
93
+ return await self.watch(url, messageHash, request, messageHash, subscribe)
94
+
95
+ async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
96
+ """
97
+
98
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/orderbook
99
+
100
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
101
+ :param str symbol: unified symbol of the market to fetch the order book for
102
+ :param int [limit]: the maximum amount of order book entries to return.
103
+ :param dict [params]: extra parameters specific to the exchange API endpoint
104
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
105
+ """
106
+ await self.load_markets()
107
+ name = 'orderbook'
108
+ market = self.market(symbol)
109
+ topic = market['id'] + '@' + name
110
+ request: dict = {
111
+ 'event': 'subscribe',
112
+ 'topic': topic,
113
+ }
114
+ message = self.extend(request, params)
115
+ orderbook = await self.watch_public(topic, message)
116
+ return orderbook.limit()
117
+
118
+ def handle_order_book(self, client: Client, message):
119
+ #
120
+ # {
121
+ # "topic": "PERP_BTC_USDC@orderbook",
122
+ # "ts": 1650121915308,
123
+ # "data": {
124
+ # "symbol": "PERP_BTC_USDC",
125
+ # "bids": [
126
+ # [
127
+ # 0.30891,
128
+ # 2469.98
129
+ # ]
130
+ # ],
131
+ # "asks": [
132
+ # [
133
+ # 0.31075,
134
+ # 2379.63
135
+ # ]
136
+ # ]
137
+ # }
138
+ # }
139
+ #
140
+ data = self.safe_dict(message, 'data', {})
141
+ marketId = self.safe_string(data, 'symbol')
142
+ market = self.safe_market(marketId)
143
+ symbol = market['symbol']
144
+ topic = self.safe_string(message, 'topic')
145
+ if not (symbol in self.orderbooks):
146
+ self.orderbooks[symbol] = self.order_book()
147
+ orderbook = self.orderbooks[symbol]
148
+ timestamp = self.safe_integer(message, 'ts')
149
+ snapshot = self.parse_order_book(data, symbol, timestamp, 'bids', 'asks')
150
+ orderbook.reset(snapshot)
151
+ client.resolve(orderbook, topic)
152
+
153
+ async def watch_ticker(self, symbol: str, params={}) -> Ticker:
154
+ """
155
+
156
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/24-hour-ticker
157
+
158
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
159
+ :param str symbol: unified symbol of the market to fetch the ticker for
160
+ :param dict [params]: extra parameters specific to the exchange API endpoint
161
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
162
+ """
163
+ await self.load_markets()
164
+ name = 'ticker'
165
+ market = self.market(symbol)
166
+ symbol = market['symbol']
167
+ topic = market['id'] + '@' + name
168
+ request: dict = {
169
+ 'event': 'subscribe',
170
+ 'topic': topic,
171
+ }
172
+ message = self.extend(request, params)
173
+ return await self.watch_public(topic, message)
174
+
175
+ def parse_ws_ticker(self, ticker, market=None):
176
+ #
177
+ # {
178
+ # "symbol": "PERP_BTC_USDC",
179
+ # "open": 19441.5,
180
+ # "close": 20147.07,
181
+ # "high": 20761.87,
182
+ # "low": 19320.54,
183
+ # "volume": 2481.103,
184
+ # "amount": 50037935.0286,
185
+ # "count": 3689
186
+ # }
187
+ #
188
+ return self.safe_ticker({
189
+ 'symbol': self.safe_symbol(None, market),
190
+ 'timestamp': None,
191
+ 'datetime': None,
192
+ 'high': self.safe_string(ticker, 'high'),
193
+ 'low': self.safe_string(ticker, 'low'),
194
+ 'bid': None,
195
+ 'bidVolume': None,
196
+ 'ask': None,
197
+ 'askVolume': None,
198
+ 'vwap': None,
199
+ 'open': self.safe_string(ticker, 'open'),
200
+ 'close': self.safe_string(ticker, 'close'),
201
+ 'last': None,
202
+ 'previousClose': None,
203
+ 'change': None,
204
+ 'percentage': None,
205
+ 'average': None,
206
+ 'baseVolume': self.safe_string(ticker, 'volume'),
207
+ 'quoteVolume': self.safe_string(ticker, 'amount'),
208
+ 'info': ticker,
209
+ }, market)
210
+
211
+ def handle_ticker(self, client: Client, message):
212
+ #
213
+ # {
214
+ # "topic": "PERP_BTC_USDC@ticker",
215
+ # "ts": 1657120017000,
216
+ # "data": {
217
+ # "symbol": "PERP_BTC_USDC",
218
+ # "open": 19441.5,
219
+ # "close": 20147.07,
220
+ # "high": 20761.87,
221
+ # "low": 19320.54,
222
+ # "volume": 2481.103,
223
+ # "amount": 50037935.0286,
224
+ # "count": 3689
225
+ # }
226
+ # }
227
+ #
228
+ data = self.safe_dict(message, 'data', {})
229
+ topic = self.safe_string(message, 'topic')
230
+ marketId = self.safe_string(data, 'symbol')
231
+ market = self.safe_market(marketId)
232
+ timestamp = self.safe_integer(message, 'ts')
233
+ data['date'] = timestamp
234
+ ticker = self.parse_ws_ticker(data, market)
235
+ ticker['symbol'] = market['symbol']
236
+ self.tickers[market['symbol']] = ticker
237
+ client.resolve(ticker, topic)
238
+ return message
239
+
240
+ async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
241
+ """
242
+
243
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/24-hour-tickers
244
+
245
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
246
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
247
+ :param dict [params]: extra parameters specific to the exchange API endpoint
248
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
249
+ """
250
+ await self.load_markets()
251
+ symbols = self.market_symbols(symbols)
252
+ name = 'tickers'
253
+ topic = name
254
+ request: dict = {
255
+ 'event': 'subscribe',
256
+ 'topic': topic,
257
+ }
258
+ message = self.extend(request, params)
259
+ tickers = await self.watch_public(topic, message)
260
+ return self.filter_by_array(tickers, 'symbol', symbols)
261
+
262
+ def handle_tickers(self, client: Client, message):
263
+ #
264
+ # {
265
+ # "topic":"tickers",
266
+ # "ts":1618820615000,
267
+ # "data":[
268
+ # {
269
+ # "symbol":"PERP_NEAR_USDC",
270
+ # "open":16.297,
271
+ # "close":17.183,
272
+ # "high":24.707,
273
+ # "low":11.997,
274
+ # "volume":0,
275
+ # "amount":0,
276
+ # "count":0
277
+ # },
278
+ # ...
279
+ # ]
280
+ # }
281
+ #
282
+ topic = self.safe_string(message, 'topic')
283
+ data = self.safe_list(message, 'data', [])
284
+ timestamp = self.safe_integer(message, 'ts')
285
+ result = []
286
+ for i in range(0, len(data)):
287
+ marketId = self.safe_string(data[i], 'symbol')
288
+ market = self.safe_market(marketId)
289
+ ticker = self.parse_ws_ticker(self.extend(data[i], {'date': timestamp}), market)
290
+ self.tickers[market['symbol']] = ticker
291
+ result.append(ticker)
292
+ client.resolve(result, topic)
293
+
294
+ async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
295
+ """
296
+
297
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/bbos
298
+
299
+ watches best bid & ask for symbols
300
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
301
+ :param dict [params]: extra parameters specific to the exchange API endpoint
302
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
303
+ """
304
+ await self.load_markets()
305
+ symbols = self.market_symbols(symbols)
306
+ name = 'bbos'
307
+ topic = name
308
+ request: dict = {
309
+ 'event': 'subscribe',
310
+ 'topic': topic,
311
+ }
312
+ message = self.extend(request, params)
313
+ tickers = await self.watch_public(topic, message)
314
+ return self.filter_by_array(tickers, 'symbol', symbols)
315
+
316
+ def handle_bid_ask(self, client: Client, message):
317
+ #
318
+ # {
319
+ # "topic": "bbos",
320
+ # "ts": 1726212495000,
321
+ # "data": [
322
+ # {
323
+ # "symbol": "PERP_WOO_USDC",
324
+ # "ask": 0.16570,
325
+ # "askSize": 4224,
326
+ # "bid": 0.16553,
327
+ # "bidSize": 6645
328
+ # }
329
+ # ]
330
+ # }
331
+ #
332
+ topic = self.safe_string(message, 'topic')
333
+ data = self.safe_list(message, 'data', [])
334
+ timestamp = self.safe_integer(message, 'ts')
335
+ result = []
336
+ for i in range(0, len(data)):
337
+ ticker = self.parse_ws_bid_ask(self.extend(data[i], {'ts': timestamp}))
338
+ self.tickers[ticker['symbol']] = ticker
339
+ result.append(ticker)
340
+ client.resolve(result, topic)
341
+
342
+ def parse_ws_bid_ask(self, ticker, market=None):
343
+ marketId = self.safe_string(ticker, 'symbol')
344
+ market = self.safe_market(marketId, market)
345
+ symbol = self.safe_string(market, 'symbol')
346
+ timestamp = self.safe_integer(ticker, 'ts')
347
+ return self.safe_ticker({
348
+ 'symbol': symbol,
349
+ 'timestamp': timestamp,
350
+ 'datetime': self.iso8601(timestamp),
351
+ 'ask': self.safe_string(ticker, 'ask'),
352
+ 'askVolume': self.safe_string(ticker, 'askSize'),
353
+ 'bid': self.safe_string(ticker, 'bid'),
354
+ 'bidVolume': self.safe_string(ticker, 'bidSize'),
355
+ 'info': ticker,
356
+ }, market)
357
+
358
+ async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
359
+ """
360
+ watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
361
+
362
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/k-line
363
+
364
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
365
+ :param str timeframe: the length of time each candle represents
366
+ :param int [since]: timestamp in ms of the earliest candle to fetch
367
+ :param int [limit]: the maximum amount of candles to fetch
368
+ :param dict [params]: extra parameters specific to the exchange API endpoint
369
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
370
+ """
371
+ await self.load_markets()
372
+ if (timeframe != '1m') and (timeframe != '5m') and (timeframe != '15m') and (timeframe != '30m') and (timeframe != '1h') and (timeframe != '1d') and (timeframe != '1w') and (timeframe != '1M'):
373
+ raise NotSupported(self.id + ' watchOHLCV timeframe argument must be 1m, 5m, 15m, 30m, 1h, 1d, 1w, 1M')
374
+ market = self.market(symbol)
375
+ interval = self.safe_string(self.timeframes, timeframe, timeframe)
376
+ name = 'kline'
377
+ topic = market['id'] + '@' + name + '_' + interval
378
+ request: dict = {
379
+ 'event': 'subscribe',
380
+ 'topic': topic,
381
+ }
382
+ message = self.extend(request, params)
383
+ ohlcv = await self.watch_public(topic, message)
384
+ if self.newUpdates:
385
+ limit = ohlcv.getLimit(market['symbol'], limit)
386
+ return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
387
+
388
+ def handle_ohlcv(self, client: Client, message):
389
+ #
390
+ # {
391
+ # "topic":"PERP_BTC_USDC@kline_1m",
392
+ # "ts":1618822432146,
393
+ # "data":{
394
+ # "symbol":"PERP_BTC_USDC",
395
+ # "type":"1m",
396
+ # "open":56948.97,
397
+ # "close":56891.76,
398
+ # "high":56948.97,
399
+ # "low":56889.06,
400
+ # "volume":44.00947568,
401
+ # "amount":2504584.9,
402
+ # "startTime":1618822380000,
403
+ # "endTime":1618822440000
404
+ # }
405
+ # }
406
+ #
407
+ data = self.safe_dict(message, 'data', {})
408
+ topic = self.safe_string(message, 'topic')
409
+ marketId = self.safe_string(data, 'symbol')
410
+ market = self.safe_market(marketId)
411
+ symbol = market['symbol']
412
+ interval = self.safe_string(data, 'type')
413
+ timeframe = self.find_timeframe(interval)
414
+ parsed = [
415
+ self.safe_integer(data, 'startTime'),
416
+ self.safe_number(data, 'open'),
417
+ self.safe_number(data, 'high'),
418
+ self.safe_number(data, 'low'),
419
+ self.safe_number(data, 'close'),
420
+ self.safe_number(data, 'volume'),
421
+ ]
422
+ self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
423
+ stored = self.safe_value(self.ohlcvs[symbol], timeframe)
424
+ if stored is None:
425
+ limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
426
+ stored = ArrayCacheByTimestamp(limit)
427
+ self.ohlcvs[symbol][timeframe] = stored
428
+ ohlcvCache = self.ohlcvs[symbol][timeframe]
429
+ ohlcvCache.append(parsed)
430
+ client.resolve(ohlcvCache, topic)
431
+
432
+ async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
433
+ """
434
+ watches information on multiple trades made in a market
435
+
436
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/trade
437
+
438
+ :param str symbol: unified market symbol of the market trades were made in
439
+ :param int [since]: the earliest time in ms to fetch trades for
440
+ :param int [limit]: the maximum number of trade structures to retrieve
441
+ :param dict [params]: extra parameters specific to the exchange API endpoint
442
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
443
+ """
444
+ await self.load_markets()
445
+ market = self.market(symbol)
446
+ symbol = market['symbol']
447
+ topic = market['id'] + '@trade'
448
+ request: dict = {
449
+ 'event': 'subscribe',
450
+ 'topic': topic,
451
+ }
452
+ message = self.extend(request, params)
453
+ trades = await self.watch_public(topic, message)
454
+ if self.newUpdates:
455
+ limit = trades.getLimit(market['symbol'], limit)
456
+ return self.filter_by_symbol_since_limit(trades, symbol, since, limit, True)
457
+
458
+ def handle_trade(self, client: Client, message):
459
+ #
460
+ # {
461
+ # "topic":"PERP_ADA_USDC@trade",
462
+ # "ts":1618820361552,
463
+ # "data":{
464
+ # "symbol":"PERP_ADA_USDC",
465
+ # "price":1.27988,
466
+ # "size":300,
467
+ # "side":"BUY",
468
+ # }
469
+ # }
470
+ #
471
+ topic = self.safe_string(message, 'topic')
472
+ timestamp = self.safe_integer(message, 'ts')
473
+ data = self.safe_dict(message, 'data', {})
474
+ marketId = self.safe_string(data, 'symbol')
475
+ market = self.safe_market(marketId)
476
+ symbol = market['symbol']
477
+ trade = self.parse_ws_trade(self.extend(data, {'timestamp': timestamp}), market)
478
+ if not (symbol in self.trades):
479
+ limit = self.safe_integer(self.options, 'tradesLimit', 1000)
480
+ stored = ArrayCache(limit)
481
+ self.trades[symbol] = stored
482
+ trades = self.trades[symbol]
483
+ trades.append(trade)
484
+ self.trades[symbol] = trades
485
+ client.resolve(trades, topic)
486
+
487
+ def parse_ws_trade(self, trade, market=None):
488
+ #
489
+ # {
490
+ # "symbol":"PERP_ADA_USDC",
491
+ # "timestamp":1618820361552,
492
+ # "price":1.27988,
493
+ # "size":300,
494
+ # "side":"BUY",
495
+ # }
496
+ # private stream
497
+ # {
498
+ # symbol: 'PERP_XRP_USDC',
499
+ # clientOrderId: '',
500
+ # orderId: 1167632251,
501
+ # type: 'MARKET',
502
+ # side: 'BUY',
503
+ # quantity: 20,
504
+ # price: 0,
505
+ # tradeId: '1715179456664012',
506
+ # executedPrice: 0.5276,
507
+ # executedQuantity: 20,
508
+ # fee: 0.006332,
509
+ # feeAsset: 'USDC',
510
+ # totalExecutedQuantity: 20,
511
+ # avgPrice: 0.5276,
512
+ # averageExecutedPrice: 0.5276,
513
+ # status: 'FILLED',
514
+ # reason: '',
515
+ # totalFee: 0.006332,
516
+ # visible: 0,
517
+ # visibleQuantity: 0,
518
+ # timestamp: 1715179456660,
519
+ # orderTag: 'CCXT',
520
+ # createdTime: 1715179456656,
521
+ # maker: False
522
+ # }
523
+ #
524
+ marketId = self.safe_string(trade, 'symbol')
525
+ market = self.safe_market(marketId, market)
526
+ symbol = market['symbol']
527
+ price = self.safe_string_2(trade, 'executedPrice', 'price')
528
+ amount = self.safe_string_2(trade, 'executedQuantity', 'size')
529
+ cost = Precise.string_mul(price, amount)
530
+ side = self.safe_string_lower(trade, 'side')
531
+ timestamp = self.safe_integer(trade, 'timestamp')
532
+ takerOrMaker = None
533
+ maker = self.safe_bool(trade, 'maker')
534
+ if maker is not None:
535
+ takerOrMaker = 'maker' if maker else 'taker'
536
+ fee = None
537
+ feeValue = self.safe_string(trade, 'fee')
538
+ if feeValue is not None:
539
+ fee = {
540
+ 'cost': feeValue,
541
+ 'currency': self.safe_currency_code(self.safe_string(trade, 'feeAsset')),
542
+ }
543
+ return self.safe_trade({
544
+ 'id': self.safe_string(trade, 'tradeId'),
545
+ 'timestamp': timestamp,
546
+ 'datetime': self.iso8601(timestamp),
547
+ 'symbol': symbol,
548
+ 'side': side,
549
+ 'price': price,
550
+ 'amount': amount,
551
+ 'cost': cost,
552
+ 'order': self.safe_string(trade, 'orderId'),
553
+ 'takerOrMaker': takerOrMaker,
554
+ 'type': self.safe_string_lower(trade, 'type'),
555
+ 'fee': fee,
556
+ 'info': trade,
557
+ }, market)
558
+
559
+ def handle_auth(self, client: Client, message):
560
+ #
561
+ # {
562
+ # "event": "auth",
563
+ # "success": True,
564
+ # "ts": 1657463158812
565
+ # }
566
+ #
567
+ messageHash = 'authenticated'
568
+ success = self.safe_value(message, 'success')
569
+ if success:
570
+ # client.resolve(message, messageHash)
571
+ future = self.safe_value(client.futures, 'authenticated')
572
+ future.resolve(True)
573
+ else:
574
+ error = AuthenticationError(self.json(message))
575
+ client.reject(error, messageHash)
576
+ # allows further authentication attempts
577
+ if messageHash in client.subscriptions:
578
+ del client.subscriptions['authenticated']
579
+
580
+ async def authenticate(self, params={}):
581
+ self.check_required_credentials()
582
+ url = self.urls['api']['ws']['private'] + '/' + self.accountId
583
+ client = self.client(url)
584
+ messageHash = 'authenticated'
585
+ event = 'auth'
586
+ future = client.future(messageHash)
587
+ authenticated = self.safe_value(client.subscriptions, messageHash)
588
+ if authenticated is None:
589
+ ts = str(self.nonce())
590
+ auth = ts
591
+ secret = self.secret
592
+ if secret.find('ed25519:') >= 0:
593
+ parts = secret.split('ed25519:')
594
+ secret = parts[1]
595
+ signature = self.eddsa(self.encode(auth), self.base58_to_binary(secret), 'ed25519')
596
+ request: dict = {
597
+ 'event': event,
598
+ 'params': {
599
+ 'orderly_key': self.apiKey,
600
+ 'sign': signature,
601
+ 'timestamp': ts,
602
+ },
603
+ }
604
+ message = self.extend(request, params)
605
+ self.watch(url, messageHash, message, messageHash)
606
+ return await future
607
+
608
+ async def watch_private(self, messageHash, message, params={}):
609
+ await self.authenticate(params)
610
+ url = self.urls['api']['ws']['private'] + '/' + self.accountId
611
+ requestId = self.request_id(url)
612
+ subscribe: dict = {
613
+ 'id': requestId,
614
+ }
615
+ request = self.extend(subscribe, message)
616
+ return await self.watch(url, messageHash, request, messageHash, subscribe)
617
+
618
+ async def watch_private_multiple(self, messageHashes, message, params={}):
619
+ await self.authenticate(params)
620
+ url = self.urls['api']['ws']['private'] + '/' + self.accountId
621
+ requestId = self.request_id(url)
622
+ subscribe: dict = {
623
+ 'id': requestId,
624
+ }
625
+ request = self.extend(subscribe, message)
626
+ return await self.watch_multiple(url, messageHashes, request, messageHashes, subscribe)
627
+
628
+ async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
629
+ """
630
+ watches information on multiple orders made by the user
631
+
632
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/execution-report
633
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/algo-execution-report
634
+
635
+ :param str symbol: unified market symbol of the market orders were made in
636
+ :param int [since]: the earliest time in ms to fetch orders for
637
+ :param int [limit]: the maximum number of order structures to retrieve
638
+ :param dict [params]: extra parameters specific to the exchange API endpoint
639
+ :param bool [params.trigger]: True if trigger order
640
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
641
+ """
642
+ await self.load_markets()
643
+ trigger = self.safe_bool_2(params, 'stop', 'trigger', False)
644
+ topic = 'algoexecutionreport' if (trigger) else 'executionreport'
645
+ params = self.omit(params, ['stop', 'trigger'])
646
+ messageHash = topic
647
+ if symbol is not None:
648
+ market = self.market(symbol)
649
+ symbol = market['symbol']
650
+ messageHash += ':' + symbol
651
+ request: dict = {
652
+ 'event': 'subscribe',
653
+ 'topic': topic,
654
+ }
655
+ message = self.extend(request, params)
656
+ orders = await self.watch_private(messageHash, message)
657
+ if self.newUpdates:
658
+ limit = orders.getLimit(symbol, limit)
659
+ return self.filter_by_symbol_since_limit(orders, symbol, since, limit, True)
660
+
661
+ async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
662
+ """
663
+ watches information on multiple trades made by the user
664
+
665
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/execution-report
666
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/algo-execution-report
667
+
668
+ :param str symbol: unified market symbol of the market orders were made in
669
+ :param int [since]: the earliest time in ms to fetch orders for
670
+ :param int [limit]: the maximum number of order structures to retrieve
671
+ :param dict [params]: extra parameters specific to the exchange API endpoint
672
+ :param bool [params.trigger]: True if trigger order
673
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
674
+ """
675
+ await self.load_markets()
676
+ trigger = self.safe_bool_2(params, 'stop', 'trigger', False)
677
+ topic = 'algoexecutionreport' if (trigger) else 'executionreport'
678
+ params = self.omit(params, 'stop')
679
+ messageHash = 'myTrades'
680
+ if symbol is not None:
681
+ market = self.market(symbol)
682
+ symbol = market['symbol']
683
+ messageHash += ':' + symbol
684
+ request: dict = {
685
+ 'event': 'subscribe',
686
+ 'topic': topic,
687
+ }
688
+ message = self.extend(request, params)
689
+ orders = await self.watch_private(messageHash, message)
690
+ if self.newUpdates:
691
+ limit = orders.getLimit(symbol, limit)
692
+ return self.filter_by_symbol_since_limit(orders, symbol, since, limit, True)
693
+
694
+ def parse_ws_order(self, order, market=None):
695
+ #
696
+ # {
697
+ # "symbol": "PERP_BTC_USDT",
698
+ # "clientOrderId": 0,
699
+ # "orderId": 52952826,
700
+ # "type": "LIMIT",
701
+ # "side": "SELL",
702
+ # "quantity": 0.01,
703
+ # "price": 22000,
704
+ # "tradeId": 0,
705
+ # "executedPrice": 0,
706
+ # "executedQuantity": 0,
707
+ # "fee": 0,
708
+ # "feeAsset": "USDT",
709
+ # "totalExecutedQuantity": 0,
710
+ # "status": "NEW",
711
+ # "reason": '',
712
+ # "orderTag": "default",
713
+ # "totalFee": 0,
714
+ # "visible": 0.01,
715
+ # "timestamp": 1657515556799,
716
+ # "reduceOnly": False,
717
+ # "maker": False
718
+ # }
719
+ # algo order
720
+ # {
721
+ # "symbol":"PERP_MATIC_USDC",
722
+ # "rootAlgoOrderId":123,
723
+ # "parentAlgoOrderId":123,
724
+ # "algoOrderId":123,
725
+ # "orderTag":"some tags",
726
+ # "algoType": "STOP",
727
+ # "clientOrderId":"client_id",
728
+ # "type":"LIMIT",
729
+ # "side":"BUY",
730
+ # "quantity":7029.0,
731
+ # "price":0.7699,
732
+ # "tradeId":0,
733
+ # "triggerTradePrice":0,
734
+ # "triggerTime":1234567,
735
+ # "triggered": False,
736
+ # "activated": False,
737
+ # "executedPrice":0.0,
738
+ # "executedQuantity":0.0,
739
+ # "fee":0.0,
740
+ # "feeAsset":"USDC",
741
+ # "totalExecutedQuantity":0.0,
742
+ # "averageExecutedQuantity":0.0,
743
+ # "avgPrice":0,
744
+ # "triggerPrice":0.0,
745
+ # "triggerPriceType":"STOP",
746
+ # "isActivated": False,
747
+ # "status":"NEW",
748
+ # "rootAlgoStatus": "FILLED",
749
+ # "algoStatus": "FILLED",
750
+ # "reason":"",
751
+ # "totalFee":0.0,
752
+ # "visible": 7029.0,
753
+ # "visibleQuantity":7029.0,
754
+ # "timestamp":1704679472448,
755
+ # "maker":false,
756
+ # "isMaker":false,
757
+ # "createdTime":1704679472448
758
+ # }
759
+ #
760
+ orderId = self.safe_string(order, 'orderId')
761
+ marketId = self.safe_string(order, 'symbol')
762
+ market = self.market(marketId)
763
+ symbol = market['symbol']
764
+ timestamp = self.safe_integer(order, 'timestamp')
765
+ fee = {
766
+ 'cost': self.safe_string(order, 'totalFee'),
767
+ 'currency': self.safe_string(order, 'feeAsset'),
768
+ }
769
+ priceString = self.safe_string(order, 'price')
770
+ price = self.safe_number(order, 'price')
771
+ avgPrice = self.safe_number(order, 'avgPrice')
772
+ if Precise.string_eq(priceString, '0') and (avgPrice is not None):
773
+ price = avgPrice
774
+ amount = self.safe_string(order, 'quantity')
775
+ side = self.safe_string_lower(order, 'side')
776
+ type = self.safe_string_lower(order, 'type')
777
+ filled = self.safe_number(order, 'totalExecutedQuantity')
778
+ totalExecQuantity = self.safe_string(order, 'totalExecutedQuantity')
779
+ remaining = amount
780
+ if Precise.string_ge(amount, totalExecQuantity):
781
+ remaining = Precise.string_sub(remaining, totalExecQuantity)
782
+ rawStatus = self.safe_string(order, 'status')
783
+ status = self.parse_order_status(rawStatus)
784
+ trades = None
785
+ clientOrderId = self.safe_string(order, 'clientOrderId')
786
+ triggerPrice = self.safe_number(order, 'triggerPrice')
787
+ return self.safe_order({
788
+ 'info': order,
789
+ 'symbol': symbol,
790
+ 'id': orderId,
791
+ 'clientOrderId': clientOrderId,
792
+ 'timestamp': timestamp,
793
+ 'datetime': self.iso8601(timestamp),
794
+ 'lastTradeTimestamp': timestamp,
795
+ 'type': type,
796
+ 'timeInForce': None,
797
+ 'postOnly': None,
798
+ 'side': side,
799
+ 'price': price,
800
+ 'stopPrice': triggerPrice,
801
+ 'triggerPrice': triggerPrice,
802
+ 'amount': amount,
803
+ 'cost': None,
804
+ 'average': None,
805
+ 'filled': filled,
806
+ 'remaining': remaining,
807
+ 'status': status,
808
+ 'fee': fee,
809
+ 'trades': trades,
810
+ })
811
+
812
+ def handle_order_update(self, client: Client, message):
813
+ #
814
+ # {
815
+ # "topic": "executionreport",
816
+ # "ts": 1657515556799,
817
+ # "data": {
818
+ # "symbol": "PERP_BTC_USDT",
819
+ # "clientOrderId": 0,
820
+ # "orderId": 52952826,
821
+ # "type": "LIMIT",
822
+ # "side": "SELL",
823
+ # "quantity": 0.01,
824
+ # "price": 22000,
825
+ # "tradeId": 0,
826
+ # "executedPrice": 0,
827
+ # "executedQuantity": 0,
828
+ # "fee": 0,
829
+ # "feeAsset": "USDT",
830
+ # "totalExecutedQuantity": 0,
831
+ # "status": "NEW",
832
+ # "reason": '',
833
+ # "orderTag": "default",
834
+ # "totalFee": 0,
835
+ # "visible": 0.01,
836
+ # "timestamp": 1657515556799,
837
+ # "maker": False
838
+ # }
839
+ # }
840
+ #
841
+ topic = self.safe_string(message, 'topic')
842
+ data = self.safe_value(message, 'data')
843
+ if isinstance(data, list):
844
+ # algoexecutionreport
845
+ for i in range(0, len(data)):
846
+ order = data[i]
847
+ tradeId = self.omit_zero(self.safe_string(data, 'tradeId'))
848
+ if tradeId is not None:
849
+ self.handle_my_trade(client, order)
850
+ self.handle_order(client, order, topic)
851
+ else:
852
+ # executionreport
853
+ tradeId = self.omit_zero(self.safe_string(data, 'tradeId'))
854
+ if tradeId is not None:
855
+ self.handle_my_trade(client, data)
856
+ self.handle_order(client, data, topic)
857
+
858
+ def handle_order(self, client: Client, message, topic):
859
+ parsed = self.parse_ws_order(message)
860
+ symbol = self.safe_string(parsed, 'symbol')
861
+ orderId = self.safe_string(parsed, 'id')
862
+ if symbol is not None:
863
+ if self.orders is None:
864
+ limit = self.safe_integer(self.options, 'ordersLimit', 1000)
865
+ self.orders = ArrayCacheBySymbolById(limit)
866
+ cachedOrders = self.orders
867
+ orders = self.safe_dict(cachedOrders.hashmap, symbol, {})
868
+ order = self.safe_dict(orders, orderId)
869
+ if order is not None:
870
+ fee = self.safe_value(order, 'fee')
871
+ if fee is not None:
872
+ parsed['fee'] = fee
873
+ fees = self.safe_list(order, 'fees')
874
+ if fees is not None:
875
+ parsed['fees'] = fees
876
+ parsed['trades'] = self.safe_list(order, 'trades')
877
+ parsed['timestamp'] = self.safe_integer(order, 'timestamp')
878
+ parsed['datetime'] = self.safe_string(order, 'datetime')
879
+ cachedOrders.append(parsed)
880
+ client.resolve(self.orders, topic)
881
+ messageHashSymbol = topic + ':' + symbol
882
+ client.resolve(self.orders, messageHashSymbol)
883
+
884
+ def handle_my_trade(self, client: Client, message):
885
+ #
886
+ # {
887
+ # symbol: 'PERP_XRP_USDC',
888
+ # clientOrderId: '',
889
+ # orderId: 1167632251,
890
+ # type: 'MARKET',
891
+ # side: 'BUY',
892
+ # quantity: 20,
893
+ # price: 0,
894
+ # tradeId: '1715179456664012',
895
+ # executedPrice: 0.5276,
896
+ # executedQuantity: 20,
897
+ # fee: 0.006332,
898
+ # feeAsset: 'USDC',
899
+ # totalExecutedQuantity: 20,
900
+ # avgPrice: 0.5276,
901
+ # averageExecutedPrice: 0.5276,
902
+ # status: 'FILLED',
903
+ # reason: '',
904
+ # totalFee: 0.006332,
905
+ # visible: 0,
906
+ # visibleQuantity: 0,
907
+ # timestamp: 1715179456660,
908
+ # orderTag: 'CCXT',
909
+ # createdTime: 1715179456656,
910
+ # maker: False
911
+ # }
912
+ #
913
+ messageHash = 'myTrades'
914
+ marketId = self.safe_string(message, 'symbol')
915
+ market = self.safe_market(marketId)
916
+ symbol = market['symbol']
917
+ trade = self.parse_ws_trade(message, market)
918
+ trades = self.myTrades
919
+ if trades is None:
920
+ limit = self.safe_integer(self.options, 'tradesLimit', 1000)
921
+ trades = ArrayCacheBySymbolById(limit)
922
+ self.myTrades = trades
923
+ trades.append(trade)
924
+ client.resolve(trades, messageHash)
925
+ symbolSpecificMessageHash = messageHash + ':' + symbol
926
+ client.resolve(trades, symbolSpecificMessageHash)
927
+
928
+ async def watch_positions(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}) -> List[Position]:
929
+ """
930
+
931
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/position-push
932
+
933
+ watch all open positions
934
+ :param str[] [symbols]: list of unified market symbols
935
+ @param since timestamp in ms of the earliest position to fetch
936
+ @param limit the maximum number of positions to fetch
937
+ :param dict params: extra parameters specific to the exchange API endpoint
938
+ :returns dict[]: a list of `position structure <https://docs.ccxt.com/en/latest/manual.html#position-structure>`
939
+ """
940
+ await self.load_markets()
941
+ messageHashes = []
942
+ symbols = self.market_symbols(symbols)
943
+ if not self.is_empty(symbols):
944
+ for i in range(0, len(symbols)):
945
+ symbol = symbols[i]
946
+ messageHashes.append('positions::' + symbol)
947
+ else:
948
+ messageHashes.append('positions')
949
+ url = self.urls['api']['ws']['private'] + '/' + self.accountId
950
+ client = self.client(url)
951
+ self.set_positions_cache(client, symbols)
952
+ fetchPositionsSnapshot = self.handle_option('watchPositions', 'fetchPositionsSnapshot', True)
953
+ awaitPositionsSnapshot = self.handle_option('watchPositions', 'awaitPositionsSnapshot', True)
954
+ if fetchPositionsSnapshot and awaitPositionsSnapshot and self.positions is None:
955
+ snapshot = await client.future('fetchPositionsSnapshot')
956
+ return self.filter_by_symbols_since_limit(snapshot, symbols, since, limit, True)
957
+ request: dict = {
958
+ 'event': 'subscribe',
959
+ 'topic': 'position',
960
+ }
961
+ newPositions = await self.watch_private_multiple(messageHashes, request, params)
962
+ if self.newUpdates:
963
+ return newPositions
964
+ return self.filter_by_symbols_since_limit(self.positions, symbols, since, limit, True)
965
+
966
+ def set_positions_cache(self, client: Client, type, symbols: Strings = None):
967
+ fetchPositionsSnapshot = self.handle_option('watchPositions', 'fetchPositionsSnapshot', False)
968
+ if fetchPositionsSnapshot:
969
+ messageHash = 'fetchPositionsSnapshot'
970
+ if not (messageHash in client.futures):
971
+ client.future(messageHash)
972
+ self.spawn(self.load_positions_snapshot, client, messageHash)
973
+ else:
974
+ self.positions = ArrayCacheBySymbolBySide()
975
+
976
+ async def load_positions_snapshot(self, client, messageHash):
977
+ positions = await self.fetch_positions()
978
+ self.positions = ArrayCacheBySymbolBySide()
979
+ cache = self.positions
980
+ for i in range(0, len(positions)):
981
+ position = positions[i]
982
+ contracts = self.safe_string(position, 'contracts', '0')
983
+ if Precise.string_gt(contracts, '0'):
984
+ cache.append(position)
985
+ # don't remove the future from the .futures cache
986
+ future = client.futures[messageHash]
987
+ future.resolve(cache)
988
+ client.resolve(cache, 'positions')
989
+
990
+ def handle_positions(self, client, message):
991
+ #
992
+ # {
993
+ # "topic":"position",
994
+ # "ts":1705292345255,
995
+ # "data":{
996
+ # "positions":[
997
+ # {
998
+ # "symbol":"PERP_ETH_USDC",
999
+ # "positionQty":3.1408,
1000
+ # "costPosition":5706.51952,
1001
+ # "lastSumUnitaryFunding":0.804,
1002
+ # "sumUnitaryFundingVersion":0,
1003
+ # "pendingLongQty":0.0,
1004
+ # "pendingShortQty":-1.0,
1005
+ # "settlePrice":1816.9,
1006
+ # "averageOpenPrice":1804.51490427,
1007
+ # "unsettledPnl":-2.79856,
1008
+ # "pnl24H":-338.90179488,
1009
+ # "fee24H":4.242423,
1010
+ # "markPrice":1816.2,
1011
+ # "estLiqPrice":0.0,
1012
+ # "version":179967,
1013
+ # "imrwithOrders":0.1,
1014
+ # "mmrwithOrders":0.05,
1015
+ # "mmr":0.05,
1016
+ # "imr":0.1,
1017
+ # "timestamp":1685154032762
1018
+ # }
1019
+ # ]
1020
+ # }
1021
+ # }
1022
+ #
1023
+ data = self.safe_dict(message, 'data', {})
1024
+ rawPositions = self.safe_list(data, 'positions', [])
1025
+ if self.positions is None:
1026
+ self.positions = ArrayCacheBySymbolBySide()
1027
+ cache = self.positions
1028
+ newPositions = []
1029
+ for i in range(0, len(rawPositions)):
1030
+ rawPosition = rawPositions[i]
1031
+ marketId = self.safe_string(rawPosition, 'symbol')
1032
+ market = self.safe_market(marketId)
1033
+ position = self.parse_ws_position(rawPosition, market)
1034
+ newPositions.append(position)
1035
+ cache.append(position)
1036
+ messageHash = 'positions::' + market['symbol']
1037
+ client.resolve(position, messageHash)
1038
+ client.resolve(newPositions, 'positions')
1039
+
1040
+ def parse_ws_position(self, position, market=None):
1041
+ #
1042
+ # {
1043
+ # "symbol":"PERP_ETH_USDC",
1044
+ # "positionQty":3.1408,
1045
+ # "costPosition":5706.51952,
1046
+ # "lastSumUnitaryFunding":0.804,
1047
+ # "sumUnitaryFundingVersion":0,
1048
+ # "pendingLongQty":0.0,
1049
+ # "pendingShortQty":-1.0,
1050
+ # "settlePrice":1816.9,
1051
+ # "averageOpenPrice":1804.51490427,
1052
+ # "unsettledPnl":-2.79856,
1053
+ # "pnl24H":-338.90179488,
1054
+ # "fee24H":4.242423,
1055
+ # "markPrice":1816.2,
1056
+ # "estLiqPrice":0.0,
1057
+ # "version":179967,
1058
+ # "imrwithOrders":0.1,
1059
+ # "mmrwithOrders":0.05,
1060
+ # "mmr":0.05,
1061
+ # "imr":0.1,
1062
+ # "timestamp":1685154032762
1063
+ # }
1064
+ #
1065
+ contract = self.safe_string(position, 'symbol')
1066
+ market = self.safe_market(contract, market)
1067
+ size = self.safe_string(position, 'positionQty')
1068
+ side: Str = None
1069
+ if Precise.string_gt(size, '0'):
1070
+ side = 'long'
1071
+ else:
1072
+ side = 'short'
1073
+ contractSize = self.safe_string(market, 'contractSize')
1074
+ markPrice = self.safe_string(position, 'markPrice')
1075
+ timestamp = self.safe_integer(position, 'timestamp')
1076
+ entryPrice = self.safe_string(position, 'averageOpenPrice')
1077
+ unrealisedPnl = self.safe_string(position, 'unsettledPnl')
1078
+ size = Precise.string_abs(size)
1079
+ notional = Precise.string_mul(size, markPrice)
1080
+ return self.safe_position({
1081
+ 'info': position,
1082
+ 'id': None,
1083
+ 'symbol': self.safe_string(market, 'symbol'),
1084
+ 'timestamp': timestamp,
1085
+ 'datetime': self.iso8601(timestamp),
1086
+ 'lastUpdateTimestamp': None,
1087
+ 'initialMargin': None,
1088
+ 'initialMarginPercentage': None,
1089
+ 'maintenanceMargin': None,
1090
+ 'maintenanceMarginPercentage': None,
1091
+ 'entryPrice': self.parse_number(entryPrice),
1092
+ 'notional': self.parse_number(notional),
1093
+ 'leverage': None,
1094
+ 'unrealizedPnl': self.parse_number(unrealisedPnl),
1095
+ 'contracts': self.parse_number(size),
1096
+ 'contractSize': self.parse_number(contractSize),
1097
+ 'marginRatio': None,
1098
+ 'liquidationPrice': self.safe_number(position, 'estLiqPrice'),
1099
+ 'markPrice': self.parse_number(markPrice),
1100
+ 'lastPrice': None,
1101
+ 'collateral': None,
1102
+ 'marginMode': 'cross',
1103
+ 'marginType': None,
1104
+ 'side': side,
1105
+ 'percentage': None,
1106
+ 'hedged': None,
1107
+ 'stopLossPrice': None,
1108
+ 'takeProfitPrice': None,
1109
+ })
1110
+
1111
+ async def watch_balance(self, params={}) -> Balances:
1112
+ """
1113
+ watch balance and get the amount of funds available for trading or funds locked in orders
1114
+
1115
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/balance
1116
+
1117
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1118
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1119
+ """
1120
+ await self.load_markets()
1121
+ topic = 'balance'
1122
+ messageHash = topic
1123
+ request: dict = {
1124
+ 'event': 'subscribe',
1125
+ 'topic': topic,
1126
+ }
1127
+ message = self.extend(request, params)
1128
+ return await self.watch_private(messageHash, message)
1129
+
1130
+ def handle_balance(self, client, message):
1131
+ #
1132
+ # {
1133
+ # "topic":"balance",
1134
+ # "ts":1651836695254,
1135
+ # "data":{
1136
+ # "balances":{
1137
+ # "USDC":{
1138
+ # "holding":5555815.47398272,
1139
+ # "frozen":0,
1140
+ # "interest":0,
1141
+ # "pendingShortQty":0,
1142
+ # "pendingExposure":0,
1143
+ # "pendingLongQty":0,
1144
+ # "pendingLongExposure":0,
1145
+ # "version":894,
1146
+ # "staked":51370692,
1147
+ # "unbonding":0,
1148
+ # "vault":0,
1149
+ # "averageOpenPrice":0.00000574,
1150
+ # "pnl24H":0,
1151
+ # "fee24H":0.01914,
1152
+ # "markPrice":0.31885
1153
+ # }
1154
+ # }
1155
+ # }
1156
+ # }
1157
+ #
1158
+ data = self.safe_dict(message, 'data', {})
1159
+ balances = self.safe_dict(data, 'balances', {})
1160
+ keys = list(balances.keys())
1161
+ ts = self.safe_integer(message, 'ts')
1162
+ self.balance['info'] = data
1163
+ self.balance['timestamp'] = ts
1164
+ self.balance['datetime'] = self.iso8601(ts)
1165
+ for i in range(0, len(keys)):
1166
+ key = keys[i]
1167
+ value = balances[key]
1168
+ code = self.safe_currency_code(key)
1169
+ account = self.balance[code] if (code in self.balance) else self.account()
1170
+ total = self.safe_string(value, 'holding')
1171
+ used = self.safe_string(value, 'frozen')
1172
+ account['total'] = total
1173
+ account['used'] = used
1174
+ account['free'] = Precise.string_sub(total, used)
1175
+ self.balance[code] = account
1176
+ self.balance = self.safe_balance(self.balance)
1177
+ client.resolve(self.balance, 'balance')
1178
+
1179
+ def handle_error_message(self, client: Client, message):
1180
+ #
1181
+ # {"id":"1","event":"subscribe","success":false,"ts":1710780997216,"errorMsg":"Auth is needed."}
1182
+ #
1183
+ if not ('success' in message):
1184
+ return False
1185
+ success = self.safe_bool(message, 'success')
1186
+ if success:
1187
+ return False
1188
+ errorMessage = self.safe_string(message, 'errorMsg')
1189
+ try:
1190
+ if errorMessage is not None:
1191
+ feedback = self.id + ' ' + self.json(message)
1192
+ self.throw_exactly_matched_exception(self.exceptions['exact'], errorMessage, feedback)
1193
+ return False
1194
+ except Exception as error:
1195
+ if isinstance(error, AuthenticationError):
1196
+ messageHash = 'authenticated'
1197
+ client.reject(error, messageHash)
1198
+ if messageHash in client.subscriptions:
1199
+ del client.subscriptions[messageHash]
1200
+ else:
1201
+ client.reject(error)
1202
+ return True
1203
+
1204
+ def handle_message(self, client: Client, message):
1205
+ if self.handle_error_message(client, message):
1206
+ return
1207
+ methods: dict = {
1208
+ 'ping': self.handle_ping,
1209
+ 'pong': self.handle_pong,
1210
+ 'subscribe': self.handle_subscribe,
1211
+ 'orderbook': self.handle_order_book,
1212
+ 'ticker': self.handle_ticker,
1213
+ 'tickers': self.handle_tickers,
1214
+ 'kline': self.handle_ohlcv,
1215
+ 'trade': self.handle_trade,
1216
+ 'auth': self.handle_auth,
1217
+ 'executionreport': self.handle_order_update,
1218
+ 'algoexecutionreport': self.handle_order_update,
1219
+ 'position': self.handle_positions,
1220
+ 'balance': self.handle_balance,
1221
+ 'bbos': self.handle_bid_ask,
1222
+ }
1223
+ event = self.safe_string(message, 'event')
1224
+ method = self.safe_value(methods, event)
1225
+ if method is not None:
1226
+ method(client, message)
1227
+ return
1228
+ topic = self.safe_string(message, 'topic')
1229
+ if topic is not None:
1230
+ method = self.safe_value(methods, topic)
1231
+ if method is not None:
1232
+ method(client, message)
1233
+ return
1234
+ splitTopic = topic.split('@')
1235
+ splitLength = len(splitTopic)
1236
+ if splitLength == 2:
1237
+ name = self.safe_string(splitTopic, 1)
1238
+ method = self.safe_value(methods, name)
1239
+ if method is not None:
1240
+ method(client, message)
1241
+ return
1242
+ splitName = name.split('_')
1243
+ splitNameLength = len(splitTopic)
1244
+ if splitNameLength == 2:
1245
+ method = self.safe_value(methods, self.safe_string(splitName, 0))
1246
+ if method is not None:
1247
+ method(client, message)
1248
+
1249
+ def ping(self, client: Client):
1250
+ return {'event': 'ping'}
1251
+
1252
+ def handle_ping(self, client: Client, message):
1253
+ return {'event': 'pong'}
1254
+
1255
+ def handle_pong(self, client: Client, message):
1256
+ #
1257
+ # {event: "pong", ts: 1614667590000}
1258
+ #
1259
+ client.lastPong = self.milliseconds()
1260
+ return message
1261
+
1262
+ def handle_subscribe(self, client: Client, message):
1263
+ #
1264
+ # {
1265
+ # "id": "666888",
1266
+ # "event": "subscribe",
1267
+ # "success": True,
1268
+ # "ts": 1657117712212
1269
+ # }
1270
+ #
1271
+ return message