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/oxfun.py ADDED
@@ -0,0 +1,1054 @@
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
+ import hashlib
9
+ from ccxt.base.types import Balances, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
10
+ from ccxt.async_support.base.ws.client import Client
11
+ from typing import List
12
+ from ccxt.base.errors import AuthenticationError
13
+ from ccxt.base.errors import ArgumentsRequired
14
+ from ccxt.base.errors import BadRequest
15
+
16
+
17
+ class oxfun(ccxt.async_support.oxfun):
18
+
19
+ def describe(self):
20
+ return self.deep_extend(super(oxfun, self).describe(), {
21
+ 'has': {
22
+ 'ws': True,
23
+ 'watchTrades': True,
24
+ 'watchTradesForSymbols': True,
25
+ 'watchOrderBook': True,
26
+ 'watchOrderBookForSymbols': True,
27
+ 'watchOHLCV': True,
28
+ 'watchOHLCVForSymbols': True,
29
+ 'watchOrders': True,
30
+ 'watchMyTrades': False,
31
+ 'watchTicker': True,
32
+ 'watchTickers': True,
33
+ 'watchBidsAsks': True,
34
+ 'watchBalance': True,
35
+ 'createOrderWs': True,
36
+ 'editOrderWs': True,
37
+ 'cancelOrderWs': True,
38
+ 'cancelOrdersWs': True,
39
+ },
40
+ 'urls': {
41
+ 'api': {
42
+ 'ws': 'wss://api.ox.fun/v2/websocket',
43
+ 'test': 'wss://stgapi.ox.fun/v2/websocket',
44
+ },
45
+ },
46
+ 'options': {
47
+ 'timeframes': {
48
+ '1m': '60s',
49
+ '3m': '180s',
50
+ '5m': '300s',
51
+ '15m': '900s',
52
+ '30m': '1800s',
53
+ '1h': '3600s',
54
+ '2h': '7200s',
55
+ '4h': '14400s',
56
+ '6h': '21600s',
57
+ '12h': '43200s',
58
+ '1d': '86400s',
59
+ },
60
+ 'watchOrderBook': {
61
+ 'channel': 'depth', # depth, depthL5, depthL10, depthL25
62
+ },
63
+ },
64
+ 'streaming': {
65
+ 'ping': self.ping,
66
+ 'keepAlive': 50000,
67
+ },
68
+ })
69
+
70
+ async def subscribe_multiple(self, messageHashes, argsArray, params={}):
71
+ url = self.urls['api']['ws']
72
+ request: dict = {
73
+ 'op': 'subscribe',
74
+ 'args': argsArray,
75
+ }
76
+ return await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
77
+
78
+ async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
79
+ """
80
+ watches information on multiple trades made in a market
81
+
82
+ https://docs.ox.fun/?json#trade
83
+
84
+ :param str symbol: unified market symbol of the market trades were made in
85
+ :param int [since]: the earliest time in ms to fetch orders for
86
+ :param int [limit]: the maximum number of trade structures to retrieve
87
+ :param dict [params]: extra parameters specific to the exchange API endpoint
88
+ :param int|str [params.tag]: If given it will be echoed in the reply and the max size of tag is 32
89
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
90
+ """
91
+ return await self.watch_trades_for_symbols([symbol], since, limit, params)
92
+
93
+ async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
94
+ """
95
+ get the list of most recent trades for a particular symbol
96
+
97
+ https://docs.ox.fun/?json#trade
98
+
99
+ :param str[] symbols:
100
+ :param int [since]: timestamp in ms of the earliest trade to fetch
101
+ :param int [limit]: the maximum amount of trades to fetch
102
+ :param dict [params]: extra parameters specific to the exchange API endpoint
103
+ :param int|str [params.tag]: If given it will be echoed in the reply and the max size of tag is 32
104
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
105
+ """
106
+ await self.load_markets()
107
+ symbols = self.market_symbols(symbols, None, False)
108
+ args = []
109
+ messageHashes = []
110
+ for i in range(0, len(symbols)):
111
+ symbol = symbols[i]
112
+ messageHash = 'trades' + ':' + symbol
113
+ messageHashes.append(messageHash)
114
+ marketId = self.market_id(symbol)
115
+ arg = 'trade:' + marketId
116
+ args.append(arg)
117
+ trades = await self.subscribe_multiple(messageHashes, args, params)
118
+ if self.newUpdates:
119
+ first = self.safe_dict(trades, 0, {})
120
+ tradeSymbol = self.safe_string(first, 'symbol')
121
+ limit = trades.getLimit(tradeSymbol, limit)
122
+ return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
123
+
124
+ def handle_trades(self, client: Client, message):
125
+ #
126
+ # {
127
+ # table: 'trade',
128
+ # data: [
129
+ # {
130
+ # side: 'SELL',
131
+ # quantity: '0.074',
132
+ # matchType: 'TAKER',
133
+ # price: '3079.5',
134
+ # marketCode: 'ETH-USD-SWAP-LIN',
135
+ # tradeId: '400017157974517783',
136
+ # timestamp: '1716124156643'
137
+ # }
138
+ # ]
139
+ # }
140
+ #
141
+ data = self.safe_list(message, 'data', [])
142
+ for i in range(0, len(data)):
143
+ trade = self.safe_dict(data, i, {})
144
+ parsedTrade = self.parse_ws_trade(trade)
145
+ symbol = self.safe_string(parsedTrade, 'symbol')
146
+ messageHash = 'trades:' + symbol
147
+ if not (symbol in self.trades):
148
+ tradesLimit = self.safe_integer(self.options, 'tradesLimit', 1000)
149
+ self.trades[symbol] = ArrayCache(tradesLimit)
150
+ stored = self.trades[symbol]
151
+ stored.append(parsedTrade)
152
+ client.resolve(stored, messageHash)
153
+
154
+ def parse_ws_trade(self, trade, market=None) -> Trade:
155
+ #
156
+ # {
157
+ # side: 'SELL',
158
+ # quantity: '0.074',
159
+ # matchType: 'TAKER',
160
+ # price: '3079.5',
161
+ # marketCode: 'ETH-USD-SWAP-LIN',
162
+ # tradeId: '400017157974517783',
163
+ # timestamp: '1716124156643'
164
+ # }
165
+ #
166
+ marketId = self.safe_string(trade, 'marketCode')
167
+ market = self.safe_market(marketId, market)
168
+ timestamp = self.safe_integer(trade, 'timestamp')
169
+ return self.safe_trade({
170
+ 'info': trade,
171
+ 'timestamp': timestamp,
172
+ 'datetime': self.iso8601(timestamp),
173
+ 'symbol': market['symbol'],
174
+ 'id': self.safe_string(trade, 'tradeId'),
175
+ 'order': None,
176
+ 'type': None,
177
+ 'takerOrMaker': self.safe_string_lower(trade, 'matchType'),
178
+ 'side': self.safe_string_lower(trade, 'side'),
179
+ 'price': self.safe_number(trade, 'price'),
180
+ 'amount': self.safe_number(trade, 'quantity'),
181
+ 'cost': None,
182
+ 'fee': None,
183
+ })
184
+
185
+ async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
186
+ """
187
+ watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
188
+
189
+ https://docs.ox.fun/?json#candles
190
+
191
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
192
+ :param str timeframe: the length of time each candle represents
193
+ :param int [since]: timestamp in ms of the earliest candle to fetch
194
+ :param int [limit]: the maximum amount of candles to fetch
195
+ :param dict [params]: extra parameters specific to the exchange API endpoint
196
+ :param int|str [params.tag]: If given it will be echoed in the reply and the max size of tag is 32
197
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
198
+ """
199
+ await self.load_markets()
200
+ market = self.market(symbol)
201
+ timeframes = self.safe_dict(self.options, 'timeframes', {})
202
+ interval = self.safe_string(timeframes, timeframe, timeframe)
203
+ args = 'candles' + interval + ':' + market['id']
204
+ messageHash = 'ohlcv:' + symbol + ':' + timeframe
205
+ url = self.urls['api']['ws']
206
+ request: dict = {
207
+ 'op': 'subscribe',
208
+ 'args': [args],
209
+ }
210
+ ohlcvs = await self.watch(url, messageHash, self.extend(request, params), messageHash)
211
+ if self.newUpdates:
212
+ limit = ohlcvs.getLimit(symbol, limit)
213
+ return self.filter_by_since_limit(ohlcvs, since, limit, 0, True)
214
+
215
+ async def watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], since: Int = None, limit: Int = None, params={}):
216
+ """
217
+ watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
218
+
219
+ https://docs.ox.fun/?json#candles
220
+
221
+ :param str[][] symbolsAndTimeframes: array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
222
+ :param int [since]: timestamp in ms of the earliest candle to fetch
223
+ :param int [limit]: the maximum amount of candles to fetch
224
+ :param dict [params]: extra parameters specific to the exchange API endpoint
225
+ :param int|str [params.tag]: If given it will be echoed in the reply and the max size of tag is 32
226
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
227
+ """
228
+ symbolsLength = len(symbolsAndTimeframes)
229
+ if symbolsLength == 0 or not isinstance(symbolsAndTimeframes[0], list):
230
+ raise ArgumentsRequired(self.id + " watchOHLCVForSymbols() requires a an array of symbols and timeframes, like [['BTC/USDT:OX', '1m'], ['OX/USDT', '5m']]")
231
+ await self.load_markets()
232
+ args = []
233
+ messageHashes = []
234
+ timeframes = self.safe_dict(self.options, 'timeframes', {})
235
+ for i in range(0, len(symbolsAndTimeframes)):
236
+ symbolAndTimeframe = symbolsAndTimeframes[i]
237
+ sym = symbolAndTimeframe[0]
238
+ tf = symbolAndTimeframe[1]
239
+ marketId = self.market_id(sym)
240
+ interval = self.safe_string(timeframes, tf, tf)
241
+ arg = 'candles' + interval + ':' + marketId
242
+ args.append(arg)
243
+ messageHash = 'multi:ohlcv:' + sym + ':' + tf
244
+ messageHashes.append(messageHash)
245
+ symbol, timeframe, candles = await self.subscribe_multiple(messageHashes, args, params)
246
+ if self.newUpdates:
247
+ limit = candles.getLimit(symbol, limit)
248
+ filtered = self.filter_by_since_limit(candles, since, limit, 0, True)
249
+ return self.create_ohlcv_object(symbol, timeframe, filtered)
250
+
251
+ def handle_ohlcv(self, client: Client, message):
252
+ #
253
+ # {
254
+ # "table": "candles60s",
255
+ # "data": [
256
+ # {
257
+ # "marketCode": "BTC-USD-SWAP-LIN",
258
+ # "candle": [
259
+ # "1594313762698", #timestamp
260
+ # "9633.1", #open
261
+ # "9693.9", #high
262
+ # "9238.1", #low
263
+ # "9630.2", #close
264
+ # "45247", #volume in OX
265
+ # "5.3" #volume in Contracts
266
+ # ]
267
+ # }
268
+ # ]
269
+ # }
270
+ #
271
+ table = self.safe_string(message, 'table')
272
+ parts = table.split('candles')
273
+ timeframeId = self.safe_string(parts, 1, '')
274
+ timeframe = self.find_timeframe(timeframeId)
275
+ messageData = self.safe_list(message, 'data', [])
276
+ data = self.safe_dict(messageData, 0, {})
277
+ marketId = self.safe_string(data, 'marketCode')
278
+ market = self.safe_market(marketId)
279
+ symbol = self.safe_symbol(marketId, market)
280
+ if not (symbol in self.ohlcvs):
281
+ self.ohlcvs[symbol] = {}
282
+ if not (timeframe in self.ohlcvs[symbol]):
283
+ limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
284
+ self.ohlcvs[symbol][timeframe] = ArrayCacheByTimestamp(limit)
285
+ candle = self.safe_list(data, 'candle', [])
286
+ parsed = self.parse_ws_ohlcv(candle, market)
287
+ stored = self.ohlcvs[symbol][timeframe]
288
+ stored.append(parsed)
289
+ messageHash = 'ohlcv:' + symbol + ':' + timeframe
290
+ client.resolve(stored, messageHash)
291
+ # for multiOHLCV we need special object, to other "multi"
292
+ # methods, because OHLCV response item does not contain symbol
293
+ # or timeframe, thus otherwise it would be unrecognizable
294
+ messageHashForMulti = 'multi:' + messageHash
295
+ client.resolve([symbol, timeframe, stored], messageHashForMulti)
296
+
297
+ def parse_ws_ohlcv(self, ohlcv, market: Market = None) -> list:
298
+ #
299
+ # [
300
+ # "1594313762698", #timestamp
301
+ # "9633.1", #open
302
+ # "9693.9", #high
303
+ # "9238.1", #low
304
+ # "9630.2", #close
305
+ # "45247", #volume in OX
306
+ # "5.3" #volume in Contracts
307
+ # ]
308
+ #
309
+ return [
310
+ self.safe_integer(ohlcv, 0),
311
+ self.safe_number(ohlcv, 1),
312
+ self.safe_number(ohlcv, 2),
313
+ self.safe_number(ohlcv, 3),
314
+ self.safe_number(ohlcv, 4),
315
+ self.safe_number(ohlcv, 6),
316
+ ]
317
+
318
+ async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
319
+ """
320
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
321
+
322
+ https://docs.ox.fun/?json#fixed-size-order-book
323
+ https://docs.ox.fun/?json#full-order-book
324
+
325
+ :param str symbol: unified symbol of the market to fetch the order book for
326
+ :param int [limit]: the maximum amount of order book entries to return
327
+ :param dict [params]: extra parameters specific to the exchange API endpoint
328
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
329
+ """
330
+ return await self.watch_order_book_for_symbols([symbol], limit, params)
331
+
332
+ async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
333
+ """
334
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
335
+
336
+ https://docs.ox.fun/?json#fixed-size-order-book
337
+ https://docs.ox.fun/?json#full-order-book
338
+
339
+ :param str[] symbols: unified array of symbols
340
+ :param int [limit]: the maximum amount of order book entries to return
341
+ :param dict [params]: extra parameters specific to the exchange API endpoint
342
+ :param int|str [params.tag]: If given it will be echoed in the reply and the max size of tag is 32
343
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
344
+ """
345
+ await self.load_markets()
346
+ symbols = self.market_symbols(symbols)
347
+ channel = 'depth'
348
+ options = self.safe_dict(self.options, 'watchOrderBook', {})
349
+ defaultChannel = self.safe_string(options, 'channel')
350
+ if defaultChannel is not None:
351
+ channel = defaultChannel
352
+ elif limit is not None:
353
+ if limit <= 5:
354
+ channel = 'depthL5'
355
+ elif limit <= 10:
356
+ channel = 'depthL10'
357
+ elif limit <= 25:
358
+ channel = 'depthL25'
359
+ args = []
360
+ messageHashes = []
361
+ for i in range(0, len(symbols)):
362
+ symbol = symbols[i]
363
+ messageHash = 'orderbook:' + symbol
364
+ messageHashes.append(messageHash)
365
+ marketId = self.market_id(symbol)
366
+ arg = channel + ':' + marketId
367
+ args.append(arg)
368
+ orderbook = await self.subscribe_multiple(messageHashes, args, params)
369
+ return orderbook.limit()
370
+
371
+ def handle_order_book(self, client: Client, message):
372
+ #
373
+ # {
374
+ # "table": "depth",
375
+ # "data": {
376
+ # "seqNum": "100170478917895032",
377
+ # "asks": [
378
+ # [0.01, 100500],
379
+ # ...
380
+ # ],
381
+ # "bids": [
382
+ # [69.69696, 69],
383
+ # ...
384
+ # ],
385
+ # "checksum": 261021645,
386
+ # "marketCode": "OX-USDT",
387
+ # "timestamp": 1716204786184
388
+ # },
389
+ # "action": "partial"
390
+ # }
391
+ #
392
+ data = self.safe_dict(message, 'data', {})
393
+ marketId = self.safe_string(data, 'marketCode')
394
+ symbol = self.safe_symbol(marketId)
395
+ timestamp = self.safe_integer(data, 'timestamp')
396
+ messageHash = 'orderbook:' + symbol
397
+ if not (symbol in self.orderbooks):
398
+ self.orderbooks[symbol] = self.order_book({})
399
+ orderbook = self.orderbooks[symbol]
400
+ snapshot = self.parse_order_book(data, symbol, timestamp, 'asks', 'bids')
401
+ orderbook.reset(snapshot)
402
+ orderbook['nonce'] = self.safe_integer(data, 'seqNum')
403
+ self.orderbooks[symbol] = orderbook
404
+ client.resolve(orderbook, messageHash)
405
+
406
+ async def watch_ticker(self, symbol: str, params={}) -> Ticker:
407
+ """
408
+
409
+ https://docs.ox.fun/?json#ticker
410
+
411
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
412
+ :param str symbol: unified symbol of the market to fetch the ticker for
413
+ :param dict [params]: extra parameters specific to the exchange API endpoint
414
+ :param int|str [params.tag]: If given it will be echoed in the reply and the max size of tag is 32
415
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
416
+ """
417
+ ticker = await self.watch_tickers([symbol], params)
418
+ return self.safe_value(ticker, symbol)
419
+
420
+ async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
421
+ """
422
+
423
+ https://docs.ox.fun/?json#ticker
424
+
425
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
426
+ :param str[] [symbols]: unified symbol of the market to fetch the ticker for
427
+ :param dict [params]: extra parameters specific to the exchange API endpoint
428
+ :param int|str [params.tag]: If given it will be echoed in the reply and the max size of tag is 32
429
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
430
+ """
431
+ await self.load_markets()
432
+ allSymbols = (symbols is None)
433
+ sym = symbols
434
+ args = []
435
+ if allSymbols:
436
+ sym = self.symbols
437
+ args.append('ticker:all')
438
+ messageHashes = []
439
+ for i in range(0, len(sym)):
440
+ symbol = sym[i]
441
+ messageHash = 'tickers' + ':' + symbol
442
+ messageHashes.append(messageHash)
443
+ marketId = self.market_id(symbol)
444
+ if not allSymbols:
445
+ args.append('ticker:' + marketId)
446
+ newTicker = await self.subscribe_multiple(messageHashes, args, params)
447
+ if self.newUpdates:
448
+ result = {}
449
+ result[newTicker['symbol']] = newTicker
450
+ return result
451
+ return self.filter_by_array(self.tickers, 'symbol', symbols)
452
+
453
+ def handle_ticker(self, client: Client, message):
454
+ #
455
+ # {
456
+ # "table": "ticker",
457
+ # "data": [
458
+ # {
459
+ # "last": "3088.6",
460
+ # "open24h": "3087.2",
461
+ # "high24h": "3142.0",
462
+ # "low24h": "3053.9",
463
+ # "volume24h": "450512672.1800",
464
+ # "currencyVolume24h": "1458.579",
465
+ # "openInterest": "3786.801",
466
+ # "marketCode": "ETH-USD-SWAP-LIN",
467
+ # "timestamp": "1716212747050",
468
+ # "lastQty": "0.813",
469
+ # "markPrice": "3088.6",
470
+ # "lastMarkPrice": "3088.6",
471
+ # "indexPrice": "3086.5"
472
+ # },
473
+ # ...
474
+ # ]
475
+ # }
476
+ #
477
+ data = self.safe_list(message, 'data', [])
478
+ for i in range(0, len(data)):
479
+ rawTicker = self.safe_dict(data, i, {})
480
+ ticker = self.parse_ticker(rawTicker)
481
+ symbol = ticker['symbol']
482
+ messageHash = 'tickers:' + symbol
483
+ self.tickers[symbol] = ticker
484
+ client.resolve(ticker, messageHash)
485
+
486
+ async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
487
+ """
488
+
489
+ https://docs.ox.fun/?json#best-bid-ask
490
+
491
+ watches best bid & ask for symbols
492
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
493
+ :param dict [params]: extra parameters specific to the exchange API endpoint
494
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
495
+ """
496
+ await self.load_markets()
497
+ symbols = self.market_symbols(symbols, None, False)
498
+ messageHashes = []
499
+ args = []
500
+ for i in range(0, len(symbols)):
501
+ market = self.market(symbols[i])
502
+ args.append('bestBidAsk:' + market['id'])
503
+ messageHashes.append('bidask:' + market['symbol'])
504
+ newTickers = await self.subscribe_multiple(messageHashes, args, params)
505
+ if self.newUpdates:
506
+ tickers: dict = {}
507
+ tickers[newTickers['symbol']] = newTickers
508
+ return tickers
509
+ return self.filter_by_array(self.bidsasks, 'symbol', symbols)
510
+
511
+ def handle_bid_ask(self, client: Client, message):
512
+ #
513
+ # {
514
+ # "table": "bestBidAsk",
515
+ # "data": {
516
+ # "ask": [
517
+ # 19045.0,
518
+ # 1.0
519
+ # ],
520
+ # "checksum": 3790706311,
521
+ # "marketCode": "BTC-USD-SWAP-LIN",
522
+ # "bid": [
523
+ # 19015.0,
524
+ # 1.0
525
+ # ],
526
+ # "timestamp": "1665456882928"
527
+ # }
528
+ # }
529
+ #
530
+ data = self.safe_dict(message, 'data', {})
531
+ parsedTicker = self.parse_ws_bid_ask(data)
532
+ symbol = parsedTicker['symbol']
533
+ self.bidsasks[symbol] = parsedTicker
534
+ messageHash = 'bidask:' + symbol
535
+ client.resolve(parsedTicker, messageHash)
536
+
537
+ def parse_ws_bid_ask(self, ticker, market=None):
538
+ marketId = self.safe_string(ticker, 'marketCode')
539
+ market = self.safe_market(marketId, market)
540
+ symbol = self.safe_string(market, 'symbol')
541
+ timestamp = self.safe_integer(ticker, 'timestamp')
542
+ ask = self.safe_list(ticker, 'ask', [])
543
+ bid = self.safe_list(ticker, 'bid', [])
544
+ return self.safe_ticker({
545
+ 'symbol': symbol,
546
+ 'timestamp': timestamp,
547
+ 'datetime': self.iso8601(timestamp),
548
+ 'ask': self.safe_number(ask, 0),
549
+ 'askVolume': self.safe_number(ask, 1),
550
+ 'bid': self.safe_number(bid, 0),
551
+ 'bidVolume': self.safe_number(bid, 1),
552
+ 'info': ticker,
553
+ }, market)
554
+
555
+ async def watch_balance(self, params={}) -> Balances:
556
+ """
557
+
558
+ https://docs.ox.fun/?json#balance-channel
559
+
560
+ watch balance and get the amount of funds available for trading or funds locked in orders
561
+ :param dict [params]: extra parameters specific to the exchange API endpoint
562
+ :param int|str [params.tag]: If given it will be echoed in the reply and the max size of tag is 32
563
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
564
+ """
565
+ await self.load_markets()
566
+ self.authenticate()
567
+ args = 'balance:all'
568
+ messageHash = 'balance'
569
+ url = self.urls['api']['ws']
570
+ request: dict = {
571
+ 'op': 'subscribe',
572
+ 'args': [args],
573
+ }
574
+ return await self.watch(url, messageHash, self.extend(request, params), messageHash)
575
+
576
+ def handle_balance(self, client, message):
577
+ #
578
+ # {
579
+ # "table": "balance",
580
+ # "accountId": "106464",
581
+ # "timestamp": "1716549132780",
582
+ # "tradeType": "PORTFOLIO",
583
+ # "data": [
584
+ # {
585
+ # "instrumentId": "xOX",
586
+ # "total": "23.375591220",
587
+ # "available": "23.375591220",
588
+ # "reserved": "0",
589
+ # "quantityLastUpdated": "1716509744262",
590
+ # "locked": "0"
591
+ # },
592
+ # ...
593
+ # ]
594
+ # }
595
+ #
596
+ balances = self.safe_list(message, 'data')
597
+ timestamp = self.safe_integer(message, 'timestamp')
598
+ self.balance['info'] = message
599
+ self.balance['timestamp'] = timestamp
600
+ self.balance['datetime'] = self.iso8601(timestamp)
601
+ for i in range(0, len(balances)):
602
+ balance = self.safe_dict(balances, i, {})
603
+ currencyId = self.safe_string(balance, 'instrumentId')
604
+ code = self.safe_currency_code(currencyId)
605
+ if not (code in self.balance):
606
+ self.balance[code] = self.account()
607
+ account = self.balance[code]
608
+ account['total'] = self.safe_string(balance, 'total')
609
+ account['used'] = self.safe_string(balance, 'reserved')
610
+ account['free'] = self.safe_string(balance, 'available')
611
+ self.balance[code] = account
612
+ self.balance = self.safe_balance(self.balance)
613
+ client.resolve(self.balance, 'balance')
614
+
615
+ async def watch_positions(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}) -> List[Position]:
616
+ """
617
+
618
+ https://docs.ox.fun/?json#position-channel
619
+
620
+ watch all open positions
621
+ :param str[]|None symbols: list of unified market symbols
622
+ @param since
623
+ @param limit
624
+ :param dict params: extra parameters specific to the exchange API endpoint
625
+ :param int|str [params.tag]: If given it will be echoed in the reply and the max size of tag is 32
626
+ :returns dict[]: a list of `position structure <https://docs.ccxt.com/en/latest/manual.html#position-structure>`
627
+ """
628
+ await self.load_markets()
629
+ await self.authenticate()
630
+ allSymbols = (symbols is None)
631
+ sym = symbols
632
+ args = []
633
+ if allSymbols:
634
+ sym = self.symbols
635
+ args.append('position:all')
636
+ messageHashes = []
637
+ for i in range(0, len(sym)):
638
+ symbol = sym[i]
639
+ messageHash = 'positions' + ':' + symbol
640
+ messageHashes.append(messageHash)
641
+ marketId = self.market_id(symbol)
642
+ if not allSymbols:
643
+ args.append('position:' + marketId)
644
+ newPositions = await self.subscribe_multiple(messageHashes, args, params)
645
+ if self.newUpdates:
646
+ return newPositions
647
+ return self.filter_by_symbols_since_limit(self.positions, symbols, since, limit, True)
648
+
649
+ def handle_positions(self, client: Client, message):
650
+ #
651
+ # {
652
+ # "table": "position",
653
+ # "accountId": "106464",
654
+ # "timestamp": "1716550771582",
655
+ # "data": [
656
+ # {
657
+ # "instrumentId": "ETH-USD-SWAP-LIN",
658
+ # "quantity": "0.01",
659
+ # "lastUpdated": "1716550757299",
660
+ # "contractValCurrency": "ETH",
661
+ # "entryPrice": "3709.6",
662
+ # "positionPnl": "-5.000",
663
+ # "estLiquidationPrice": "743.4",
664
+ # "margin": "0",
665
+ # "leverage": "0"
666
+ # }
667
+ # ]
668
+ # }
669
+ #
670
+ if self.positions is None:
671
+ self.positions = ArrayCacheBySymbolBySide()
672
+ cache = self.positions
673
+ data = self.safe_list(message, 'data', [])
674
+ for i in range(0, len(data)):
675
+ rawPosition = self.safe_dict(data, i, {})
676
+ position = self.parse_ws_position(rawPosition)
677
+ symbol = position['symbol']
678
+ messageHash = 'positions:' + symbol
679
+ cache.append(position)
680
+ client.resolve(position, messageHash)
681
+
682
+ def parse_ws_position(self, position, market: Market = None):
683
+ #
684
+ # {
685
+ # "instrumentId": "ETH-USD-SWAP-LIN",
686
+ # "quantity": "0.01",
687
+ # "lastUpdated": "1716550757299",
688
+ # "contractValCurrency": "ETH",
689
+ # "entryPrice": "3709.6",
690
+ # "positionPnl": "-5.000",
691
+ # "estLiquidationPrice": "743.4",
692
+ # "margin": "0", # Currently always reports 0
693
+ # "leverage": "0" # Currently always reports 0
694
+ # }
695
+ #
696
+ marketId = self.safe_string(position, 'instrumentId')
697
+ market = self.safe_market(marketId, market)
698
+ return self.safe_position({
699
+ 'info': position,
700
+ 'id': None,
701
+ 'symbol': market['symbol'],
702
+ 'notional': None,
703
+ 'marginMode': 'cross',
704
+ 'liquidationPrice': self.safe_number(position, 'estLiquidationPrice'),
705
+ 'entryPrice': self.safe_number(position, 'entryPrice'),
706
+ 'unrealizedPnl': self.safe_number(position, 'positionPnl'),
707
+ 'realizedPnl': None,
708
+ 'percentage': None,
709
+ 'contracts': self.safe_number(position, 'quantity'),
710
+ 'contractSize': None,
711
+ 'markPrice': None,
712
+ 'lastPrice': None,
713
+ 'side': None,
714
+ 'hedged': None,
715
+ 'timestamp': None,
716
+ 'datetime': None,
717
+ 'lastUpdateTimestamp': self.safe_integer(position, 'lastUpdated'),
718
+ 'maintenanceMargin': None,
719
+ 'maintenanceMarginPercentage': None,
720
+ 'collateral': None,
721
+ 'initialMargin': None,
722
+ 'initialMarginPercentage': None,
723
+ 'leverage': None,
724
+ 'marginRatio': None,
725
+ 'stopLossPrice': None,
726
+ 'takeProfitPrice': None,
727
+ })
728
+
729
+ async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
730
+ """
731
+ watches information on multiple orders made by the user
732
+
733
+ https://docs.ox.fun/?json#order-channel
734
+
735
+ :param str symbol: unified market symbol of the market orders were made in
736
+ :param int [since]: the earliest time in ms to fetch orders for
737
+ :param int [limit]: the maximum number of order structures to retrieve
738
+ :param dict [params]: extra parameters specific to the exchange API endpoint
739
+ :param int|str [params.tag]: If given it will be echoed in the reply and the max size of tag is 32
740
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
741
+ """
742
+ await self.load_markets()
743
+ await self.authenticate()
744
+ messageHash = 'orders'
745
+ args = 'order:'
746
+ market = self.safe_market(symbol)
747
+ if symbol is None:
748
+ args += 'all'
749
+ else:
750
+ messageHash += ':' + symbol
751
+ args += ':' + market['id']
752
+ request: dict = {
753
+ 'op': 'subscribe',
754
+ 'args': [
755
+ args,
756
+ ],
757
+ }
758
+ url = self.urls['api']['ws']
759
+ orders = await self.watch(url, messageHash, request, messageHash)
760
+ if self.newUpdates:
761
+ limit = orders.getLimit(symbol, limit)
762
+ return self.filter_by_symbol_since_limit(orders, symbol, since, limit, True)
763
+
764
+ def handle_orders(self, client: Client, message):
765
+ #
766
+ # {
767
+ # "table": "order",
768
+ # "data": [
769
+ # {
770
+ # "accountId": "106464",
771
+ # "clientOrderId": "1716713676233",
772
+ # "orderId": "1000116921319",
773
+ # "price": "1000.0",
774
+ # "quantity": "0.01",
775
+ # "amount": "0.0",
776
+ # "side": "BUY",
777
+ # "status": "OPEN",
778
+ # "marketCode": "ETH-USD-SWAP-LIN",
779
+ # "timeInForce": "MAKER_ONLY",
780
+ # "timestamp": "1716713677834",
781
+ # "remainQuantity": "0.01",
782
+ # "limitPrice": "1000.0",
783
+ # "notice": "OrderOpened",
784
+ # "orderType": "LIMIT",
785
+ # "isTriggered": "false",
786
+ # "displayQuantity": "0.01"
787
+ # }
788
+ # ]
789
+ # }
790
+ #
791
+ data = self.safe_list(message, 'data', [])
792
+ messageHash = 'orders'
793
+ if self.orders is None:
794
+ limit = self.safe_integer(self.options, 'ordersLimit', 1000)
795
+ self.orders = ArrayCacheBySymbolById(limit)
796
+ orders = self.orders
797
+ for i in range(0, len(data)):
798
+ order = self.safe_dict(data, i, {})
799
+ parsedOrder = self.parse_order(order)
800
+ orders.append(parsedOrder)
801
+ messageHash += ':' + parsedOrder['symbol']
802
+ client.resolve(self.orders, messageHash)
803
+
804
+ async def create_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> Order:
805
+ """
806
+
807
+ https://docs.ox.fun/?json#order-commands
808
+
809
+ create a trade order
810
+ :param str symbol: unified symbol of the market to create an order in
811
+ :param str type: 'market', 'limit', 'STOP_LIMIT' or 'STOP_MARKET'
812
+ :param str side: 'buy' or 'sell'
813
+ :param float amount: how much of currency you want to trade in units of base currency
814
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
815
+ :param dict [params]: extra parameters specific to the exchange API endpoint
816
+ :param int [params.clientOrderId]: a unique id for the order
817
+ :param int [params.timestamp]: in milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected.
818
+ :param int [params.recvWindow]: in milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used.
819
+ :param float [params.cost]: the quote quantity that can be used alternative for the amount for market buy orders
820
+ :param float [params.triggerPrice]: The price at which a trigger order is triggered at
821
+ :param float [params.limitPrice]: Limit price for the STOP_LIMIT order
822
+ :param bool [params.postOnly]: if True, the order will only be posted if it will be a maker order
823
+ :param str [params.timeInForce]: GTC(default), IOC, FOK, PO, MAKER_ONLY or MAKER_ONLY_REPRICE(reprices order to the best maker only price if the specified price were to lead to a taker trade)
824
+ :param str [params.selfTradePreventionMode]: NONE, EXPIRE_MAKER, EXPIRE_TAKER or EXPIRE_BOTH for more info check here {@link https://docs.ox.fun/?json#self-trade-prevention-modes}
825
+ :param str [params.displayQuantity]: for an iceberg order, pass both quantity and displayQuantity fields in the order request
826
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
827
+ """
828
+ await self.load_markets()
829
+ await self.authenticate()
830
+ messageHash = str(self.nonce())
831
+ request: dict = {
832
+ 'op': 'placeorder',
833
+ 'tag': messageHash,
834
+ }
835
+ params = self.omit(params, 'tag')
836
+ orderRequest: dict = self.create_order_request(symbol, type, side, amount, price, params)
837
+ timestamp = self.safe_integer(orderRequest, 'timestamp')
838
+ if timestamp is None:
839
+ orderRequest['timestamp'] = self.milliseconds()
840
+ request['data'] = orderRequest
841
+ url = self.urls['api']['ws']
842
+ return await self.watch(url, messageHash, request, messageHash)
843
+
844
+ async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}) -> Order:
845
+ """
846
+ edit a trade order
847
+
848
+ https://docs.ox.fun/?json#modify-order
849
+
850
+ :param str id: order id
851
+ :param str symbol: unified symbol of the market to create an order in
852
+ :param str type: 'market' or 'limit'
853
+ :param str side: 'buy' or 'sell'
854
+ :param float amount: how much of the currency you want to trade in units of the base currency
855
+ :param float|None [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
856
+ :param dict [params]: extra parameters specific to the exchange API endpoint
857
+ :param int [params.timestamp]: in milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected.
858
+ :param int [params.recvWindow]: in milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used.
859
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
860
+ """
861
+ await self.load_markets()
862
+ await self.authenticate()
863
+ messageHash = str(self.nonce())
864
+ request: dict = {
865
+ 'op': 'modifyorder',
866
+ 'tag': messageHash,
867
+ }
868
+ params = self.omit(params, 'tag')
869
+ orderRequest: dict = self.create_order_request(symbol, type, side, amount, price, params)
870
+ orderRequest = self.extend(orderRequest, {'orderId': id})
871
+ timestamp = self.safe_integer(orderRequest, 'timestamp')
872
+ if timestamp is None:
873
+ orderRequest['timestamp'] = self.milliseconds()
874
+ request['data'] = orderRequest
875
+ url = self.urls['api']['ws']
876
+ return await self.watch(url, messageHash, request, messageHash)
877
+
878
+ def handle_place_orders(self, client: Client, message):
879
+ #
880
+ # {
881
+ # "event": "placeorder",
882
+ # "submitted": True,
883
+ # "tag": "1716934577",
884
+ # "timestamp": "1716932973899",
885
+ # "data": {
886
+ # "marketCode": "ETH-USD-SWAP-LIN",
887
+ # "side": "BUY",
888
+ # "orderType": "LIMIT",
889
+ # "quantity": "0.010",
890
+ # "timeInForce": "GTC",
891
+ # "price": "400.0",
892
+ # "limitPrice": "400.0",
893
+ # "orderId": "1000117429736",
894
+ # "source": 13
895
+ # }
896
+ # }
897
+ #
898
+ #
899
+ # Failure response format
900
+ # {
901
+ # "event": "placeorder",
902
+ # "submitted": False,
903
+ # "message": "JSON data format is invalid",
904
+ # "code": "20009",
905
+ # "timestamp": "1716932877381"
906
+ # }
907
+ #
908
+ messageHash = self.safe_string(message, 'tag')
909
+ submitted = self.safe_bool(message, 'submitted')
910
+ # filter out partial errors
911
+ if not submitted:
912
+ method = self.safe_string(message, 'event')
913
+ stringMsg = self.json(message)
914
+ code = self.safe_integer(message, 'code')
915
+ self.handle_errors(code, None, client.url, method, None, stringMsg, message, None, None)
916
+ data = self.safe_value(message, 'data', {})
917
+ order = self.parse_order(data)
918
+ client.resolve(order, messageHash)
919
+
920
+ async def cancel_order_ws(self, id: str, symbol: Str = None, params={}) -> Order:
921
+ """
922
+
923
+ https://docs.ox.fun/?json#cancel-order
924
+
925
+ cancels an open order
926
+ :param str id: order id
927
+ :param str symbol: unified market symbol, default is None
928
+ :param dict [params]: extra parameters specific to the exchange API endpoint
929
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
930
+ """
931
+ if symbol is None:
932
+ raise ArgumentsRequired(self.id + ' cancelOrderWs() requires a symbol argument')
933
+ await self.load_markets()
934
+ await self.authenticate()
935
+ messageHash = str(self.nonce())
936
+ data: dict = {
937
+ 'marketCode': self.market_id(symbol),
938
+ 'orderId': id,
939
+ }
940
+ request: dict = {
941
+ 'op': 'cancelorder',
942
+ 'tag': messageHash,
943
+ 'data': data,
944
+ }
945
+ url = self.urls['api']['ws']
946
+ return await self.watch(url, messageHash, request, messageHash)
947
+
948
+ async def cancel_orders_ws(self, ids: List[str], symbol: Str = None, params={}):
949
+ """
950
+
951
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-ws-mass-cancel-order
952
+
953
+ cancel multiple orders
954
+ :param str[] ids: order ids
955
+ :param str symbol: unified market symbol, default is None
956
+ :param dict [params]: extra parameters specific to the exchange API endpoint
957
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
958
+ """
959
+ idsLength: number = len(ids)
960
+ if idsLength > 20:
961
+ raise BadRequest(self.id + ' cancelOrdersWs() accepts up to 20 ids at a time')
962
+ if symbol is None:
963
+ raise ArgumentsRequired(self.id + ' cancelOrdersWs() requires a symbol argument')
964
+ await self.load_markets()
965
+ await self.authenticate()
966
+ messageHash = str(self.nonce())
967
+ marketId = self.market_id(symbol)
968
+ dataArray = []
969
+ for i in range(0, idsLength):
970
+ data: dict = {
971
+ 'instId': marketId,
972
+ 'ordId': ids[i],
973
+ }
974
+ dataArray.append(data)
975
+ request: dict = {
976
+ 'op': 'cancelorders',
977
+ 'tag': messageHash,
978
+ 'dataArray': dataArray,
979
+ }
980
+ url = self.urls['api']['ws']
981
+ return await self.watch(url, messageHash, self.deep_extend(request, params), messageHash)
982
+
983
+ async def authenticate(self, params={}):
984
+ url = self.urls['api']['ws']
985
+ client = self.client(url)
986
+ messageHash = 'authenticated'
987
+ future = client.future(messageHash)
988
+ authenticated = self.safe_dict(client.subscriptions, messageHash)
989
+ if authenticated is None:
990
+ self.check_required_credentials()
991
+ timestamp = self.milliseconds()
992
+ payload = str(timestamp) + 'GET/auth/self/verify'
993
+ signature = self.hmac(self.encode(payload), self.encode(self.secret), hashlib.sha256, 'base64')
994
+ request: dict = {
995
+ 'op': 'login',
996
+ 'data': {
997
+ 'apiKey': self.apiKey,
998
+ 'timestamp': timestamp,
999
+ 'signature': signature,
1000
+ },
1001
+ }
1002
+ message = self.extend(request, params)
1003
+ self.watch(url, messageHash, message, messageHash)
1004
+ return await future
1005
+
1006
+ def handle_authentication_message(self, client: Client, message):
1007
+ authenticated = self.safe_bool(message, 'success', False)
1008
+ messageHash = 'authenticated'
1009
+ if authenticated:
1010
+ # we resolve the future here permanently so authentication only happens once
1011
+ future = self.safe_dict(client.futures, messageHash)
1012
+ future.resolve(True)
1013
+ else:
1014
+ error = AuthenticationError(self.json(message))
1015
+ client.reject(error, messageHash)
1016
+ if messageHash in client.subscriptions:
1017
+ del client.subscriptions[messageHash]
1018
+
1019
+ def ping(self, client: Client):
1020
+ return 'ping'
1021
+
1022
+ def handle_pong(self, client: Client, message):
1023
+ client.lastPong = self.milliseconds()
1024
+ return message
1025
+
1026
+ def handle_message(self, client: Client, message):
1027
+ if message == 'pong':
1028
+ self.handle_pong(client, message)
1029
+ return
1030
+ table = self.safe_string(message, 'table')
1031
+ data = self.safe_list(message, 'data', [])
1032
+ event = self.safe_string(message, 'event')
1033
+ if (table is not None) and (data is not None):
1034
+ if table == 'trade':
1035
+ self.handle_trades(client, message)
1036
+ if table == 'ticker':
1037
+ self.handle_ticker(client, message)
1038
+ if table.find('candles') > -1:
1039
+ self.handle_ohlcv(client, message)
1040
+ if table.find('depth') > -1:
1041
+ self.handle_order_book(client, message)
1042
+ if table.find('balance') > -1:
1043
+ self.handle_balance(client, message)
1044
+ if table.find('position') > -1:
1045
+ self.handle_positions(client, message)
1046
+ if table.find('order') > -1:
1047
+ self.handle_orders(client, message)
1048
+ if table == 'bestBidAsk':
1049
+ self.handle_bid_ask(client, message)
1050
+ else:
1051
+ if event == 'login':
1052
+ self.handle_authentication_message(client, message)
1053
+ if (event == 'placeorder') or (event == 'modifyorder') or (event == 'cancelorder'):
1054
+ self.handle_place_orders(client, message)