ccxt-ir 4.3.46.0.1__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.
- ccxt/__init__.py +358 -0
- ccxt/abantether.py +316 -0
- ccxt/abstract/__init__.py +0 -0
- ccxt/abstract/abantether.py +5 -0
- ccxt/abstract/ace.py +15 -0
- ccxt/abstract/afratether.py +6 -0
- ccxt/abstract/alpaca.py +70 -0
- ccxt/abstract/arzinja.py +5 -0
- ccxt/abstract/arzplus.py +7 -0
- ccxt/abstract/ascendex.py +77 -0
- ccxt/abstract/bequant.py +115 -0
- ccxt/abstract/bigone.py +45 -0
- ccxt/abstract/binance.py +712 -0
- ccxt/abstract/binancecoinm.py +712 -0
- ccxt/abstract/binanceus.py +764 -0
- ccxt/abstract/binanceusdm.py +712 -0
- ccxt/abstract/bingx.py +113 -0
- ccxt/abstract/bit2c.py +27 -0
- ccxt/abstract/bitbank.py +27 -0
- ccxt/abstract/bitbay.py +53 -0
- ccxt/abstract/bitbns.py +40 -0
- ccxt/abstract/bitcoincom.py +115 -0
- ccxt/abstract/bitfinex.py +69 -0
- ccxt/abstract/bitfinex2.py +139 -0
- ccxt/abstract/bitflyer.py +38 -0
- ccxt/abstract/bitget.py +508 -0
- ccxt/abstract/bithumb.py +32 -0
- ccxt/abstract/bitimen.py +7 -0
- ccxt/abstract/bitir.py +7 -0
- ccxt/abstract/bitmart.py +99 -0
- ccxt/abstract/bitmex.py +97 -0
- ccxt/abstract/bitopro.py +29 -0
- ccxt/abstract/bitpanda.py +35 -0
- ccxt/abstract/bitpin.py +7 -0
- ccxt/abstract/bitrue.py +72 -0
- ccxt/abstract/bitso.py +43 -0
- ccxt/abstract/bitstamp.py +258 -0
- ccxt/abstract/bitteam.py +29 -0
- ccxt/abstract/bitvavo.py +27 -0
- ccxt/abstract/bl3p.py +19 -0
- ccxt/abstract/blockchaincom.py +28 -0
- ccxt/abstract/blofin.py +37 -0
- ccxt/abstract/btcalpha.py +18 -0
- ccxt/abstract/btcbox.py +13 -0
- ccxt/abstract/btcmarkets.py +39 -0
- ccxt/abstract/btcturk.py +20 -0
- ccxt/abstract/bybit.py +298 -0
- ccxt/abstract/cex.py +33 -0
- ccxt/abstract/coinbase.py +94 -0
- ccxt/abstract/coinbaseadvanced.py +94 -0
- ccxt/abstract/coinbaseexchange.py +67 -0
- ccxt/abstract/coinbaseinternational.py +39 -0
- ccxt/abstract/coincatch.py +94 -0
- ccxt/abstract/coincheck.py +33 -0
- ccxt/abstract/coinex.py +237 -0
- ccxt/abstract/coinlist.py +54 -0
- ccxt/abstract/coinmate.py +62 -0
- ccxt/abstract/coinmetro.py +34 -0
- ccxt/abstract/coinone.py +67 -0
- ccxt/abstract/coinsph.py +54 -0
- ccxt/abstract/coinspot.py +28 -0
- ccxt/abstract/cryptocom.py +107 -0
- ccxt/abstract/currencycom.py +68 -0
- ccxt/abstract/delta.py +50 -0
- ccxt/abstract/deribit.py +125 -0
- ccxt/abstract/digifinex.py +91 -0
- ccxt/abstract/eterex.py +5 -0
- ccxt/abstract/excoino.py +7 -0
- ccxt/abstract/exir.py +8 -0
- ccxt/abstract/exmo.py +55 -0
- ccxt/abstract/exnovin.py +6 -0
- ccxt/abstract/farhadexchange.py +5 -0
- ccxt/abstract/fmfwio.py +115 -0
- ccxt/abstract/gate.py +265 -0
- ccxt/abstract/gateio.py +265 -0
- ccxt/abstract/gemini.py +58 -0
- ccxt/abstract/hashkey.py +67 -0
- ccxt/abstract/hitbtc.py +115 -0
- ccxt/abstract/hitbtc3.py +115 -0
- ccxt/abstract/hitobit.py +8 -0
- ccxt/abstract/hollaex.py +33 -0
- ccxt/abstract/htx.py +548 -0
- ccxt/abstract/huobi.py +548 -0
- ccxt/abstract/huobijp.py +114 -0
- ccxt/abstract/hyperliquid.py +6 -0
- ccxt/abstract/idex.py +26 -0
- ccxt/abstract/independentreserve.py +37 -0
- ccxt/abstract/indodax.py +26 -0
- ccxt/abstract/jibitex.py +7 -0
- ccxt/abstract/kraken.py +57 -0
- ccxt/abstract/krakenfutures.py +38 -0
- ccxt/abstract/kucoin.py +214 -0
- ccxt/abstract/kucoinfutures.py +233 -0
- ccxt/abstract/kuna.py +182 -0
- ccxt/abstract/latoken.py +56 -0
- ccxt/abstract/lbank.py +61 -0
- ccxt/abstract/luno.py +37 -0
- ccxt/abstract/lykke.py +29 -0
- ccxt/abstract/mercado.py +25 -0
- ccxt/abstract/mexc.py +178 -0
- ccxt/abstract/ndax.py +97 -0
- ccxt/abstract/nobitex.py +7 -0
- ccxt/abstract/novadax.py +29 -0
- ccxt/abstract/oceanex.py +22 -0
- ccxt/abstract/okcoin.py +74 -0
- ccxt/abstract/okexchange.py +8 -0
- ccxt/abstract/okx.py +324 -0
- ccxt/abstract/ompfinex.py +7 -0
- ccxt/abstract/onetrading.py +35 -0
- ccxt/abstract/oxfun.py +34 -0
- ccxt/abstract/p2b.py +22 -0
- ccxt/abstract/paradex.py +40 -0
- ccxt/abstract/paymium.py +28 -0
- ccxt/abstract/phemex.py +115 -0
- ccxt/abstract/poloniex.py +69 -0
- ccxt/abstract/poloniexfutures.py +48 -0
- ccxt/abstract/probit.py +23 -0
- ccxt/abstract/ramzinex.py +7 -0
- ccxt/abstract/sarmayex.py +5 -0
- ccxt/abstract/sarrafex.py +7 -0
- ccxt/abstract/tabdeal.py +7 -0
- ccxt/abstract/tetherland.py +5 -0
- ccxt/abstract/timex.py +62 -0
- ccxt/abstract/tokocrypto.py +37 -0
- ccxt/abstract/tradeogre.py +16 -0
- ccxt/abstract/twox.py +5 -0
- ccxt/abstract/ubitex.py +7 -0
- ccxt/abstract/upbit.py +38 -0
- ccxt/abstract/vertex.py +19 -0
- ccxt/abstract/wallex.py +8 -0
- ccxt/abstract/wavesexchange.py +154 -0
- ccxt/abstract/wazirx.py +30 -0
- ccxt/abstract/whitebit.py +98 -0
- ccxt/abstract/woo.py +83 -0
- ccxt/abstract/woofipro.py +119 -0
- ccxt/abstract/xt.py +152 -0
- ccxt/abstract/yobit.py +16 -0
- ccxt/abstract/zaif.py +38 -0
- ccxt/abstract/zonda.py +53 -0
- ccxt/ace.py +1012 -0
- ccxt/afratether.py +293 -0
- ccxt/alpaca.py +1083 -0
- ccxt/arzinja.py +285 -0
- ccxt/arzplus.py +412 -0
- ccxt/ascendex.py +3330 -0
- ccxt/async_support/__init__.py +337 -0
- ccxt/async_support/abantether.py +316 -0
- ccxt/async_support/ace.py +1012 -0
- ccxt/async_support/afratether.py +293 -0
- ccxt/async_support/alpaca.py +1083 -0
- ccxt/async_support/arzinja.py +285 -0
- ccxt/async_support/arzplus.py +412 -0
- ccxt/async_support/ascendex.py +3330 -0
- ccxt/async_support/base/__init__.py +1 -0
- ccxt/async_support/base/exchange.py +1966 -0
- ccxt/async_support/base/throttler.py +50 -0
- ccxt/async_support/base/ws/__init__.py +38 -0
- ccxt/async_support/base/ws/aiohttp_client.py +125 -0
- ccxt/async_support/base/ws/cache.py +212 -0
- ccxt/async_support/base/ws/client.py +193 -0
- ccxt/async_support/base/ws/fast_client.py +96 -0
- ccxt/async_support/base/ws/functions.py +59 -0
- ccxt/async_support/base/ws/future.py +58 -0
- ccxt/async_support/base/ws/order_book.py +78 -0
- ccxt/async_support/base/ws/order_book_side.py +174 -0
- ccxt/async_support/bequant.py +33 -0
- ccxt/async_support/bigone.py +2113 -0
- ccxt/async_support/binance.py +12234 -0
- ccxt/async_support/binancecoinm.py +45 -0
- ccxt/async_support/binanceus.py +211 -0
- ccxt/async_support/binanceusdm.py +58 -0
- ccxt/async_support/bingx.py +4325 -0
- ccxt/async_support/bit2c.py +866 -0
- ccxt/async_support/bitbank.py +1001 -0
- ccxt/async_support/bitbay.py +17 -0
- ccxt/async_support/bitbns.py +1154 -0
- ccxt/async_support/bitcoincom.py +17 -0
- ccxt/async_support/bitfinex.py +1617 -0
- ccxt/async_support/bitfinex2.py +3552 -0
- ccxt/async_support/bitflyer.py +995 -0
- ccxt/async_support/bitget.py +8273 -0
- ccxt/async_support/bithumb.py +1061 -0
- ccxt/async_support/bitimen.py +401 -0
- ccxt/async_support/bitir.py +490 -0
- ccxt/async_support/bitmart.py +4415 -0
- ccxt/async_support/bitmex.py +2756 -0
- ccxt/async_support/bitopro.py +1630 -0
- ccxt/async_support/bitpanda.py +16 -0
- ccxt/async_support/bitpin.py +454 -0
- ccxt/async_support/bitrue.py +3027 -0
- ccxt/async_support/bitso.py +1670 -0
- ccxt/async_support/bitstamp.py +2203 -0
- ccxt/async_support/bitteam.py +2239 -0
- ccxt/async_support/bitvavo.py +1968 -0
- ccxt/async_support/bl3p.py +485 -0
- ccxt/async_support/blockchaincom.py +1104 -0
- ccxt/async_support/blofin.py +2066 -0
- ccxt/async_support/btcalpha.py +891 -0
- ccxt/async_support/btcbox.py +544 -0
- ccxt/async_support/btcmarkets.py +1221 -0
- ccxt/async_support/btcturk.py +911 -0
- ccxt/async_support/bybit.py +8159 -0
- ccxt/async_support/cex.py +1605 -0
- ccxt/async_support/coinbase.py +4475 -0
- ccxt/async_support/coinbaseadvanced.py +17 -0
- ccxt/async_support/coinbaseexchange.py +1734 -0
- ccxt/async_support/coinbaseinternational.py +1899 -0
- ccxt/async_support/coincatch.py +5069 -0
- ccxt/async_support/coincheck.py +815 -0
- ccxt/async_support/coinex.py +5526 -0
- ccxt/async_support/coinlist.py +2243 -0
- ccxt/async_support/coinmate.py +1067 -0
- ccxt/async_support/coinmetro.py +1797 -0
- ccxt/async_support/coinone.py +1127 -0
- ccxt/async_support/coinsph.py +1850 -0
- ccxt/async_support/coinspot.py +534 -0
- ccxt/async_support/cryptocom.py +2822 -0
- ccxt/async_support/currencycom.py +1950 -0
- ccxt/async_support/delta.py +3376 -0
- ccxt/async_support/deribit.py +3437 -0
- ccxt/async_support/digifinex.py +3960 -0
- ccxt/async_support/eterex.py +286 -0
- ccxt/async_support/excoino.py +399 -0
- ccxt/async_support/exir.py +375 -0
- ccxt/async_support/exmo.py +2462 -0
- ccxt/async_support/exnovin.py +360 -0
- ccxt/async_support/farhadexchange.py +266 -0
- ccxt/async_support/fmfwio.py +34 -0
- ccxt/async_support/gate.py +6976 -0
- ccxt/async_support/gateio.py +16 -0
- ccxt/async_support/gemini.py +1825 -0
- ccxt/async_support/hashkey.py +4150 -0
- ccxt/async_support/hitbtc.py +3423 -0
- ccxt/async_support/hitbtc3.py +16 -0
- ccxt/async_support/hitobit.py +391 -0
- ccxt/async_support/hollaex.py +1813 -0
- ccxt/async_support/htx.py +8506 -0
- ccxt/async_support/huobi.py +16 -0
- ccxt/async_support/huobijp.py +1801 -0
- ccxt/async_support/hyperliquid.py +2431 -0
- ccxt/async_support/idex.py +1766 -0
- ccxt/async_support/independentreserve.py +784 -0
- ccxt/async_support/indodax.py +1247 -0
- ccxt/async_support/jibitex.py +395 -0
- ccxt/async_support/kraken.py +2894 -0
- ccxt/async_support/krakenfutures.py +2601 -0
- ccxt/async_support/kucoin.py +4602 -0
- ccxt/async_support/kucoinfutures.py +2698 -0
- ccxt/async_support/kuna.py +1841 -0
- ccxt/async_support/latoken.py +1664 -0
- ccxt/async_support/lbank.py +2683 -0
- ccxt/async_support/luno.py +1067 -0
- ccxt/async_support/lykke.py +1270 -0
- ccxt/async_support/mercado.py +842 -0
- ccxt/async_support/mexc.py +5369 -0
- ccxt/async_support/ndax.py +2354 -0
- ccxt/async_support/nobitex.py +419 -0
- ccxt/async_support/novadax.py +1484 -0
- ccxt/async_support/oceanex.py +903 -0
- ccxt/async_support/okcoin.py +2936 -0
- ccxt/async_support/okexchange.py +349 -0
- ccxt/async_support/okx.py +7827 -0
- ccxt/async_support/ompfinex.py +472 -0
- ccxt/async_support/onetrading.py +1911 -0
- ccxt/async_support/oxfun.py +2773 -0
- ccxt/async_support/p2b.py +1194 -0
- ccxt/async_support/paradex.py +2015 -0
- ccxt/async_support/paymium.py +564 -0
- ccxt/async_support/phemex.py +4473 -0
- ccxt/async_support/poloniex.py +2232 -0
- ccxt/async_support/poloniexfutures.py +1717 -0
- ccxt/async_support/probit.py +1734 -0
- ccxt/async_support/ramzinex.py +476 -0
- ccxt/async_support/sarmayex.py +357 -0
- ccxt/async_support/sarrafex.py +478 -0
- ccxt/async_support/tabdeal.py +364 -0
- ccxt/async_support/tetherland.py +349 -0
- ccxt/async_support/timex.py +1593 -0
- ccxt/async_support/tokocrypto.py +2405 -0
- ccxt/async_support/tradeogre.py +608 -0
- ccxt/async_support/twox.py +326 -0
- ccxt/async_support/ubitex.py +409 -0
- ccxt/async_support/upbit.py +1833 -0
- ccxt/async_support/vertex.py +2922 -0
- ccxt/async_support/wallex.py +445 -0
- ccxt/async_support/wavesexchange.py +2473 -0
- ccxt/async_support/wazirx.py +1224 -0
- ccxt/async_support/whitebit.py +2469 -0
- ccxt/async_support/woo.py +3114 -0
- ccxt/async_support/woofipro.py +2533 -0
- ccxt/async_support/xt.py +4454 -0
- ccxt/async_support/yobit.py +1283 -0
- ccxt/async_support/zaif.py +725 -0
- ccxt/async_support/zonda.py +1828 -0
- ccxt/base/__init__.py +27 -0
- ccxt/base/decimal_to_precision.py +174 -0
- ccxt/base/errors.py +242 -0
- ccxt/base/exchange.py +5941 -0
- ccxt/base/precise.py +287 -0
- ccxt/base/types.py +502 -0
- ccxt/bequant.py +33 -0
- ccxt/bigone.py +2112 -0
- ccxt/binance.py +12233 -0
- ccxt/binancecoinm.py +45 -0
- ccxt/binanceus.py +211 -0
- ccxt/binanceusdm.py +58 -0
- ccxt/bingx.py +4324 -0
- ccxt/bit2c.py +866 -0
- ccxt/bitbank.py +1001 -0
- ccxt/bitbay.py +17 -0
- ccxt/bitbns.py +1154 -0
- ccxt/bitcoincom.py +17 -0
- ccxt/bitfinex.py +1617 -0
- ccxt/bitfinex2.py +3552 -0
- ccxt/bitflyer.py +995 -0
- ccxt/bitget.py +8272 -0
- ccxt/bithumb.py +1061 -0
- ccxt/bitimen.py +401 -0
- ccxt/bitir.py +490 -0
- ccxt/bitmart.py +4415 -0
- ccxt/bitmex.py +2756 -0
- ccxt/bitopro.py +1630 -0
- ccxt/bitpanda.py +16 -0
- ccxt/bitpin.py +454 -0
- ccxt/bitrue.py +3026 -0
- ccxt/bitso.py +1670 -0
- ccxt/bitstamp.py +2203 -0
- ccxt/bitteam.py +2239 -0
- ccxt/bitvavo.py +1968 -0
- ccxt/bl3p.py +485 -0
- ccxt/blockchaincom.py +1104 -0
- ccxt/blofin.py +2066 -0
- ccxt/btcalpha.py +891 -0
- ccxt/btcbox.py +544 -0
- ccxt/btcmarkets.py +1221 -0
- ccxt/btcturk.py +911 -0
- ccxt/bybit.py +8158 -0
- ccxt/cex.py +1605 -0
- ccxt/coinbase.py +4474 -0
- ccxt/coinbaseadvanced.py +17 -0
- ccxt/coinbaseexchange.py +1734 -0
- ccxt/coinbaseinternational.py +1899 -0
- ccxt/coincatch.py +5069 -0
- ccxt/coincheck.py +815 -0
- ccxt/coinex.py +5525 -0
- ccxt/coinlist.py +2243 -0
- ccxt/coinmate.py +1067 -0
- ccxt/coinmetro.py +1797 -0
- ccxt/coinone.py +1127 -0
- ccxt/coinsph.py +1850 -0
- ccxt/coinspot.py +534 -0
- ccxt/cryptocom.py +2822 -0
- ccxt/currencycom.py +1950 -0
- ccxt/delta.py +3376 -0
- ccxt/deribit.py +3437 -0
- ccxt/digifinex.py +3959 -0
- ccxt/eterex.py +286 -0
- ccxt/excoino.py +399 -0
- ccxt/exir.py +375 -0
- ccxt/exmo.py +2462 -0
- ccxt/exnovin.py +360 -0
- ccxt/farhadexchange.py +266 -0
- ccxt/fmfwio.py +34 -0
- ccxt/gate.py +6975 -0
- ccxt/gateio.py +16 -0
- ccxt/gemini.py +1824 -0
- ccxt/hashkey.py +4150 -0
- ccxt/hitbtc.py +3423 -0
- ccxt/hitbtc3.py +16 -0
- ccxt/hitobit.py +391 -0
- ccxt/hollaex.py +1813 -0
- ccxt/htx.py +8505 -0
- ccxt/huobi.py +16 -0
- ccxt/huobijp.py +1801 -0
- ccxt/hyperliquid.py +2430 -0
- ccxt/idex.py +1766 -0
- ccxt/independentreserve.py +784 -0
- ccxt/indodax.py +1247 -0
- ccxt/jibitex.py +395 -0
- ccxt/kraken.py +2894 -0
- ccxt/krakenfutures.py +2601 -0
- ccxt/kucoin.py +4601 -0
- ccxt/kucoinfutures.py +2698 -0
- ccxt/kuna.py +1841 -0
- ccxt/latoken.py +1664 -0
- ccxt/lbank.py +2682 -0
- ccxt/luno.py +1067 -0
- ccxt/lykke.py +1270 -0
- ccxt/mercado.py +842 -0
- ccxt/mexc.py +5369 -0
- ccxt/ndax.py +2354 -0
- ccxt/nobitex.py +419 -0
- ccxt/novadax.py +1484 -0
- ccxt/oceanex.py +903 -0
- ccxt/okcoin.py +2936 -0
- ccxt/okexchange.py +349 -0
- ccxt/okx.py +7826 -0
- ccxt/ompfinex.py +472 -0
- ccxt/onetrading.py +1911 -0
- ccxt/oxfun.py +2772 -0
- ccxt/p2b.py +1194 -0
- ccxt/paradex.py +2015 -0
- ccxt/paymium.py +564 -0
- ccxt/phemex.py +4473 -0
- ccxt/poloniex.py +2232 -0
- ccxt/poloniexfutures.py +1717 -0
- ccxt/pro/__init__.py +149 -0
- ccxt/pro/alpaca.py +685 -0
- ccxt/pro/ascendex.py +916 -0
- ccxt/pro/bequant.py +38 -0
- ccxt/pro/binance.py +3488 -0
- ccxt/pro/binancecoinm.py +28 -0
- ccxt/pro/binanceus.py +48 -0
- ccxt/pro/binanceusdm.py +31 -0
- ccxt/pro/bingx.py +1264 -0
- ccxt/pro/bitcoincom.py +34 -0
- ccxt/pro/bitfinex.py +621 -0
- ccxt/pro/bitfinex2.py +1083 -0
- ccxt/pro/bitget.py +1692 -0
- ccxt/pro/bithumb.py +368 -0
- ccxt/pro/bitmart.py +1449 -0
- ccxt/pro/bitmex.py +1656 -0
- ccxt/pro/bitopro.py +445 -0
- ccxt/pro/bitpanda.py +15 -0
- ccxt/pro/bitrue.py +447 -0
- ccxt/pro/bitstamp.py +522 -0
- ccxt/pro/bitvavo.py +1270 -0
- ccxt/pro/blockchaincom.py +738 -0
- ccxt/pro/blofin.py +692 -0
- ccxt/pro/bybit.py +2000 -0
- ccxt/pro/cex.py +1440 -0
- ccxt/pro/coinbase.py +678 -0
- ccxt/pro/coinbaseadvanced.py +16 -0
- ccxt/pro/coinbaseexchange.py +895 -0
- ccxt/pro/coinbaseinternational.py +620 -0
- ccxt/pro/coincatch.py +1464 -0
- ccxt/pro/coincheck.py +199 -0
- ccxt/pro/coinex.py +1061 -0
- ccxt/pro/coinone.py +395 -0
- ccxt/pro/cryptocom.py +947 -0
- ccxt/pro/currencycom.py +536 -0
- ccxt/pro/deribit.py +892 -0
- ccxt/pro/exmo.py +629 -0
- ccxt/pro/gate.py +1416 -0
- ccxt/pro/gateio.py +15 -0
- ccxt/pro/gemini.py +865 -0
- ccxt/pro/hashkey.py +802 -0
- ccxt/pro/hitbtc.py +1216 -0
- ccxt/pro/hollaex.py +563 -0
- ccxt/pro/htx.py +2215 -0
- ccxt/pro/huobi.py +15 -0
- ccxt/pro/huobijp.py +570 -0
- ccxt/pro/hyperliquid.py +525 -0
- ccxt/pro/idex.py +672 -0
- ccxt/pro/independentreserve.py +270 -0
- ccxt/pro/kraken.py +1356 -0
- ccxt/pro/krakenfutures.py +1492 -0
- ccxt/pro/kucoin.py +1133 -0
- ccxt/pro/kucoinfutures.py +1081 -0
- ccxt/pro/lbank.py +843 -0
- ccxt/pro/luno.py +303 -0
- ccxt/pro/mexc.py +1122 -0
- ccxt/pro/ndax.py +506 -0
- ccxt/pro/okcoin.py +698 -0
- ccxt/pro/okx.py +1851 -0
- ccxt/pro/onetrading.py +1275 -0
- ccxt/pro/oxfun.py +950 -0
- ccxt/pro/p2b.py +419 -0
- ccxt/pro/paradex.py +352 -0
- ccxt/pro/phemex.py +1441 -0
- ccxt/pro/poloniex.py +1166 -0
- ccxt/pro/poloniexfutures.py +990 -0
- ccxt/pro/probit.py +551 -0
- ccxt/pro/upbit.py +520 -0
- ccxt/pro/vertex.py +943 -0
- ccxt/pro/wazirx.py +749 -0
- ccxt/pro/whitebit.py +864 -0
- ccxt/pro/woo.py +1078 -0
- ccxt/pro/woofipro.py +1183 -0
- ccxt/pro/xt.py +1067 -0
- ccxt/probit.py +1734 -0
- ccxt/ramzinex.py +476 -0
- ccxt/sarmayex.py +357 -0
- ccxt/sarrafex.py +478 -0
- ccxt/static_dependencies/__init__.py +1 -0
- ccxt/static_dependencies/ecdsa/__init__.py +14 -0
- ccxt/static_dependencies/ecdsa/_version.py +520 -0
- ccxt/static_dependencies/ecdsa/curves.py +56 -0
- ccxt/static_dependencies/ecdsa/der.py +221 -0
- ccxt/static_dependencies/ecdsa/ecdsa.py +310 -0
- ccxt/static_dependencies/ecdsa/ellipticcurve.py +197 -0
- ccxt/static_dependencies/ecdsa/keys.py +332 -0
- ccxt/static_dependencies/ecdsa/numbertheory.py +531 -0
- ccxt/static_dependencies/ecdsa/rfc6979.py +100 -0
- ccxt/static_dependencies/ecdsa/util.py +266 -0
- ccxt/static_dependencies/ethereum/__init__.py +7 -0
- ccxt/static_dependencies/ethereum/abi/__init__.py +16 -0
- ccxt/static_dependencies/ethereum/abi/abi.py +19 -0
- ccxt/static_dependencies/ethereum/abi/base.py +152 -0
- ccxt/static_dependencies/ethereum/abi/codec.py +217 -0
- ccxt/static_dependencies/ethereum/abi/constants.py +3 -0
- ccxt/static_dependencies/ethereum/abi/decoding.py +565 -0
- ccxt/static_dependencies/ethereum/abi/encoding.py +720 -0
- ccxt/static_dependencies/ethereum/abi/exceptions.py +139 -0
- ccxt/static_dependencies/ethereum/abi/grammar.py +443 -0
- ccxt/static_dependencies/ethereum/abi/packed.py +13 -0
- ccxt/static_dependencies/ethereum/abi/py.typed +0 -0
- ccxt/static_dependencies/ethereum/abi/registry.py +643 -0
- ccxt/static_dependencies/ethereum/abi/tools/__init__.py +3 -0
- ccxt/static_dependencies/ethereum/abi/tools/_strategies.py +230 -0
- ccxt/static_dependencies/ethereum/abi/utils/__init__.py +0 -0
- ccxt/static_dependencies/ethereum/abi/utils/numeric.py +83 -0
- ccxt/static_dependencies/ethereum/abi/utils/padding.py +27 -0
- ccxt/static_dependencies/ethereum/abi/utils/string.py +19 -0
- ccxt/static_dependencies/ethereum/account/__init__.py +3 -0
- ccxt/static_dependencies/ethereum/account/encode_typed_data/__init__.py +4 -0
- ccxt/static_dependencies/ethereum/account/encode_typed_data/encoding_and_hashing.py +239 -0
- ccxt/static_dependencies/ethereum/account/encode_typed_data/helpers.py +40 -0
- ccxt/static_dependencies/ethereum/account/messages.py +263 -0
- ccxt/static_dependencies/ethereum/account/py.typed +0 -0
- ccxt/static_dependencies/ethereum/hexbytes/__init__.py +5 -0
- ccxt/static_dependencies/ethereum/hexbytes/_utils.py +54 -0
- ccxt/static_dependencies/ethereum/hexbytes/main.py +65 -0
- ccxt/static_dependencies/ethereum/hexbytes/py.typed +0 -0
- ccxt/static_dependencies/ethereum/typing/__init__.py +63 -0
- ccxt/static_dependencies/ethereum/typing/abi.py +6 -0
- ccxt/static_dependencies/ethereum/typing/bls.py +7 -0
- ccxt/static_dependencies/ethereum/typing/discovery.py +5 -0
- ccxt/static_dependencies/ethereum/typing/encoding.py +7 -0
- ccxt/static_dependencies/ethereum/typing/enums.py +17 -0
- ccxt/static_dependencies/ethereum/typing/ethpm.py +9 -0
- ccxt/static_dependencies/ethereum/typing/evm.py +20 -0
- ccxt/static_dependencies/ethereum/typing/networks.py +1122 -0
- ccxt/static_dependencies/ethereum/typing/py.typed +0 -0
- ccxt/static_dependencies/ethereum/utils/__init__.py +115 -0
- ccxt/static_dependencies/ethereum/utils/abi.py +72 -0
- ccxt/static_dependencies/ethereum/utils/address.py +171 -0
- ccxt/static_dependencies/ethereum/utils/applicators.py +151 -0
- ccxt/static_dependencies/ethereum/utils/conversions.py +190 -0
- ccxt/static_dependencies/ethereum/utils/currency.py +107 -0
- ccxt/static_dependencies/ethereum/utils/curried/__init__.py +269 -0
- ccxt/static_dependencies/ethereum/utils/debug.py +20 -0
- ccxt/static_dependencies/ethereum/utils/decorators.py +132 -0
- ccxt/static_dependencies/ethereum/utils/encoding.py +6 -0
- ccxt/static_dependencies/ethereum/utils/exceptions.py +4 -0
- ccxt/static_dependencies/ethereum/utils/functional.py +75 -0
- ccxt/static_dependencies/ethereum/utils/hexadecimal.py +74 -0
- ccxt/static_dependencies/ethereum/utils/humanize.py +188 -0
- ccxt/static_dependencies/ethereum/utils/logging.py +159 -0
- ccxt/static_dependencies/ethereum/utils/module_loading.py +31 -0
- ccxt/static_dependencies/ethereum/utils/numeric.py +43 -0
- ccxt/static_dependencies/ethereum/utils/py.typed +0 -0
- ccxt/static_dependencies/ethereum/utils/toolz.py +76 -0
- ccxt/static_dependencies/ethereum/utils/types.py +54 -0
- ccxt/static_dependencies/ethereum/utils/typing/__init__.py +18 -0
- ccxt/static_dependencies/ethereum/utils/typing/misc.py +14 -0
- ccxt/static_dependencies/ethereum/utils/units.py +31 -0
- ccxt/static_dependencies/keccak/__init__.py +3 -0
- ccxt/static_dependencies/keccak/keccak.py +197 -0
- ccxt/static_dependencies/lark/__init__.py +38 -0
- ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
- ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
- ccxt/static_dependencies/lark/ast_utils.py +59 -0
- ccxt/static_dependencies/lark/common.py +86 -0
- ccxt/static_dependencies/lark/exceptions.py +292 -0
- ccxt/static_dependencies/lark/grammar.py +130 -0
- ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
- ccxt/static_dependencies/lark/indenter.py +143 -0
- ccxt/static_dependencies/lark/lark.py +658 -0
- ccxt/static_dependencies/lark/lexer.py +678 -0
- ccxt/static_dependencies/lark/load_grammar.py +1428 -0
- ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
- ccxt/static_dependencies/lark/parser_frontends.py +257 -0
- ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
- ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
- ccxt/static_dependencies/lark/parsers/earley.py +314 -0
- ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
- ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
- ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
- ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
- ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
- ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
- ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
- ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
- ccxt/static_dependencies/lark/reconstruct.py +107 -0
- ccxt/static_dependencies/lark/tools/__init__.py +70 -0
- ccxt/static_dependencies/lark/tools/nearley.py +202 -0
- ccxt/static_dependencies/lark/tools/serialize.py +32 -0
- ccxt/static_dependencies/lark/tools/standalone.py +196 -0
- ccxt/static_dependencies/lark/tree.py +267 -0
- ccxt/static_dependencies/lark/tree_matcher.py +186 -0
- ccxt/static_dependencies/lark/tree_templates.py +180 -0
- ccxt/static_dependencies/lark/utils.py +343 -0
- ccxt/static_dependencies/lark/visitors.py +596 -0
- ccxt/static_dependencies/marshmallow/__init__.py +81 -0
- ccxt/static_dependencies/marshmallow/base.py +65 -0
- ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
- ccxt/static_dependencies/marshmallow/decorators.py +231 -0
- ccxt/static_dependencies/marshmallow/error_store.py +60 -0
- ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
- ccxt/static_dependencies/marshmallow/fields.py +2114 -0
- ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
- ccxt/static_dependencies/marshmallow/schema.py +1228 -0
- ccxt/static_dependencies/marshmallow/types.py +12 -0
- ccxt/static_dependencies/marshmallow/utils.py +378 -0
- ccxt/static_dependencies/marshmallow/validate.py +678 -0
- ccxt/static_dependencies/marshmallow/warnings.py +2 -0
- ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
- ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
- ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
- ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
- ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
- ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
- ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
- ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
- ccxt/static_dependencies/msgpack/__init__.py +55 -0
- ccxt/static_dependencies/msgpack/exceptions.py +48 -0
- ccxt/static_dependencies/msgpack/ext.py +168 -0
- ccxt/static_dependencies/msgpack/fallback.py +951 -0
- ccxt/static_dependencies/parsimonious/__init__.py +10 -0
- ccxt/static_dependencies/parsimonious/exceptions.py +105 -0
- ccxt/static_dependencies/parsimonious/expressions.py +479 -0
- ccxt/static_dependencies/parsimonious/grammar.py +487 -0
- ccxt/static_dependencies/parsimonious/nodes.py +325 -0
- ccxt/static_dependencies/parsimonious/utils.py +40 -0
- ccxt/static_dependencies/starknet/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
- ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
- ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
- ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
- ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
- ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
- ccxt/static_dependencies/starknet/common.py +15 -0
- ccxt/static_dependencies/starknet/constants.py +39 -0
- ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
- ccxt/static_dependencies/starknet/hash/address.py +79 -0
- ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
- ccxt/static_dependencies/starknet/hash/selector.py +16 -0
- ccxt/static_dependencies/starknet/hash/storage.py +12 -0
- ccxt/static_dependencies/starknet/hash/utils.py +78 -0
- ccxt/static_dependencies/starknet/models/__init__.py +0 -0
- ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
- ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
- ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
- ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
- ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
- ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
- ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
- ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
- ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
- ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
- ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
- ccxt/static_dependencies/starknet/utils/schema.py +13 -0
- ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
- ccxt/static_dependencies/starkware/__init__.py +0 -0
- ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
- ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
- ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
- ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
- ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
- ccxt/static_dependencies/sympy/__init__.py +0 -0
- ccxt/static_dependencies/sympy/core/__init__.py +0 -0
- ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
- ccxt/static_dependencies/sympy/external/__init__.py +0 -0
- ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
- ccxt/static_dependencies/sympy/external/importtools.py +187 -0
- ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
- ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
- ccxt/static_dependencies/toolz/__init__.py +26 -0
- ccxt/static_dependencies/toolz/_signatures.py +784 -0
- ccxt/static_dependencies/toolz/_version.py +520 -0
- ccxt/static_dependencies/toolz/compatibility.py +30 -0
- ccxt/static_dependencies/toolz/curried/__init__.py +101 -0
- ccxt/static_dependencies/toolz/curried/exceptions.py +22 -0
- ccxt/static_dependencies/toolz/curried/operator.py +22 -0
- ccxt/static_dependencies/toolz/dicttoolz.py +339 -0
- ccxt/static_dependencies/toolz/functoolz.py +1049 -0
- ccxt/static_dependencies/toolz/itertoolz.py +1057 -0
- ccxt/static_dependencies/toolz/recipes.py +46 -0
- ccxt/static_dependencies/toolz/utils.py +9 -0
- ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
- ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
- ccxt/tabdeal.py +364 -0
- ccxt/test/__init__.py +3 -0
- ccxt/test/base/__init__.py +29 -0
- ccxt/test/base/test_account.py +26 -0
- ccxt/test/base/test_balance.py +56 -0
- ccxt/test/base/test_borrow_interest.py +35 -0
- ccxt/test/base/test_borrow_rate.py +32 -0
- ccxt/test/base/test_calculate_fee.py +51 -0
- ccxt/test/base/test_crypto.py +127 -0
- ccxt/test/base/test_currency.py +76 -0
- ccxt/test/base/test_datetime.py +109 -0
- ccxt/test/base/test_decimal_to_precision.py +392 -0
- ccxt/test/base/test_deep_extend.py +68 -0
- ccxt/test/base/test_deposit_withdrawal.py +50 -0
- ccxt/test/base/test_exchange_datetime_functions.py +76 -0
- ccxt/test/base/test_funding_rate_history.py +29 -0
- ccxt/test/base/test_last_price.py +31 -0
- ccxt/test/base/test_ledger_entry.py +45 -0
- ccxt/test/base/test_ledger_item.py +48 -0
- ccxt/test/base/test_leverage_tier.py +33 -0
- ccxt/test/base/test_liquidation.py +50 -0
- ccxt/test/base/test_margin_mode.py +24 -0
- ccxt/test/base/test_margin_modification.py +35 -0
- ccxt/test/base/test_market.py +193 -0
- ccxt/test/base/test_number.py +411 -0
- ccxt/test/base/test_ohlcv.py +33 -0
- ccxt/test/base/test_open_interest.py +32 -0
- ccxt/test/base/test_order.py +64 -0
- ccxt/test/base/test_order_book.py +69 -0
- ccxt/test/base/test_position.py +60 -0
- ccxt/test/base/test_shared_methods.py +353 -0
- ccxt/test/base/test_status.py +24 -0
- ccxt/test/base/test_throttle.py +126 -0
- ccxt/test/base/test_ticker.py +92 -0
- ccxt/test/base/test_trade.py +47 -0
- ccxt/test/base/test_trading_fee.py +26 -0
- ccxt/test/base/test_transaction.py +39 -0
- ccxt/test/test_async.py +1649 -0
- ccxt/test/test_sync.py +1648 -0
- ccxt/test/tests_async.py +1558 -0
- ccxt/test/tests_helpers.py +287 -0
- ccxt/test/tests_init.py +39 -0
- ccxt/test/tests_sync.py +1555 -0
- ccxt/tetherland.py +349 -0
- ccxt/timex.py +1593 -0
- ccxt/tokocrypto.py +2405 -0
- ccxt/tradeogre.py +608 -0
- ccxt/twox.py +326 -0
- ccxt/ubitex.py +409 -0
- ccxt/upbit.py +1833 -0
- ccxt/vertex.py +2922 -0
- ccxt/wallex.py +445 -0
- ccxt/wavesexchange.py +2472 -0
- ccxt/wazirx.py +1224 -0
- ccxt/whitebit.py +2469 -0
- ccxt/woo.py +3114 -0
- ccxt/woofipro.py +2533 -0
- ccxt/xt.py +4453 -0
- ccxt/yobit.py +1283 -0
- ccxt/zaif.py +725 -0
- ccxt/zonda.py +1828 -0
- ccxt_ir-4.3.46.0.1.dist-info/LICENSE.txt +21 -0
- ccxt_ir-4.3.46.0.1.dist-info/METADATA +655 -0
- ccxt_ir-4.3.46.0.1.dist-info/RECORD +772 -0
- ccxt_ir-4.3.46.0.1.dist-info/WHEEL +6 -0
- ccxt_ir-4.3.46.0.1.dist-info/top_level.txt +1 -0
ccxt/pro/cex.py
ADDED
|
@@ -0,0 +1,1440 @@
|
|
|
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, ArrayCacheByTimestamp
|
|
8
|
+
import hashlib
|
|
9
|
+
from ccxt.base.types import Balances, Int, Num, Order, OrderBook, OrderSide, OrderType, 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 ExchangeError
|
|
13
|
+
from ccxt.base.errors import ArgumentsRequired
|
|
14
|
+
from ccxt.base.errors import BadRequest
|
|
15
|
+
from ccxt.base.precise import Precise
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class cex(ccxt.async_support.cex):
|
|
19
|
+
|
|
20
|
+
def describe(self):
|
|
21
|
+
return self.deep_extend(super(cex, self).describe(), {
|
|
22
|
+
'has': {
|
|
23
|
+
'ws': True,
|
|
24
|
+
'watchBalance': True,
|
|
25
|
+
'watchTicker': True,
|
|
26
|
+
'watchTickers': True,
|
|
27
|
+
'watchTrades': True,
|
|
28
|
+
'watchMyTrades': True,
|
|
29
|
+
'watchOrders': True,
|
|
30
|
+
'watchOrderBook': True,
|
|
31
|
+
'watchOHLCV': True,
|
|
32
|
+
'watchPosition': None,
|
|
33
|
+
'createOrderWs': True,
|
|
34
|
+
'editOrderWs': True,
|
|
35
|
+
'cancelOrderWs': True,
|
|
36
|
+
'cancelOrdersWs': True,
|
|
37
|
+
'fetchOrderWs': True,
|
|
38
|
+
'fetchOpenOrdersWs': True,
|
|
39
|
+
'fetchTickerWs': True,
|
|
40
|
+
'fetchBalanceWs': True,
|
|
41
|
+
},
|
|
42
|
+
'urls': {
|
|
43
|
+
'api': {
|
|
44
|
+
'ws': 'wss://ws.cex.io/ws',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
'options': {
|
|
48
|
+
'orderbook': {},
|
|
49
|
+
},
|
|
50
|
+
'streaming': {
|
|
51
|
+
},
|
|
52
|
+
'exceptions': {
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
def request_id(self):
|
|
57
|
+
requestId = self.sum(self.safe_integer(self.options, 'requestId', 0), 1)
|
|
58
|
+
self.options['requestId'] = requestId
|
|
59
|
+
return str(requestId)
|
|
60
|
+
|
|
61
|
+
async def watch_balance(self, params={}) -> Balances:
|
|
62
|
+
"""
|
|
63
|
+
watch balance and get the amount of funds available for trading or funds locked in orders
|
|
64
|
+
:see: https://cex.io/websocket-api#get-balance
|
|
65
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
66
|
+
:returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
|
|
67
|
+
"""
|
|
68
|
+
await self.authenticate(params)
|
|
69
|
+
messageHash = self.request_id()
|
|
70
|
+
url = self.urls['api']['ws']
|
|
71
|
+
subscribe: dict = {
|
|
72
|
+
'e': 'get-balance',
|
|
73
|
+
'data': {},
|
|
74
|
+
'oid': self.request_id(),
|
|
75
|
+
}
|
|
76
|
+
request = self.deep_extend(subscribe, params)
|
|
77
|
+
return await self.watch(url, messageHash, request, messageHash, request)
|
|
78
|
+
|
|
79
|
+
def handle_balance(self, client: Client, message):
|
|
80
|
+
#
|
|
81
|
+
# {
|
|
82
|
+
# "e": "get-balance",
|
|
83
|
+
# "data": {
|
|
84
|
+
# "balance": {
|
|
85
|
+
# "BTC": "0.00000000",
|
|
86
|
+
# "USD": "0.00",
|
|
87
|
+
# ...
|
|
88
|
+
# },
|
|
89
|
+
# "obalance": {
|
|
90
|
+
# "BTC": "0.00000000",
|
|
91
|
+
# "USD": "0.00",
|
|
92
|
+
# ...
|
|
93
|
+
# },
|
|
94
|
+
# "time": 1663761159605
|
|
95
|
+
# },
|
|
96
|
+
# "oid": 1,
|
|
97
|
+
# "ok": "ok"
|
|
98
|
+
# }
|
|
99
|
+
#
|
|
100
|
+
data = self.safe_value(message, 'data', {})
|
|
101
|
+
freeBalance = self.safe_value(data, 'balance', {})
|
|
102
|
+
usedBalance = self.safe_value(data, 'obalance', {})
|
|
103
|
+
result: dict = {
|
|
104
|
+
'info': data,
|
|
105
|
+
}
|
|
106
|
+
currencyIds = list(freeBalance.keys())
|
|
107
|
+
for i in range(0, len(currencyIds)):
|
|
108
|
+
currencyId = currencyIds[i]
|
|
109
|
+
account = self.account()
|
|
110
|
+
account['free'] = self.safe_string(freeBalance, currencyId)
|
|
111
|
+
account['used'] = self.safe_string(usedBalance, currencyId)
|
|
112
|
+
code = self.safe_currency_code(currencyId)
|
|
113
|
+
result[code] = account
|
|
114
|
+
self.balance = self.safe_balance(result)
|
|
115
|
+
messageHash = self.safe_string(message, 'oid')
|
|
116
|
+
client.resolve(self.balance, messageHash)
|
|
117
|
+
|
|
118
|
+
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
|
119
|
+
"""
|
|
120
|
+
get the list of most recent trades for a particular symbol. Note: can only watch one symbol at a time.
|
|
121
|
+
:see: https://cex.io/websocket-api#old-pair-room
|
|
122
|
+
:param str symbol: unified symbol of the market to fetch trades for
|
|
123
|
+
:param int [since]: timestamp in ms of the earliest trade to fetch
|
|
124
|
+
:param int [limit]: the maximum amount of trades to fetch
|
|
125
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
126
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
|
127
|
+
"""
|
|
128
|
+
await self.load_markets()
|
|
129
|
+
market = self.market(symbol)
|
|
130
|
+
symbol = market['symbol']
|
|
131
|
+
url = self.urls['api']['ws']
|
|
132
|
+
messageHash = 'trades'
|
|
133
|
+
subscriptionHash = 'old:' + symbol
|
|
134
|
+
self.options['currentWatchTradeSymbol'] = symbol # exchange supports only 1 symbol for self watchTrades channel
|
|
135
|
+
client = self.safe_value(self.clients, url)
|
|
136
|
+
if client is not None:
|
|
137
|
+
subscriptionKeys = list(client.subscriptions.keys())
|
|
138
|
+
for i in range(0, len(subscriptionKeys)):
|
|
139
|
+
subscriptionKey = subscriptionKeys[i]
|
|
140
|
+
if subscriptionKey == subscriptionHash:
|
|
141
|
+
continue
|
|
142
|
+
subscriptionKey = subscriptionKey[0:3]
|
|
143
|
+
if subscriptionKey == 'old':
|
|
144
|
+
raise ExchangeError(self.id + ' watchTrades() only supports watching one symbol at a time.')
|
|
145
|
+
message: dict = {
|
|
146
|
+
'e': 'subscribe',
|
|
147
|
+
'rooms': ['pair-' + market['base'] + '-' + market['quote']],
|
|
148
|
+
}
|
|
149
|
+
request = self.deep_extend(message, params)
|
|
150
|
+
trades = await self.watch(url, messageHash, request, subscriptionHash)
|
|
151
|
+
# assing symbol to the trades does not contain symbol information
|
|
152
|
+
for i in range(0, len(trades)):
|
|
153
|
+
trades[i]['symbol'] = symbol
|
|
154
|
+
return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
|
|
155
|
+
|
|
156
|
+
def handle_trades_snapshot(self, client: Client, message):
|
|
157
|
+
#
|
|
158
|
+
# {
|
|
159
|
+
# "e": "history",
|
|
160
|
+
# "data": [
|
|
161
|
+
# 'buy:1710255706095:444444:71222.2:14892622'
|
|
162
|
+
# 'sell:1710255658251:42530:71300:14892621'
|
|
163
|
+
# 'buy:1710252424241:87913:72800:14892620'
|
|
164
|
+
# ... timestamp descending
|
|
165
|
+
# ]
|
|
166
|
+
# }
|
|
167
|
+
#
|
|
168
|
+
data = self.safe_list(message, 'data', [])
|
|
169
|
+
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
|
170
|
+
stored = ArrayCache(limit)
|
|
171
|
+
symbol = self.safe_string(self.options, 'currentWatchTradeSymbol')
|
|
172
|
+
if symbol is None:
|
|
173
|
+
return
|
|
174
|
+
market = self.market(symbol)
|
|
175
|
+
dataLength = len(data)
|
|
176
|
+
for i in range(0, dataLength):
|
|
177
|
+
index = dataLength - 1 - i
|
|
178
|
+
rawTrade = data[index]
|
|
179
|
+
parsed = self.parse_ws_old_trade(rawTrade, market)
|
|
180
|
+
stored.append(parsed)
|
|
181
|
+
messageHash = 'trades'
|
|
182
|
+
self.trades = stored # trades don't have symbol
|
|
183
|
+
client.resolve(self.trades, messageHash)
|
|
184
|
+
|
|
185
|
+
def parse_ws_old_trade(self, trade, market=None):
|
|
186
|
+
#
|
|
187
|
+
# snapshot trade
|
|
188
|
+
# "sell:1665467367741:3888551:19058.8:14541219"
|
|
189
|
+
# update trade
|
|
190
|
+
# ['buy', '1665467516704', '98070', "19057.7", "14541220"]
|
|
191
|
+
#
|
|
192
|
+
if not isinstance(trade, list):
|
|
193
|
+
trade = trade.split(':')
|
|
194
|
+
side = self.safe_string(trade, 0)
|
|
195
|
+
timestamp = self.safe_integer(trade, 1)
|
|
196
|
+
amount = self.safe_string(trade, 2)
|
|
197
|
+
price = self.safe_string(trade, 3)
|
|
198
|
+
id = self.safe_string(trade, 4)
|
|
199
|
+
return self.safe_trade({
|
|
200
|
+
'info': trade,
|
|
201
|
+
'id': id,
|
|
202
|
+
'timestamp': timestamp,
|
|
203
|
+
'datetime': self.iso8601(timestamp),
|
|
204
|
+
'symbol': self.safe_string(market, 'symbol'),
|
|
205
|
+
'type': None,
|
|
206
|
+
'side': side,
|
|
207
|
+
'order': None,
|
|
208
|
+
'takerOrMaker': None,
|
|
209
|
+
'price': price,
|
|
210
|
+
'amount': amount,
|
|
211
|
+
'cost': None,
|
|
212
|
+
'fee': None,
|
|
213
|
+
}, market)
|
|
214
|
+
|
|
215
|
+
def handle_trade(self, client: Client, message):
|
|
216
|
+
#
|
|
217
|
+
# {
|
|
218
|
+
# "e": "history-update",
|
|
219
|
+
# "data": [
|
|
220
|
+
# ['buy', '1665467516704', '98070', "19057.7", "14541220"]
|
|
221
|
+
# ]
|
|
222
|
+
# }
|
|
223
|
+
#
|
|
224
|
+
data = self.safe_value(message, 'data', [])
|
|
225
|
+
stored = self.trades # to do fix self, self.trades is not meant to be used like self
|
|
226
|
+
dataLength = len(data)
|
|
227
|
+
for i in range(0, dataLength):
|
|
228
|
+
index = dataLength - 1 - i
|
|
229
|
+
rawTrade = data[index]
|
|
230
|
+
parsed = self.parse_ws_old_trade(rawTrade)
|
|
231
|
+
stored.append(parsed)
|
|
232
|
+
messageHash = 'trades'
|
|
233
|
+
self.trades = stored
|
|
234
|
+
client.resolve(self.trades, messageHash)
|
|
235
|
+
|
|
236
|
+
async def watch_ticker(self, symbol: str, params={}) -> Ticker:
|
|
237
|
+
"""
|
|
238
|
+
:see: https://cex.io/websocket-api#ticker-subscription
|
|
239
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
240
|
+
:param str symbol: unified symbol of the market to fetch the ticker for
|
|
241
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
242
|
+
:param str [params.method]: public or private
|
|
243
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
|
244
|
+
"""
|
|
245
|
+
await self.load_markets()
|
|
246
|
+
market = self.market(symbol)
|
|
247
|
+
symbol = market['symbol']
|
|
248
|
+
url = self.urls['api']['ws']
|
|
249
|
+
messageHash = 'ticker:' + symbol
|
|
250
|
+
method = self.safe_string(params, 'method', 'private') # default to private because the specified ticker is received quicker
|
|
251
|
+
message = {
|
|
252
|
+
'e': 'subscribe',
|
|
253
|
+
'rooms': [
|
|
254
|
+
'tickers',
|
|
255
|
+
],
|
|
256
|
+
}
|
|
257
|
+
subscriptionHash = 'tickers'
|
|
258
|
+
if method == 'private':
|
|
259
|
+
await self.authenticate()
|
|
260
|
+
message = {
|
|
261
|
+
'e': 'ticker',
|
|
262
|
+
'data': [
|
|
263
|
+
market['baseId'], market['quoteId'],
|
|
264
|
+
],
|
|
265
|
+
'oid': self.request_id(),
|
|
266
|
+
}
|
|
267
|
+
subscriptionHash = 'ticker:' + symbol
|
|
268
|
+
request = self.deep_extend(message, params)
|
|
269
|
+
return await self.watch(url, messageHash, request, subscriptionHash)
|
|
270
|
+
|
|
271
|
+
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
|
272
|
+
"""
|
|
273
|
+
:see: https://cex.io/websocket-api#ticker-subscription
|
|
274
|
+
watches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
|
|
275
|
+
:param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
|
|
276
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
277
|
+
:returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
|
|
278
|
+
"""
|
|
279
|
+
await self.load_markets()
|
|
280
|
+
symbols = self.market_symbols(symbols)
|
|
281
|
+
url = self.urls['api']['ws']
|
|
282
|
+
messageHash = 'tickers'
|
|
283
|
+
message: dict = {
|
|
284
|
+
'e': 'subscribe',
|
|
285
|
+
'rooms': [
|
|
286
|
+
'tickers',
|
|
287
|
+
],
|
|
288
|
+
}
|
|
289
|
+
request = self.deep_extend(message, params)
|
|
290
|
+
ticker = await self.watch(url, messageHash, request, messageHash)
|
|
291
|
+
tickerSymbol = ticker['symbol']
|
|
292
|
+
if symbols is not None and not self.in_array(tickerSymbol, symbols):
|
|
293
|
+
return await self.watch_tickers(symbols, params)
|
|
294
|
+
if self.newUpdates:
|
|
295
|
+
result: dict = {}
|
|
296
|
+
result[tickerSymbol] = ticker
|
|
297
|
+
return result
|
|
298
|
+
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
|
299
|
+
|
|
300
|
+
async def fetch_ticker_ws(self, symbol: str, params={}) -> Ticker:
|
|
301
|
+
"""
|
|
302
|
+
:see: https://docs.cex.io/#ws-api-ticker-deprecated
|
|
303
|
+
fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
304
|
+
:param str symbol: unified symbol of the market to fetch the ticker for
|
|
305
|
+
:param dict [params]: extra parameters specific to the cex api endpoint
|
|
306
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
|
307
|
+
"""
|
|
308
|
+
await self.load_markets()
|
|
309
|
+
market = self.market(symbol)
|
|
310
|
+
url = self.urls['api']['ws']
|
|
311
|
+
messageHash = self.request_id()
|
|
312
|
+
request = self.extend({
|
|
313
|
+
'e': 'ticker',
|
|
314
|
+
'oid': messageHash,
|
|
315
|
+
'data': [market['base'], market['quote']],
|
|
316
|
+
}, params)
|
|
317
|
+
return await self.watch(url, messageHash, request, messageHash)
|
|
318
|
+
|
|
319
|
+
def handle_ticker(self, client: Client, message):
|
|
320
|
+
#
|
|
321
|
+
# {
|
|
322
|
+
# "e": "tick",
|
|
323
|
+
# "data": {
|
|
324
|
+
# "symbol1": "LRC",
|
|
325
|
+
# "symbol2": "USD",
|
|
326
|
+
# "price": "0.305",
|
|
327
|
+
# "open24": "0.301",
|
|
328
|
+
# "volume": "241421.641700"
|
|
329
|
+
# }
|
|
330
|
+
# }
|
|
331
|
+
#
|
|
332
|
+
data = self.safe_value(message, 'data', {})
|
|
333
|
+
ticker = self.parse_ws_ticker(data)
|
|
334
|
+
symbol = ticker['symbol']
|
|
335
|
+
if symbol is None:
|
|
336
|
+
return
|
|
337
|
+
self.tickers[symbol] = ticker
|
|
338
|
+
messageHash = 'ticker:' + symbol
|
|
339
|
+
client.resolve(ticker, messageHash)
|
|
340
|
+
client.resolve(ticker, 'tickers')
|
|
341
|
+
messageHash = self.safe_string(message, 'oid')
|
|
342
|
+
if messageHash is not None:
|
|
343
|
+
client.resolve(ticker, messageHash)
|
|
344
|
+
|
|
345
|
+
def parse_ws_ticker(self, ticker, market=None):
|
|
346
|
+
#
|
|
347
|
+
# public
|
|
348
|
+
# {
|
|
349
|
+
# "symbol1": "LRC",
|
|
350
|
+
# "symbol2": "USD",
|
|
351
|
+
# "price": "0.305",
|
|
352
|
+
# "open24": "0.301",
|
|
353
|
+
# "volume": "241421.641700"
|
|
354
|
+
# }
|
|
355
|
+
# private
|
|
356
|
+
# {
|
|
357
|
+
# "timestamp": "1663764969",
|
|
358
|
+
# "low": "18756.3",
|
|
359
|
+
# "high": "19200",
|
|
360
|
+
# "last": "19200",
|
|
361
|
+
# "volume": "0.94735907",
|
|
362
|
+
# "volume30d": "64.61299999",
|
|
363
|
+
# "bid": 19217.2,
|
|
364
|
+
# "ask": 19247.5,
|
|
365
|
+
# "priceChange": "44.3",
|
|
366
|
+
# "priceChangePercentage": "0.23",
|
|
367
|
+
# "pair": ["BTC", "USDT"]
|
|
368
|
+
# }
|
|
369
|
+
pair = self.safe_value(ticker, 'pair', [])
|
|
370
|
+
baseId = self.safe_string(ticker, 'symbol1')
|
|
371
|
+
if baseId is None:
|
|
372
|
+
baseId = self.safe_string(pair, 0)
|
|
373
|
+
quoteId = self.safe_string(ticker, 'symbol2')
|
|
374
|
+
if quoteId is None:
|
|
375
|
+
quoteId = self.safe_string(pair, 1)
|
|
376
|
+
base = self.safe_currency_code(baseId)
|
|
377
|
+
quote = self.safe_currency_code(quoteId)
|
|
378
|
+
symbol = base + '/' + quote
|
|
379
|
+
timestamp = self.safe_integer(ticker, 'timestamp')
|
|
380
|
+
if timestamp is not None:
|
|
381
|
+
timestamp = timestamp * 1000
|
|
382
|
+
return self.safe_ticker({
|
|
383
|
+
'symbol': symbol,
|
|
384
|
+
'timestamp': timestamp,
|
|
385
|
+
'datetime': self.iso8601(timestamp),
|
|
386
|
+
'high': self.safe_string(ticker, 'high'),
|
|
387
|
+
'low': self.safe_string(ticker, 'low'),
|
|
388
|
+
'bid': self.safe_string(ticker, 'bid'),
|
|
389
|
+
'bidVolume': None,
|
|
390
|
+
'ask': self.safe_string(ticker, 'ask'),
|
|
391
|
+
'askVolume': None,
|
|
392
|
+
'vwap': None,
|
|
393
|
+
'open': self.safe_string(ticker, 'open24'),
|
|
394
|
+
'close': None,
|
|
395
|
+
'last': self.safe_string_2(ticker, 'price', 'last'),
|
|
396
|
+
'previousClose': None,
|
|
397
|
+
'change': self.safe_string(ticker, 'priceChange'),
|
|
398
|
+
'percentage': self.safe_string(ticker, 'priceChangePercentage'),
|
|
399
|
+
'average': None,
|
|
400
|
+
'baseVolume': None,
|
|
401
|
+
'quoteVolume': self.safe_string(ticker, 'volume'),
|
|
402
|
+
'info': ticker,
|
|
403
|
+
}, market)
|
|
404
|
+
|
|
405
|
+
async def fetch_balance_ws(self, params={}) -> Balances:
|
|
406
|
+
"""
|
|
407
|
+
:see: https://docs.cex.io/#ws-api-get-balance
|
|
408
|
+
query for balance and get the amount of funds available for trading or funds locked in orders
|
|
409
|
+
:param dict [params]: extra parameters specific to the cex api endpoint
|
|
410
|
+
:returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
|
|
411
|
+
"""
|
|
412
|
+
await self.load_markets()
|
|
413
|
+
await self.authenticate()
|
|
414
|
+
url = self.urls['api']['ws']
|
|
415
|
+
messageHash = self.request_id()
|
|
416
|
+
request = self.extend({
|
|
417
|
+
'e': 'get-balance',
|
|
418
|
+
'oid': messageHash,
|
|
419
|
+
}, params)
|
|
420
|
+
return await self.watch(url, messageHash, request, messageHash)
|
|
421
|
+
|
|
422
|
+
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
|
423
|
+
"""
|
|
424
|
+
get the list of orders associated with the user. Note: In CEX.IO system, orders can be present in trade engine or in archive database. There can be time periods(~2 seconds or more), when order is done/canceled, but still not moved to archive database. That means, you cannot see it using calls: archived-orders/open-orders.
|
|
425
|
+
:see: https://docs.cex.io/#ws-api-open-orders
|
|
426
|
+
:param str symbol: unified symbol of the market to fetch trades for
|
|
427
|
+
:param int [since]: timestamp in ms of the earliest trade to fetch
|
|
428
|
+
:param int [limit]: the maximum amount of trades to fetch
|
|
429
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
430
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
|
431
|
+
"""
|
|
432
|
+
if symbol is None:
|
|
433
|
+
raise ArgumentsRequired(self.id + ' watchOrders() requires a symbol argument')
|
|
434
|
+
await self.load_markets()
|
|
435
|
+
await self.authenticate(params)
|
|
436
|
+
url = self.urls['api']['ws']
|
|
437
|
+
market = self.market(symbol)
|
|
438
|
+
symbol = market['symbol']
|
|
439
|
+
messageHash = 'orders:' + symbol
|
|
440
|
+
message: dict = {
|
|
441
|
+
'e': 'open-orders',
|
|
442
|
+
'data': {
|
|
443
|
+
'pair': [
|
|
444
|
+
market['baseId'],
|
|
445
|
+
market['quoteId'],
|
|
446
|
+
],
|
|
447
|
+
},
|
|
448
|
+
'oid': symbol,
|
|
449
|
+
}
|
|
450
|
+
request = self.deep_extend(message, params)
|
|
451
|
+
orders = await self.watch(url, messageHash, request, messageHash, request)
|
|
452
|
+
if self.newUpdates:
|
|
453
|
+
limit = orders.getLimit(symbol, limit)
|
|
454
|
+
return self.filter_by_symbol_since_limit(orders, symbol, since, limit, True)
|
|
455
|
+
|
|
456
|
+
async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
|
457
|
+
"""
|
|
458
|
+
get the list of trades associated with the user. Note: In CEX.IO system, orders can be present in trade engine or in archive database. There can be time periods(~2 seconds or more), when order is done/canceled, but still not moved to archive database. That means, you cannot see it using calls: archived-orders/open-orders.
|
|
459
|
+
:see: https://docs.cex.io/#ws-api-open-orders
|
|
460
|
+
:param str symbol: unified symbol of the market to fetch trades for
|
|
461
|
+
:param int [since]: timestamp in ms of the earliest trade to fetch
|
|
462
|
+
:param int [limit]: the maximum amount of trades to fetch
|
|
463
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
464
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
|
465
|
+
"""
|
|
466
|
+
if symbol is None:
|
|
467
|
+
raise ArgumentsRequired(self.id + ' watchMyTrades() requires a symbol argument')
|
|
468
|
+
await self.load_markets()
|
|
469
|
+
await self.authenticate(params)
|
|
470
|
+
url = self.urls['api']['ws']
|
|
471
|
+
market = self.market(symbol)
|
|
472
|
+
messageHash = 'myTrades:' + market['symbol']
|
|
473
|
+
subscriptionHash = 'orders:' + market['symbol']
|
|
474
|
+
message: dict = {
|
|
475
|
+
'e': 'open-orders',
|
|
476
|
+
'data': {
|
|
477
|
+
'pair': [
|
|
478
|
+
market['baseId'],
|
|
479
|
+
market['quoteId'],
|
|
480
|
+
],
|
|
481
|
+
},
|
|
482
|
+
'oid': market['symbol'],
|
|
483
|
+
}
|
|
484
|
+
request = self.deep_extend(message, params)
|
|
485
|
+
orders = await self.watch(url, messageHash, request, subscriptionHash, request)
|
|
486
|
+
return self.filter_by_symbol_since_limit(orders, market['symbol'], since, limit)
|
|
487
|
+
|
|
488
|
+
def handle_transaction(self, client: Client, message):
|
|
489
|
+
data = self.safe_value(message, 'data')
|
|
490
|
+
symbol2 = self.safe_string(data, 'symbol2')
|
|
491
|
+
if symbol2 is None:
|
|
492
|
+
return
|
|
493
|
+
self.handle_order_update(client, message)
|
|
494
|
+
self.handle_my_trades(client, message)
|
|
495
|
+
|
|
496
|
+
def handle_my_trades(self, client: Client, message):
|
|
497
|
+
#
|
|
498
|
+
# {
|
|
499
|
+
# "e": "tx",
|
|
500
|
+
# "data": {
|
|
501
|
+
# "d": "order:59091012956:a:USD",
|
|
502
|
+
# "c": "user:up105393824:a:USD",
|
|
503
|
+
# "a": "0.01",
|
|
504
|
+
# "ds": 0,
|
|
505
|
+
# "cs": "15.27",
|
|
506
|
+
# "user": "up105393824",
|
|
507
|
+
# "symbol": "USD",
|
|
508
|
+
# "order": 59091012956,
|
|
509
|
+
# "amount": "-18.49",
|
|
510
|
+
# "type": "buy",
|
|
511
|
+
# "time": "2022-09-24T19:36:18.466Z",
|
|
512
|
+
# "balance": "15.27",
|
|
513
|
+
# "id": "59091012966"
|
|
514
|
+
# }
|
|
515
|
+
# }
|
|
516
|
+
# {
|
|
517
|
+
# "e": "tx",
|
|
518
|
+
# "data": {
|
|
519
|
+
# "d": "order:59091012956:a:BTC",
|
|
520
|
+
# "c": "user:up105393824:a:BTC",
|
|
521
|
+
# "a": "0.00096420",
|
|
522
|
+
# "ds": 0,
|
|
523
|
+
# "cs": "0.00096420",
|
|
524
|
+
# "user": "up105393824",
|
|
525
|
+
# "symbol": "BTC",
|
|
526
|
+
# "symbol2": "USD",
|
|
527
|
+
# "amount": "0.00096420",
|
|
528
|
+
# "buy": 59091012956,
|
|
529
|
+
# "order": 59091012956,
|
|
530
|
+
# "sell": 59090796005,
|
|
531
|
+
# "price": 19135,
|
|
532
|
+
# "type": "buy",
|
|
533
|
+
# "time": "2022-09-24T19:36:18.466Z",
|
|
534
|
+
# "balance": "0.00096420",
|
|
535
|
+
# "fee_amount": "0.05",
|
|
536
|
+
# "id": "59091012962"
|
|
537
|
+
# }
|
|
538
|
+
# }
|
|
539
|
+
data = self.safe_value(message, 'data', {})
|
|
540
|
+
stored = self.myTrades
|
|
541
|
+
if stored is None:
|
|
542
|
+
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
|
543
|
+
stored = ArrayCacheBySymbolById(limit)
|
|
544
|
+
self.myTrades = stored
|
|
545
|
+
trade = self.parse_ws_trade(data)
|
|
546
|
+
stored.append(trade)
|
|
547
|
+
messageHash = 'myTrades:' + trade['symbol']
|
|
548
|
+
client.resolve(stored, messageHash)
|
|
549
|
+
|
|
550
|
+
def parse_ws_trade(self, trade, market=None):
|
|
551
|
+
#
|
|
552
|
+
# {
|
|
553
|
+
# "d": "order:59091012956:a:BTC",
|
|
554
|
+
# "c": "user:up105393824:a:BTC",
|
|
555
|
+
# "a": "0.00096420",
|
|
556
|
+
# "ds": 0,
|
|
557
|
+
# "cs": "0.00096420",
|
|
558
|
+
# "user": "up105393824",
|
|
559
|
+
# "symbol": "BTC",
|
|
560
|
+
# "symbol2": "USD",
|
|
561
|
+
# "amount": "0.00096420",
|
|
562
|
+
# "buy": 59091012956,
|
|
563
|
+
# "order": 59091012956,
|
|
564
|
+
# "sell": 59090796005,
|
|
565
|
+
# "price": 19135,
|
|
566
|
+
# "type": "buy",
|
|
567
|
+
# "time": "2022-09-24T19:36:18.466Z",
|
|
568
|
+
# "balance": "0.00096420",
|
|
569
|
+
# "fee_amount": "0.05",
|
|
570
|
+
# "id": "59091012962"
|
|
571
|
+
# }
|
|
572
|
+
# Note symbol and symbol2 are inverse on sell and ammount is in symbol currency.
|
|
573
|
+
#
|
|
574
|
+
side = self.safe_string(trade, 'type')
|
|
575
|
+
price = self.safe_string(trade, 'price')
|
|
576
|
+
datetime = self.safe_string(trade, 'time')
|
|
577
|
+
baseId = self.safe_string(trade, 'symbol')
|
|
578
|
+
quoteId = self.safe_string(trade, 'symbol2')
|
|
579
|
+
base = self.safe_currency_code(baseId)
|
|
580
|
+
quote = self.safe_currency_code(quoteId)
|
|
581
|
+
symbol = base + '/' + quote
|
|
582
|
+
amount = self.safe_string(trade, 'amount')
|
|
583
|
+
if side == 'sell':
|
|
584
|
+
symbol = quote + '/' + base
|
|
585
|
+
amount = Precise.string_div(amount, price) # due to rounding errors amount in not exact to trade
|
|
586
|
+
parsedTrade: dict = {
|
|
587
|
+
'id': self.safe_string(trade, 'id'),
|
|
588
|
+
'order': self.safe_string(trade, 'order'),
|
|
589
|
+
'info': trade,
|
|
590
|
+
'timestamp': self.parse8601(datetime),
|
|
591
|
+
'datetime': datetime,
|
|
592
|
+
'symbol': symbol,
|
|
593
|
+
'type': None,
|
|
594
|
+
'side': side,
|
|
595
|
+
'takerOrMaker': None,
|
|
596
|
+
'price': price,
|
|
597
|
+
'cost': None,
|
|
598
|
+
'amount': amount,
|
|
599
|
+
'fee': None,
|
|
600
|
+
}
|
|
601
|
+
fee = self.safe_string(trade, 'fee_amount')
|
|
602
|
+
if fee is not None:
|
|
603
|
+
parsedTrade['fee'] = {
|
|
604
|
+
'cost': fee,
|
|
605
|
+
'currency': quote,
|
|
606
|
+
'rate': None,
|
|
607
|
+
}
|
|
608
|
+
return self.safe_trade(parsedTrade, market)
|
|
609
|
+
|
|
610
|
+
def handle_order_update(self, client: Client, message):
|
|
611
|
+
#
|
|
612
|
+
# partialExecution
|
|
613
|
+
# {
|
|
614
|
+
# "e": "order",
|
|
615
|
+
# "data": {
|
|
616
|
+
# "id": "150714937",
|
|
617
|
+
# "remains": "1000000",
|
|
618
|
+
# "price": "17513",
|
|
619
|
+
# "amount": 2000000, As Precision
|
|
620
|
+
# "time": "1654506118448",
|
|
621
|
+
# "type": "buy",
|
|
622
|
+
# "pair": {
|
|
623
|
+
# "symbol1": "BTC",
|
|
624
|
+
# "symbol2": "USD"
|
|
625
|
+
# },
|
|
626
|
+
# "fee": "0.15"
|
|
627
|
+
# }
|
|
628
|
+
# }
|
|
629
|
+
# canceled order
|
|
630
|
+
# {
|
|
631
|
+
# "e": "order",
|
|
632
|
+
# "data": {
|
|
633
|
+
# "id": "6310857",
|
|
634
|
+
# "remains": "200000000"
|
|
635
|
+
# "fremains": "2.00000000"
|
|
636
|
+
# "cancel": True,
|
|
637
|
+
# "pair": {
|
|
638
|
+
# "symbol1": "BTC",
|
|
639
|
+
# "symbol2": "USD"
|
|
640
|
+
# }
|
|
641
|
+
# }
|
|
642
|
+
# }
|
|
643
|
+
# fullfilledOrder
|
|
644
|
+
# {
|
|
645
|
+
# "e": "order",
|
|
646
|
+
# "data": {
|
|
647
|
+
# "id": "59098421630",
|
|
648
|
+
# "remains": "0",
|
|
649
|
+
# "pair": {
|
|
650
|
+
# "symbol1": "BTC",
|
|
651
|
+
# "symbol2": "USD"
|
|
652
|
+
# }
|
|
653
|
+
# }
|
|
654
|
+
# }
|
|
655
|
+
# {
|
|
656
|
+
# "e": "tx",
|
|
657
|
+
# "data": {
|
|
658
|
+
# "d": "order:59425993014:a:BTC",
|
|
659
|
+
# "c": "user:up105393824:a:BTC",
|
|
660
|
+
# "a": "0.00098152",
|
|
661
|
+
# "ds": 0,
|
|
662
|
+
# "cs": "0.00098152",
|
|
663
|
+
# "user": "up105393824",
|
|
664
|
+
# "symbol": "BTC",
|
|
665
|
+
# "symbol2": "USD",
|
|
666
|
+
# "amount": "0.00098152",
|
|
667
|
+
# "buy": 59425993014,
|
|
668
|
+
# "order": 59425993014,
|
|
669
|
+
# "sell": 59425986168,
|
|
670
|
+
# "price": 19306.6,
|
|
671
|
+
# "type": "buy",
|
|
672
|
+
# "time": "2022-10-02T01:11:15.148Z",
|
|
673
|
+
# "balance": "0.00098152",
|
|
674
|
+
# "fee_amount": "0.05",
|
|
675
|
+
# "id": "59425993020"
|
|
676
|
+
# }
|
|
677
|
+
# }
|
|
678
|
+
#
|
|
679
|
+
data = self.safe_value(message, 'data', {})
|
|
680
|
+
isTransaction = self.safe_string(message, 'e') == 'tx'
|
|
681
|
+
orderId = self.safe_string_2(data, 'id', 'order')
|
|
682
|
+
remains = self.safe_string(data, 'remains')
|
|
683
|
+
baseId = self.safe_string(data, 'symbol')
|
|
684
|
+
quoteId = self.safe_string(data, 'symbol2')
|
|
685
|
+
pair = self.safe_value(data, 'pair')
|
|
686
|
+
if pair is not None:
|
|
687
|
+
baseId = self.safe_string(pair, 'symbol1')
|
|
688
|
+
quoteId = self.safe_string(pair, 'symbol2')
|
|
689
|
+
base = self.safe_currency_code(baseId)
|
|
690
|
+
quote = self.safe_currency_code(quoteId)
|
|
691
|
+
symbol = base + '/' + quote
|
|
692
|
+
market = self.safe_market(symbol)
|
|
693
|
+
remains = self.currency_from_precision(base, remains)
|
|
694
|
+
if self.orders is None:
|
|
695
|
+
limit = self.safe_integer(self.options, 'ordersLimit', 1000)
|
|
696
|
+
self.orders = ArrayCacheBySymbolById(limit)
|
|
697
|
+
storedOrders = self.orders
|
|
698
|
+
ordersBySymbol = self.safe_value(storedOrders.hashmap, symbol, {})
|
|
699
|
+
order = self.safe_value(ordersBySymbol, orderId)
|
|
700
|
+
if order is None:
|
|
701
|
+
order = self.parse_ws_order_update(data, market)
|
|
702
|
+
order['remaining'] = remains
|
|
703
|
+
canceled = self.safe_bool(data, 'cancel', False)
|
|
704
|
+
if canceled:
|
|
705
|
+
order['status'] = 'canceled'
|
|
706
|
+
if isTransaction:
|
|
707
|
+
order['status'] = 'closed'
|
|
708
|
+
fee = self.safe_number(data, 'fee')
|
|
709
|
+
if fee is not None:
|
|
710
|
+
order['fee'] = {
|
|
711
|
+
'cost': fee,
|
|
712
|
+
'currency': quote,
|
|
713
|
+
'rate': None,
|
|
714
|
+
}
|
|
715
|
+
timestamp = self.safe_integer(data, 'time')
|
|
716
|
+
order['timestamp'] = timestamp
|
|
717
|
+
order['datetime'] = self.iso8601(timestamp)
|
|
718
|
+
order = self.safe_order(order)
|
|
719
|
+
storedOrders.append(order)
|
|
720
|
+
messageHash = 'orders:' + symbol
|
|
721
|
+
client.resolve(storedOrders, messageHash)
|
|
722
|
+
|
|
723
|
+
def parse_ws_order_update(self, order, market=None):
|
|
724
|
+
#
|
|
725
|
+
# {
|
|
726
|
+
# "id": "150714937",
|
|
727
|
+
# "remains": "1000000",
|
|
728
|
+
# "price": "17513",
|
|
729
|
+
# "amount": 2000000, As Precision
|
|
730
|
+
# "time": "1654506118448",
|
|
731
|
+
# "type": "buy",
|
|
732
|
+
# "pair": {
|
|
733
|
+
# "symbol1": "BTC",
|
|
734
|
+
# "symbol2": "USD"
|
|
735
|
+
# },
|
|
736
|
+
# "fee": "0.15"
|
|
737
|
+
# }
|
|
738
|
+
# transaction
|
|
739
|
+
# {
|
|
740
|
+
# "d": "order:59425993014:a:BTC",
|
|
741
|
+
# "c": "user:up105393824:a:BTC",
|
|
742
|
+
# "a": "0.00098152",
|
|
743
|
+
# "ds": 0,
|
|
744
|
+
# "cs": "0.00098152",
|
|
745
|
+
# "user": "up105393824",
|
|
746
|
+
# "symbol": "BTC",
|
|
747
|
+
# "symbol2": "USD",
|
|
748
|
+
# "amount": "0.00098152",
|
|
749
|
+
# "buy": 59425993014,
|
|
750
|
+
# "order": 59425993014,
|
|
751
|
+
# "sell": 59425986168,
|
|
752
|
+
# "price": 19306.6,
|
|
753
|
+
# "type": "buy",
|
|
754
|
+
# "time": "2022-10-02T01:11:15.148Z",
|
|
755
|
+
# "balance": "0.00098152",
|
|
756
|
+
# "fee_amount": "0.05",
|
|
757
|
+
# "id": "59425993020"
|
|
758
|
+
# }
|
|
759
|
+
#
|
|
760
|
+
isTransaction = self.safe_value(order, 'd') is not None
|
|
761
|
+
remainsPrecision = self.safe_string(order, 'remains')
|
|
762
|
+
remaining = None
|
|
763
|
+
if remainsPrecision is not None:
|
|
764
|
+
remaining = self.currency_from_precision(market['base'], remainsPrecision)
|
|
765
|
+
amount = self.safe_string(order, 'amount')
|
|
766
|
+
if not isTransaction:
|
|
767
|
+
self.currency_from_precision(market['base'], amount)
|
|
768
|
+
baseId = self.safe_string(order, 'symbol')
|
|
769
|
+
quoteId = self.safe_string(order, 'symbol2')
|
|
770
|
+
pair = self.safe_value(order, 'pair')
|
|
771
|
+
if pair is not None:
|
|
772
|
+
baseId = self.safe_string(order, 'symbol1')
|
|
773
|
+
quoteId = self.safe_string(order, 'symbol2')
|
|
774
|
+
base = self.safe_currency_code(baseId)
|
|
775
|
+
quote = self.safe_currency_code(quoteId)
|
|
776
|
+
symbol = None
|
|
777
|
+
if base is not None and quote is not None:
|
|
778
|
+
symbol = base + '/' + quote
|
|
779
|
+
market = self.safe_market(symbol, market)
|
|
780
|
+
time = self.safe_integer(order, 'time', self.milliseconds())
|
|
781
|
+
timestamp = time
|
|
782
|
+
if isTransaction:
|
|
783
|
+
timestamp = self.parse8601(time)
|
|
784
|
+
canceled = self.safe_bool(order, 'cancel', False)
|
|
785
|
+
status = 'open'
|
|
786
|
+
if canceled:
|
|
787
|
+
status = 'canceled'
|
|
788
|
+
elif isTransaction:
|
|
789
|
+
status = 'closed'
|
|
790
|
+
parsedOrder: dict = {
|
|
791
|
+
'id': self.safe_string_2(order, 'id', 'order'),
|
|
792
|
+
'clientOrderId': None,
|
|
793
|
+
'info': order,
|
|
794
|
+
'timestamp': timestamp,
|
|
795
|
+
'datetime': self.iso8601(timestamp),
|
|
796
|
+
'lastTradeTimestamp': None,
|
|
797
|
+
'status': status,
|
|
798
|
+
'symbol': symbol,
|
|
799
|
+
'type': None,
|
|
800
|
+
'timeInForce': None,
|
|
801
|
+
'postOnly': None,
|
|
802
|
+
'side': self.safe_string(order, 'type'),
|
|
803
|
+
'price': self.safe_number(order, 'price'),
|
|
804
|
+
'stopPrice': None,
|
|
805
|
+
'triggerPrice': None,
|
|
806
|
+
'average': None,
|
|
807
|
+
'cost': None,
|
|
808
|
+
'amount': amount,
|
|
809
|
+
'filled': None,
|
|
810
|
+
'remaining': remaining,
|
|
811
|
+
'fee': {
|
|
812
|
+
'cost': self.safe_number_2(order, 'fee', 'fee_amount'),
|
|
813
|
+
'currency': quote,
|
|
814
|
+
'rate': None,
|
|
815
|
+
},
|
|
816
|
+
'trades': None,
|
|
817
|
+
}
|
|
818
|
+
if isTransaction:
|
|
819
|
+
parsedOrder['trades'] = self.parse_ws_trade(order, market)
|
|
820
|
+
return self.safe_order(parsedOrder, market)
|
|
821
|
+
|
|
822
|
+
def from_precision(self, amount, scale):
|
|
823
|
+
if amount is None:
|
|
824
|
+
return None
|
|
825
|
+
precise = Precise(amount)
|
|
826
|
+
precise.decimals = self.sum(precise.decimals, scale)
|
|
827
|
+
precise.reduce()
|
|
828
|
+
return str(precise)
|
|
829
|
+
|
|
830
|
+
def currency_from_precision(self, currency, amount):
|
|
831
|
+
scale = self.safe_integer(self.currencies[currency], 'precision', 0)
|
|
832
|
+
return self.from_precision(amount, scale)
|
|
833
|
+
|
|
834
|
+
def handle_orders_snapshot(self, client: Client, message):
|
|
835
|
+
#
|
|
836
|
+
# {
|
|
837
|
+
# "e": "open-orders",
|
|
838
|
+
# "data": [{
|
|
839
|
+
# "id": "59098421630",
|
|
840
|
+
# "time": "1664062285425",
|
|
841
|
+
# "type": "buy",
|
|
842
|
+
# "price": "18920",
|
|
843
|
+
# "amount": "0.00100000",
|
|
844
|
+
# "pending": "0.00100000"
|
|
845
|
+
# }],
|
|
846
|
+
# "oid": 1,
|
|
847
|
+
# "ok": "ok"
|
|
848
|
+
# }
|
|
849
|
+
#
|
|
850
|
+
symbol = self.safe_string(message, 'oid') # symbol is set in watchOrders
|
|
851
|
+
rawOrders = self.safe_value(message, 'data', [])
|
|
852
|
+
myOrders = self.orders
|
|
853
|
+
if self.orders is None:
|
|
854
|
+
limit = self.safe_integer(self.options, 'ordersLimit', 1000)
|
|
855
|
+
myOrders = ArrayCacheBySymbolById(limit)
|
|
856
|
+
for i in range(0, len(rawOrders)):
|
|
857
|
+
rawOrder = rawOrders[i]
|
|
858
|
+
market = self.safe_market(symbol)
|
|
859
|
+
order = self.parse_order(rawOrder, market)
|
|
860
|
+
order['status'] = 'open'
|
|
861
|
+
myOrders.append(order)
|
|
862
|
+
self.orders = myOrders
|
|
863
|
+
messageHash = 'orders:' + symbol
|
|
864
|
+
ordersLength = len(myOrders)
|
|
865
|
+
if ordersLength > 0:
|
|
866
|
+
client.resolve(myOrders, messageHash)
|
|
867
|
+
|
|
868
|
+
async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
|
869
|
+
"""
|
|
870
|
+
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
|
871
|
+
:see: https://cex.io/websocket-api#orderbook-subscribe
|
|
872
|
+
:param str symbol: unified symbol of the market to fetch the order book for
|
|
873
|
+
:param int [limit]: the maximum amount of order book entries to return
|
|
874
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
875
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
|
876
|
+
"""
|
|
877
|
+
await self.load_markets()
|
|
878
|
+
await self.authenticate()
|
|
879
|
+
market = self.market(symbol)
|
|
880
|
+
symbol = market['symbol']
|
|
881
|
+
url = self.urls['api']['ws']
|
|
882
|
+
messageHash = 'orderbook:' + symbol
|
|
883
|
+
depth = 0 if (limit is None) else limit
|
|
884
|
+
subscribe: dict = {
|
|
885
|
+
'e': 'order-book-subscribe',
|
|
886
|
+
'data': {
|
|
887
|
+
'pair': [
|
|
888
|
+
market['baseId'],
|
|
889
|
+
market['quoteId'],
|
|
890
|
+
],
|
|
891
|
+
'subscribe': True,
|
|
892
|
+
'depth': depth,
|
|
893
|
+
},
|
|
894
|
+
'oid': self.request_id(),
|
|
895
|
+
}
|
|
896
|
+
request = self.deep_extend(subscribe, params)
|
|
897
|
+
orderbook = await self.watch(url, messageHash, request, messageHash)
|
|
898
|
+
return orderbook.limit()
|
|
899
|
+
|
|
900
|
+
def handle_order_book_snapshot(self, client: Client, message):
|
|
901
|
+
#
|
|
902
|
+
# {
|
|
903
|
+
# "e": "order-book-subscribe",
|
|
904
|
+
# "data": {
|
|
905
|
+
# "timestamp": 1663762032,
|
|
906
|
+
# "timestamp_ms": 1663762031680,
|
|
907
|
+
# "bids": [
|
|
908
|
+
# [241.947, 155.91626],
|
|
909
|
+
# [241, 154],
|
|
910
|
+
# ],
|
|
911
|
+
# "asks": [
|
|
912
|
+
# [242.947, 155.91626],
|
|
913
|
+
# [243, 154], ],
|
|
914
|
+
# "pair": "BTC:USDT",
|
|
915
|
+
# "id": 616267120,
|
|
916
|
+
# "sell_total": "13.59066946",
|
|
917
|
+
# "buy_total": "163553.625948"
|
|
918
|
+
# },
|
|
919
|
+
# "oid": "1",
|
|
920
|
+
# "ok": "ok"
|
|
921
|
+
# }
|
|
922
|
+
#
|
|
923
|
+
data = self.safe_value(message, 'data', {})
|
|
924
|
+
pair = self.safe_string(data, 'pair')
|
|
925
|
+
symbol = self.pair_to_symbol(pair)
|
|
926
|
+
messageHash = 'orderbook:' + symbol
|
|
927
|
+
timestamp = self.safe_integer_2(data, 'timestamp_ms', 'timestamp')
|
|
928
|
+
incrementalId = self.safe_integer(data, 'id')
|
|
929
|
+
orderbook = self.order_book({})
|
|
930
|
+
snapshot = self.parse_order_book(data, symbol, timestamp, 'bids', 'asks')
|
|
931
|
+
snapshot['nonce'] = incrementalId
|
|
932
|
+
orderbook.reset(snapshot)
|
|
933
|
+
self.options['orderbook'][symbol] = {
|
|
934
|
+
'incrementalId': incrementalId,
|
|
935
|
+
}
|
|
936
|
+
self.orderbooks[symbol] = orderbook
|
|
937
|
+
client.resolve(orderbook, messageHash)
|
|
938
|
+
|
|
939
|
+
def pair_to_symbol(self, pair):
|
|
940
|
+
parts = pair.split(':')
|
|
941
|
+
baseId = self.safe_string(parts, 0)
|
|
942
|
+
quoteId = self.safe_string(parts, 1)
|
|
943
|
+
base = self.safe_currency_code(baseId)
|
|
944
|
+
quote = self.safe_currency_code(quoteId)
|
|
945
|
+
symbol = base + '/' + quote
|
|
946
|
+
return symbol
|
|
947
|
+
|
|
948
|
+
def handle_order_book_update(self, client: Client, message):
|
|
949
|
+
#
|
|
950
|
+
# {
|
|
951
|
+
# "e": "md_update",
|
|
952
|
+
# "data": {
|
|
953
|
+
# "id": 616267121,
|
|
954
|
+
# "pair": "BTC:USDT",
|
|
955
|
+
# "time": 1663762031719,
|
|
956
|
+
# "bids": [],
|
|
957
|
+
# "asks": [
|
|
958
|
+
# [122, 23]
|
|
959
|
+
# ]
|
|
960
|
+
# }
|
|
961
|
+
# }
|
|
962
|
+
#
|
|
963
|
+
data = self.safe_value(message, 'data', {})
|
|
964
|
+
incrementalId = self.safe_number(data, 'id')
|
|
965
|
+
pair = self.safe_string(data, 'pair', '')
|
|
966
|
+
symbol = self.pair_to_symbol(pair)
|
|
967
|
+
storedOrderBook = self.safe_value(self.orderbooks, symbol)
|
|
968
|
+
messageHash = 'orderbook:' + symbol
|
|
969
|
+
if incrementalId != storedOrderBook['nonce'] + 1:
|
|
970
|
+
del client.subscriptions[messageHash]
|
|
971
|
+
client.reject(self.id + ' watchOrderBook() skipped a message', messageHash)
|
|
972
|
+
timestamp = self.safe_integer(data, 'time')
|
|
973
|
+
asks = self.safe_value(data, 'asks', [])
|
|
974
|
+
bids = self.safe_value(data, 'bids', [])
|
|
975
|
+
self.handle_deltas(storedOrderBook['asks'], asks)
|
|
976
|
+
self.handle_deltas(storedOrderBook['bids'], bids)
|
|
977
|
+
storedOrderBook['timestamp'] = timestamp
|
|
978
|
+
storedOrderBook['datetime'] = self.iso8601(timestamp)
|
|
979
|
+
storedOrderBook['nonce'] = incrementalId
|
|
980
|
+
client.resolve(storedOrderBook, messageHash)
|
|
981
|
+
|
|
982
|
+
def handle_delta(self, bookside, delta):
|
|
983
|
+
bidAsk = self.parse_bid_ask(delta, 0, 1)
|
|
984
|
+
bookside.storeArray(bidAsk)
|
|
985
|
+
|
|
986
|
+
def handle_deltas(self, bookside, deltas):
|
|
987
|
+
for i in range(0, len(deltas)):
|
|
988
|
+
self.handle_delta(bookside, deltas[i])
|
|
989
|
+
|
|
990
|
+
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
|
991
|
+
"""
|
|
992
|
+
:see: https://cex.io/websocket-api#minute-data
|
|
993
|
+
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market. It will return the last 120 minutes with the selected timeframe and then 1m candle updates after that.
|
|
994
|
+
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
|
995
|
+
:param str timeframe: the length of time each candle represents.
|
|
996
|
+
:param int [since]: timestamp in ms of the earliest candle to fetch
|
|
997
|
+
:param int [limit]: the maximum amount of candles to fetch
|
|
998
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
999
|
+
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
|
1000
|
+
"""
|
|
1001
|
+
await self.load_markets()
|
|
1002
|
+
market = self.market(symbol)
|
|
1003
|
+
symbol = market['symbol']
|
|
1004
|
+
messageHash = 'ohlcv:' + symbol
|
|
1005
|
+
url = self.urls['api']['ws']
|
|
1006
|
+
request: dict = {
|
|
1007
|
+
'e': 'init-ohlcv',
|
|
1008
|
+
'i': timeframe,
|
|
1009
|
+
'rooms': [
|
|
1010
|
+
'pair-' + market['baseId'] + '-' + market['quoteId'],
|
|
1011
|
+
],
|
|
1012
|
+
}
|
|
1013
|
+
ohlcv = await self.watch(url, messageHash, self.extend(request, params), messageHash)
|
|
1014
|
+
if self.newUpdates:
|
|
1015
|
+
limit = ohlcv.getLimit(symbol, limit)
|
|
1016
|
+
return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
|
|
1017
|
+
|
|
1018
|
+
def handle_init_ohlcv(self, client: Client, message):
|
|
1019
|
+
#
|
|
1020
|
+
# {
|
|
1021
|
+
# "e": "init-ohlcv-data",
|
|
1022
|
+
# "data": [
|
|
1023
|
+
# [
|
|
1024
|
+
# 1663660680,
|
|
1025
|
+
# "19396.4",
|
|
1026
|
+
# "19396.4",
|
|
1027
|
+
# "19396.4",
|
|
1028
|
+
# "19396.4",
|
|
1029
|
+
# "1262861"
|
|
1030
|
+
# ],
|
|
1031
|
+
# ...
|
|
1032
|
+
# ],
|
|
1033
|
+
# "pair": "BTC:USDT"
|
|
1034
|
+
# }
|
|
1035
|
+
#
|
|
1036
|
+
pair = self.safe_string(message, 'pair')
|
|
1037
|
+
parts = pair.split(':')
|
|
1038
|
+
baseId = self.safe_string(parts, 0)
|
|
1039
|
+
quoteId = self.safe_string(parts, 1)
|
|
1040
|
+
base = self.safe_currency_code(baseId)
|
|
1041
|
+
quote = self.safe_currency_code(quoteId)
|
|
1042
|
+
symbol = base + '/' + quote
|
|
1043
|
+
market = self.safe_market(symbol)
|
|
1044
|
+
messageHash = 'ohlcv:' + symbol
|
|
1045
|
+
data = self.safe_value(message, 'data', [])
|
|
1046
|
+
limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
|
|
1047
|
+
stored = ArrayCacheByTimestamp(limit)
|
|
1048
|
+
sorted = self.sort_by(data, 0)
|
|
1049
|
+
for i in range(0, len(sorted)):
|
|
1050
|
+
stored.append(self.parse_ohlcv(sorted[i], market))
|
|
1051
|
+
if not (symbol in self.ohlcvs):
|
|
1052
|
+
self.ohlcvs[symbol] = {}
|
|
1053
|
+
self.ohlcvs[symbol]['unknown'] = stored
|
|
1054
|
+
client.resolve(stored, messageHash)
|
|
1055
|
+
|
|
1056
|
+
def handle_ohlcv24(self, client: Client, message):
|
|
1057
|
+
#
|
|
1058
|
+
# {
|
|
1059
|
+
# "e": "ohlcv24",
|
|
1060
|
+
# "data": ['18793.2', '19630', '18793.2', "19104.1", "314157273"],
|
|
1061
|
+
# "pair": "BTC:USDT"
|
|
1062
|
+
# }
|
|
1063
|
+
#
|
|
1064
|
+
return message
|
|
1065
|
+
|
|
1066
|
+
def handle_ohlcv1m(self, client: Client, message):
|
|
1067
|
+
#
|
|
1068
|
+
# {
|
|
1069
|
+
# "e": "ohlcv1m",
|
|
1070
|
+
# "data": {
|
|
1071
|
+
# "pair": "BTC:USD",
|
|
1072
|
+
# "time": "1665436800",
|
|
1073
|
+
# "o": "19279.6",
|
|
1074
|
+
# "h": "19279.6",
|
|
1075
|
+
# "l": "19266.7",
|
|
1076
|
+
# "c": "19266.7",
|
|
1077
|
+
# "v": 3343884,
|
|
1078
|
+
# "d": 3343884
|
|
1079
|
+
# }
|
|
1080
|
+
# }
|
|
1081
|
+
#
|
|
1082
|
+
data = self.safe_value(message, 'data', {})
|
|
1083
|
+
pair = self.safe_string(data, 'pair')
|
|
1084
|
+
symbol = self.pair_to_symbol(pair)
|
|
1085
|
+
messageHash = 'ohlcv:' + symbol
|
|
1086
|
+
ohlcv = [
|
|
1087
|
+
self.safe_timestamp(data, 'time'),
|
|
1088
|
+
self.safe_number(data, 'o'),
|
|
1089
|
+
self.safe_number(data, 'h'),
|
|
1090
|
+
self.safe_number(data, 'l'),
|
|
1091
|
+
self.safe_number(data, 'c'),
|
|
1092
|
+
self.safe_number(data, 'v'),
|
|
1093
|
+
]
|
|
1094
|
+
stored = self.safe_value(self.ohlcvs, symbol)
|
|
1095
|
+
stored.append(ohlcv)
|
|
1096
|
+
client.resolve(stored, messageHash)
|
|
1097
|
+
|
|
1098
|
+
def handle_ohlcv(self, client: Client, message):
|
|
1099
|
+
#
|
|
1100
|
+
# {
|
|
1101
|
+
# "e": "ohlcv",
|
|
1102
|
+
# "data": [
|
|
1103
|
+
# [1665461100, '19068.2', '19068.2', '19068.2', "19068.2", 268478]
|
|
1104
|
+
# ],
|
|
1105
|
+
# "pair": "BTC:USD"
|
|
1106
|
+
# }
|
|
1107
|
+
#
|
|
1108
|
+
data = self.safe_value(message, 'data', [])
|
|
1109
|
+
pair = self.safe_string(message, 'pair')
|
|
1110
|
+
symbol = self.pair_to_symbol(pair)
|
|
1111
|
+
messageHash = 'ohlcv:' + symbol
|
|
1112
|
+
# stored = self.safe_value(self.ohlcvs, symbol)
|
|
1113
|
+
stored = self.ohlcvs[symbol]['unknown']
|
|
1114
|
+
for i in range(0, len(data)):
|
|
1115
|
+
ohlcv = [
|
|
1116
|
+
self.safe_timestamp(data[i], 0),
|
|
1117
|
+
self.safe_number(data[i], 1),
|
|
1118
|
+
self.safe_number(data[i], 2),
|
|
1119
|
+
self.safe_number(data[i], 3),
|
|
1120
|
+
self.safe_number(data[i], 4),
|
|
1121
|
+
self.safe_number(data[i], 5),
|
|
1122
|
+
]
|
|
1123
|
+
stored.append(ohlcv)
|
|
1124
|
+
dataLength = len(data)
|
|
1125
|
+
if dataLength > 0:
|
|
1126
|
+
client.resolve(stored, messageHash)
|
|
1127
|
+
|
|
1128
|
+
async def fetch_order_ws(self, id: str, symbol: Str = None, params={}):
|
|
1129
|
+
"""
|
|
1130
|
+
fetches information on an order made by the user
|
|
1131
|
+
:see: https://docs.cex.io/#ws-api-get-order
|
|
1132
|
+
:param str symbol: not used by cex fetchOrder
|
|
1133
|
+
:param dict [params]: extra parameters specific to the cex api endpoint
|
|
1134
|
+
:returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
|
1135
|
+
"""
|
|
1136
|
+
await self.load_markets()
|
|
1137
|
+
await self.authenticate()
|
|
1138
|
+
market = None
|
|
1139
|
+
if symbol is not None:
|
|
1140
|
+
market = self.market(symbol)
|
|
1141
|
+
data = self.extend({
|
|
1142
|
+
'order_id': str(id),
|
|
1143
|
+
}, params)
|
|
1144
|
+
url = self.urls['api']['ws']
|
|
1145
|
+
messageHash = self.request_id()
|
|
1146
|
+
request: dict = {
|
|
1147
|
+
'e': 'get-order',
|
|
1148
|
+
'oid': messageHash,
|
|
1149
|
+
'data': data,
|
|
1150
|
+
}
|
|
1151
|
+
response = await self.watch(url, messageHash, request, messageHash)
|
|
1152
|
+
return self.parse_order(response, market)
|
|
1153
|
+
|
|
1154
|
+
async def fetch_open_orders_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
1155
|
+
"""
|
|
1156
|
+
:see: https://docs.cex.io/#ws-api-open-orders
|
|
1157
|
+
fetch all unfilled currently open orders
|
|
1158
|
+
:param str symbol: unified market symbol
|
|
1159
|
+
:param int [since]: the earliest time in ms to fetch open orders for
|
|
1160
|
+
:param int [limit]: the maximum number of open orders structures to retrieve
|
|
1161
|
+
:param dict [params]: extra parameters specific to the cex api endpoint
|
|
1162
|
+
:returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
|
1163
|
+
"""
|
|
1164
|
+
if symbol is None:
|
|
1165
|
+
raise ArgumentsRequired(self.id + 'fetchOpenOrdersWs requires a symbol.')
|
|
1166
|
+
await self.load_markets()
|
|
1167
|
+
await self.authenticate()
|
|
1168
|
+
market = self.market(symbol)
|
|
1169
|
+
url = self.urls['api']['ws']
|
|
1170
|
+
messageHash = self.request_id()
|
|
1171
|
+
data = self.extend({
|
|
1172
|
+
'pair': [market['baseId'], market['quoteId']],
|
|
1173
|
+
}, params)
|
|
1174
|
+
request: dict = {
|
|
1175
|
+
'e': 'open-orders',
|
|
1176
|
+
'oid': messageHash,
|
|
1177
|
+
'data': data,
|
|
1178
|
+
}
|
|
1179
|
+
response = await self.watch(url, messageHash, request, messageHash)
|
|
1180
|
+
return self.parse_orders(response, market, since, limit, params)
|
|
1181
|
+
|
|
1182
|
+
async def create_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> Order:
|
|
1183
|
+
"""
|
|
1184
|
+
:see: https://docs.cex.io/#ws-api-order-placement
|
|
1185
|
+
create a trade order
|
|
1186
|
+
:param str symbol: unified symbol of the market to create an order in
|
|
1187
|
+
:param str type: 'market' or 'limit'
|
|
1188
|
+
:param str side: 'buy' or 'sell'
|
|
1189
|
+
:param float amount: how much of currency you want to trade in units of base currency
|
|
1190
|
+
:param float price: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
|
1191
|
+
:param dict [params]: extra parameters specific to the kraken api endpoint
|
|
1192
|
+
:param boolean [params.maker_only]: Optional, maker only places an order only if offers best sell(<= max) or buy(>= max) price for self pair, if not order placement will be rejected with an error - "Order is not maker"
|
|
1193
|
+
:returns dict: an `order structure <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
|
|
1194
|
+
"""
|
|
1195
|
+
if price is None:
|
|
1196
|
+
raise BadRequest(self.id + ' createOrderWs requires a price argument')
|
|
1197
|
+
await self.load_markets()
|
|
1198
|
+
await self.authenticate()
|
|
1199
|
+
market = self.market(symbol)
|
|
1200
|
+
url = self.urls['api']['ws']
|
|
1201
|
+
messageHash = self.request_id()
|
|
1202
|
+
data = self.extend({
|
|
1203
|
+
'pair': [market['baseId'], market['quoteId']],
|
|
1204
|
+
'amount': amount,
|
|
1205
|
+
'price': price,
|
|
1206
|
+
'type': side,
|
|
1207
|
+
}, params)
|
|
1208
|
+
request: dict = {
|
|
1209
|
+
'e': 'place-order',
|
|
1210
|
+
'oid': messageHash,
|
|
1211
|
+
'data': data,
|
|
1212
|
+
}
|
|
1213
|
+
rawOrder = await self.watch(url, messageHash, request, messageHash)
|
|
1214
|
+
return self.parse_order(rawOrder, market)
|
|
1215
|
+
|
|
1216
|
+
async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}) -> Order:
|
|
1217
|
+
"""
|
|
1218
|
+
edit a trade order
|
|
1219
|
+
:see: https://docs.cex.io/#ws-api-cancel-replace
|
|
1220
|
+
:param str id: order id
|
|
1221
|
+
:param str symbol: unified symbol of the market to create an order in
|
|
1222
|
+
:param str type: 'market' or 'limit'
|
|
1223
|
+
:param str side: 'buy' or 'sell'
|
|
1224
|
+
:param float amount: how much of the currency you want to trade in units of the base currency
|
|
1225
|
+
:param float|None [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
|
1226
|
+
:param dict [params]: extra parameters specific to the cex api endpoint
|
|
1227
|
+
:returns dict: an `order structure <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
|
|
1228
|
+
"""
|
|
1229
|
+
if amount is None:
|
|
1230
|
+
raise ArgumentsRequired(self.id + ' editOrder() requires a amount argument')
|
|
1231
|
+
if price is None:
|
|
1232
|
+
raise ArgumentsRequired(self.id + ' editOrder() requires a price argument')
|
|
1233
|
+
await self.load_markets()
|
|
1234
|
+
await self.authenticate()
|
|
1235
|
+
market = self.market(symbol)
|
|
1236
|
+
data = self.extend({
|
|
1237
|
+
'pair': [market['baseId'], market['quoteId']],
|
|
1238
|
+
'type': side,
|
|
1239
|
+
'amount': amount,
|
|
1240
|
+
'price': price,
|
|
1241
|
+
'order_id': id,
|
|
1242
|
+
}, params)
|
|
1243
|
+
messageHash = self.request_id()
|
|
1244
|
+
url = self.urls['api']['ws']
|
|
1245
|
+
request: dict = {
|
|
1246
|
+
'e': 'cancel-replace-order',
|
|
1247
|
+
'oid': messageHash,
|
|
1248
|
+
'data': data,
|
|
1249
|
+
}
|
|
1250
|
+
response = await self.watch(url, messageHash, request, messageHash, messageHash)
|
|
1251
|
+
return self.parse_order(response, market)
|
|
1252
|
+
|
|
1253
|
+
async def cancel_order_ws(self, id: str, symbol: Str = None, params={}):
|
|
1254
|
+
"""
|
|
1255
|
+
:see: https://docs.cex.io/#ws-api-order-cancel
|
|
1256
|
+
cancels an open order
|
|
1257
|
+
:param str id: order id
|
|
1258
|
+
:param str symbol: not used by cex cancelOrder()
|
|
1259
|
+
:param dict [params]: extra parameters specific to the cex api endpoint
|
|
1260
|
+
:returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
|
1261
|
+
"""
|
|
1262
|
+
await self.load_markets()
|
|
1263
|
+
await self.authenticate()
|
|
1264
|
+
market = None
|
|
1265
|
+
if symbol is not None:
|
|
1266
|
+
market = self.market(symbol)
|
|
1267
|
+
data = self.extend({
|
|
1268
|
+
'order_id': id,
|
|
1269
|
+
}, params)
|
|
1270
|
+
messageHash = self.request_id()
|
|
1271
|
+
url = self.urls['api']['ws']
|
|
1272
|
+
request: dict = {
|
|
1273
|
+
'e': 'cancel-order',
|
|
1274
|
+
'oid': messageHash,
|
|
1275
|
+
'data': data,
|
|
1276
|
+
}
|
|
1277
|
+
response = await self.watch(url, messageHash, request, messageHash, messageHash)
|
|
1278
|
+
return self.parse_order(response, market)
|
|
1279
|
+
|
|
1280
|
+
async def cancel_orders_ws(self, ids: List[str], symbol: Str = None, params={}):
|
|
1281
|
+
"""
|
|
1282
|
+
cancel multiple orders
|
|
1283
|
+
:see: https://docs.cex.io/#ws-api-mass-cancel-place
|
|
1284
|
+
:param str[] ids: order ids
|
|
1285
|
+
:param str symbol: not used by cex cancelOrders()
|
|
1286
|
+
:param dict [params]: extra parameters specific to the cex api endpoint
|
|
1287
|
+
:returns dict: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
|
1288
|
+
"""
|
|
1289
|
+
if symbol is not None:
|
|
1290
|
+
raise BadRequest(self.id + ' cancelOrderWs does not allow filtering by symbol')
|
|
1291
|
+
await self.load_markets()
|
|
1292
|
+
await self.authenticate()
|
|
1293
|
+
messageHash = self.request_id()
|
|
1294
|
+
data = self.extend({
|
|
1295
|
+
'cancel-orders': ids,
|
|
1296
|
+
}, params)
|
|
1297
|
+
url = self.urls['api']['ws']
|
|
1298
|
+
request: dict = {
|
|
1299
|
+
'e': 'mass-cancel-place-orders',
|
|
1300
|
+
'oid': messageHash,
|
|
1301
|
+
'data': data,
|
|
1302
|
+
}
|
|
1303
|
+
response = await self.watch(url, messageHash, request, messageHash, messageHash)
|
|
1304
|
+
#
|
|
1305
|
+
# {
|
|
1306
|
+
# "cancel-orders": [{
|
|
1307
|
+
# "order_id": 69202557979,
|
|
1308
|
+
# "fremains": "0.15000000"
|
|
1309
|
+
# }],
|
|
1310
|
+
# "place-orders": [],
|
|
1311
|
+
# "placed-cancelled": []
|
|
1312
|
+
# }
|
|
1313
|
+
#
|
|
1314
|
+
canceledOrders = self.safe_value(response, 'cancel-orders')
|
|
1315
|
+
return self.parse_orders(canceledOrders, None, None, None, params)
|
|
1316
|
+
|
|
1317
|
+
def resolve_data(self, client: Client, message):
|
|
1318
|
+
#
|
|
1319
|
+
# "e": "open-orders",
|
|
1320
|
+
# "data": [
|
|
1321
|
+
# {
|
|
1322
|
+
# "id": "2477098",
|
|
1323
|
+
# "time": "1435927928618",
|
|
1324
|
+
# "type": "buy",
|
|
1325
|
+
# "price": "241.9477",
|
|
1326
|
+
# "amount": "0.02000000",
|
|
1327
|
+
# "pending": "0.02000000"
|
|
1328
|
+
# },
|
|
1329
|
+
# ...
|
|
1330
|
+
# ],
|
|
1331
|
+
# "oid": "1435927928274_9_open-orders",
|
|
1332
|
+
# "ok": "ok"
|
|
1333
|
+
# }
|
|
1334
|
+
#
|
|
1335
|
+
data = self.safe_value(message, 'data')
|
|
1336
|
+
messageHash = self.safe_string(message, 'oid')
|
|
1337
|
+
client.resolve(data, messageHash)
|
|
1338
|
+
|
|
1339
|
+
def handle_connected(self, client: Client, message):
|
|
1340
|
+
#
|
|
1341
|
+
# {
|
|
1342
|
+
# "e": "connected"
|
|
1343
|
+
# }
|
|
1344
|
+
#
|
|
1345
|
+
return message
|
|
1346
|
+
|
|
1347
|
+
def handle_error_message(self, client: Client, message):
|
|
1348
|
+
#
|
|
1349
|
+
# {
|
|
1350
|
+
# "e": "get-balance",
|
|
1351
|
+
# "data": {error: "Please Login"},
|
|
1352
|
+
# "oid": 1,
|
|
1353
|
+
# "ok": "error"
|
|
1354
|
+
# }
|
|
1355
|
+
#
|
|
1356
|
+
try:
|
|
1357
|
+
data = self.safe_value(message, 'data', {})
|
|
1358
|
+
error = self.safe_string(data, 'error')
|
|
1359
|
+
event = self.safe_string(message, 'e', '')
|
|
1360
|
+
feedback = self.id + ' ' + event + ' ' + error
|
|
1361
|
+
self.throw_exactly_matched_exception(self.exceptions['exact'], error, feedback)
|
|
1362
|
+
self.throw_broadly_matched_exception(self.exceptions['broad'], error, feedback)
|
|
1363
|
+
raise ExchangeError(feedback)
|
|
1364
|
+
except Exception as error:
|
|
1365
|
+
messageHash = self.safe_string(message, 'oid')
|
|
1366
|
+
future = self.safe_value(client['futures'], messageHash)
|
|
1367
|
+
if future is not None:
|
|
1368
|
+
client.reject(error, messageHash)
|
|
1369
|
+
else:
|
|
1370
|
+
raise error
|
|
1371
|
+
|
|
1372
|
+
def handle_message(self, client: Client, message):
|
|
1373
|
+
ok = self.safe_string(message, 'ok')
|
|
1374
|
+
if ok == 'error':
|
|
1375
|
+
self.handle_error_message(client, message)
|
|
1376
|
+
return
|
|
1377
|
+
event = self.safe_string(message, 'e')
|
|
1378
|
+
handlers: dict = {
|
|
1379
|
+
'auth': self.handle_authentication_message,
|
|
1380
|
+
'connected': self.handle_connected,
|
|
1381
|
+
'tick': self.handle_ticker,
|
|
1382
|
+
'ticker': self.handle_ticker,
|
|
1383
|
+
'init-ohlcv-data': self.handle_init_ohlcv,
|
|
1384
|
+
'ohlcv24': self.handle_ohlcv24,
|
|
1385
|
+
'ohlcv1m': self.handle_ohlcv1m,
|
|
1386
|
+
'ohlcv': self.handle_ohlcv,
|
|
1387
|
+
'get-balance': self.handle_balance,
|
|
1388
|
+
'order-book-subscribe': self.handle_order_book_snapshot,
|
|
1389
|
+
'md_update': self.handle_order_book_update,
|
|
1390
|
+
'open-orders': self.resolve_data,
|
|
1391
|
+
'order': self.handle_order_update,
|
|
1392
|
+
'history-update': self.handle_trade,
|
|
1393
|
+
'history': self.handle_trades_snapshot,
|
|
1394
|
+
'tx': self.handle_transaction,
|
|
1395
|
+
'place-order': self.resolve_data,
|
|
1396
|
+
'cancel-replace-order': self.resolve_data,
|
|
1397
|
+
'cancel-order': self.resolve_data,
|
|
1398
|
+
'mass-cancel-place-orders': self.resolve_data,
|
|
1399
|
+
'get-order': self.resolve_data,
|
|
1400
|
+
}
|
|
1401
|
+
handler = self.safe_value(handlers, event)
|
|
1402
|
+
if handler is not None:
|
|
1403
|
+
handler(client, message)
|
|
1404
|
+
|
|
1405
|
+
def handle_authentication_message(self, client: Client, message):
|
|
1406
|
+
#
|
|
1407
|
+
# {
|
|
1408
|
+
# "e": "auth",
|
|
1409
|
+
# "data": {
|
|
1410
|
+
# "ok": "ok"
|
|
1411
|
+
# },
|
|
1412
|
+
# "ok": "ok",
|
|
1413
|
+
# "timestamp":1448034593
|
|
1414
|
+
# }
|
|
1415
|
+
#
|
|
1416
|
+
future = self.safe_value(client.futures, 'authenticated')
|
|
1417
|
+
if future is not None:
|
|
1418
|
+
future.resolve(True)
|
|
1419
|
+
|
|
1420
|
+
async def authenticate(self, params={}):
|
|
1421
|
+
url = self.urls['api']['ws']
|
|
1422
|
+
client = self.client(url)
|
|
1423
|
+
messageHash = 'authenticated'
|
|
1424
|
+
future = client.future('authenticated')
|
|
1425
|
+
authenticated = self.safe_value(client.subscriptions, messageHash)
|
|
1426
|
+
if authenticated is None:
|
|
1427
|
+
self.check_required_credentials()
|
|
1428
|
+
nonce = str(self.seconds())
|
|
1429
|
+
auth = nonce + self.apiKey
|
|
1430
|
+
signature = self.hmac(self.encode(auth), self.encode(self.secret), hashlib.sha256)
|
|
1431
|
+
request: dict = {
|
|
1432
|
+
'e': 'auth',
|
|
1433
|
+
'auth': {
|
|
1434
|
+
'key': self.apiKey,
|
|
1435
|
+
'signature': signature.upper(),
|
|
1436
|
+
'timestamp': nonce,
|
|
1437
|
+
},
|
|
1438
|
+
}
|
|
1439
|
+
await self.watch(url, messageHash, self.extend(request, params), messageHash)
|
|
1440
|
+
return await future
|