ccxt-ir 4.3.46.0.3__py2.py3-none-any.whl → 4.5.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ccxt/__init__.py +39 -35
- ccxt/abantether.py +8 -8
- ccxt/abstract/alpaca.py +4 -0
- ccxt/abstract/apex.py +31 -0
- ccxt/abstract/bigone.py +1 -1
- ccxt/abstract/binance.py +106 -48
- ccxt/abstract/binancecoinm.py +106 -48
- ccxt/abstract/binanceus.py +141 -83
- ccxt/abstract/binanceusdm.py +106 -48
- ccxt/abstract/bingx.py +50 -1
- ccxt/abstract/bitbank.py +5 -0
- ccxt/abstract/bitfinex.py +136 -65
- ccxt/abstract/bitflyer.py +1 -0
- ccxt/abstract/bitget.py +67 -0
- ccxt/abstract/bitmart.py +19 -1
- ccxt/abstract/bitopro.py +1 -0
- ccxt/abstract/bitrue.py +68 -68
- ccxt/abstract/bitstamp.py +1 -0
- ccxt/abstract/blofin.py +30 -0
- ccxt/abstract/btcbox.py +2 -0
- ccxt/abstract/bybit.py +28 -13
- ccxt/abstract/cex.py +28 -29
- ccxt/abstract/coinbaseexchange.py +1 -0
- ccxt/abstract/coinbaseinternational.py +1 -1
- ccxt/abstract/cryptocom.py +16 -0
- ccxt/abstract/cryptomus.py +20 -0
- ccxt/abstract/defx.py +69 -0
- ccxt/abstract/deribit.py +1 -0
- ccxt/abstract/derive.py +117 -0
- ccxt/abstract/digifinex.py +1 -0
- ccxt/abstract/ellipx.py +25 -0
- ccxt/abstract/foxbit.py +26 -0
- ccxt/abstract/gate.py +19 -0
- ccxt/abstract/gateio.py +19 -0
- ccxt/abstract/gemini.py +1 -0
- ccxt/abstract/hibachi.py +26 -0
- ccxt/abstract/hyperliquid.py +1 -1
- ccxt/abstract/independentreserve.py +6 -0
- ccxt/abstract/kraken.py +1 -0
- ccxt/abstract/krakenfutures.py +4 -0
- ccxt/abstract/kucoin.py +10 -0
- ccxt/abstract/kucoinfutures.py +18 -0
- ccxt/abstract/lbank.py +2 -1
- ccxt/abstract/luno.py +1 -0
- ccxt/abstract/mexc.py +2 -0
- ccxt/abstract/modetrade.py +119 -0
- ccxt/abstract/myokx.py +349 -0
- ccxt/abstract/oceanex.py +5 -0
- ccxt/abstract/okx.py +25 -0
- ccxt/abstract/okxus.py +349 -0
- ccxt/abstract/onetrading.py +0 -12
- ccxt/abstract/paradex.py +23 -0
- ccxt/abstract/phemex.py +2 -0
- ccxt/abstract/poloniex.py +36 -0
- ccxt/abstract/tradeogre.py +3 -1
- ccxt/abstract/upbit.py +51 -34
- ccxt/abstract/whitebit.py +16 -0
- ccxt/abstract/woo.py +64 -6
- ccxt/abstract/xt.py +10 -5
- ccxt/afratether.py +7 -7
- ccxt/alpaca.py +828 -51
- ccxt/apex.py +1875 -0
- ccxt/arzinja.py +7 -7
- ccxt/arzplus.py +9 -9
- ccxt/ascendex.py +501 -306
- ccxt/async_support/__init__.py +39 -35
- ccxt/async_support/abantether.py +8 -8
- ccxt/async_support/afratether.py +9 -9
- ccxt/async_support/alpaca.py +828 -51
- ccxt/async_support/apex.py +1875 -0
- ccxt/async_support/arzinja.py +10 -10
- ccxt/async_support/arzplus.py +12 -12
- ccxt/async_support/ascendex.py +502 -306
- ccxt/async_support/base/exchange.py +303 -89
- ccxt/async_support/base/ws/cache.py +9 -3
- ccxt/async_support/base/ws/client.py +173 -38
- ccxt/async_support/base/ws/future.py +25 -37
- ccxt/async_support/bequant.py +5 -3
- ccxt/async_support/bigone.py +279 -144
- ccxt/async_support/binance.py +2347 -1158
- ccxt/async_support/binancecoinm.py +9 -3
- ccxt/async_support/binanceus.py +17 -3
- ccxt/async_support/binanceusdm.py +9 -4
- ccxt/async_support/bingx.py +2962 -920
- ccxt/async_support/bit2c.py +147 -27
- ccxt/async_support/bitbank.py +151 -23
- ccxt/async_support/bitbns.py +104 -30
- ccxt/async_support/bitfinex.py +3291 -1113
- ccxt/async_support/bitflyer.py +202 -27
- ccxt/async_support/bitget.py +3683 -1538
- ccxt/async_support/bithumb.py +195 -38
- ccxt/async_support/bitimen.py +12 -12
- ccxt/async_support/bitir.py +38 -38
- ccxt/async_support/bitmart.py +1288 -350
- ccxt/async_support/bitmex.py +260 -75
- ccxt/async_support/bitopro.py +262 -62
- ccxt/async_support/bitpin.py +17 -16
- ccxt/async_support/bitrue.py +459 -290
- ccxt/async_support/bitso.py +199 -54
- ccxt/async_support/bitstamp.py +230 -96
- ccxt/async_support/bitteam.py +167 -25
- ccxt/async_support/{huobijp.py → bittrade.py} +158 -30
- ccxt/async_support/bitvavo.py +213 -49
- ccxt/async_support/blockchaincom.py +160 -46
- ccxt/async_support/blofin.py +502 -120
- ccxt/async_support/btcalpha.py +169 -31
- ccxt/async_support/btcbox.py +292 -23
- ccxt/async_support/btcmarkets.py +211 -58
- ccxt/async_support/btcturk.py +161 -38
- ccxt/async_support/bybit.py +1775 -1030
- ccxt/async_support/cex.py +1440 -1303
- ccxt/async_support/coinbase.py +724 -212
- ccxt/async_support/coinbaseadvanced.py +2 -1
- ccxt/async_support/coinbaseexchange.py +388 -89
- ccxt/async_support/coinbaseinternational.py +412 -57
- ccxt/async_support/coincatch.py +177 -78
- ccxt/async_support/coincheck.py +135 -19
- ccxt/async_support/coinex.py +606 -232
- ccxt/async_support/coinmate.py +189 -63
- ccxt/async_support/coinmetro.py +195 -54
- ccxt/async_support/coinone.py +158 -51
- ccxt/async_support/coinsph.py +336 -61
- ccxt/async_support/coinspot.py +151 -52
- ccxt/async_support/cryptocom.py +661 -111
- ccxt/async_support/cryptomus.py +1137 -0
- ccxt/async_support/defx.py +2071 -0
- ccxt/async_support/delta.py +299 -99
- ccxt/async_support/deribit.py +348 -126
- ccxt/async_support/derive.py +2572 -0
- ccxt/async_support/digifinex.py +430 -214
- ccxt/async_support/ellipx.py +2029 -0
- ccxt/async_support/eterex.py +10 -10
- ccxt/async_support/excoino.py +31 -31
- ccxt/async_support/exir.py +14 -14
- ccxt/async_support/exmo.py +344 -131
- ccxt/async_support/exnovin.py +10 -10
- ccxt/async_support/farhadexchange.py +12 -12
- ccxt/async_support/fmfwio.py +2 -1
- ccxt/async_support/foxbit.py +1935 -0
- ccxt/async_support/gate.py +1351 -529
- ccxt/async_support/gateio.py +2 -1
- ccxt/async_support/gemini.py +144 -39
- ccxt/async_support/hashkey.py +152 -109
- ccxt/async_support/hibachi.py +2080 -0
- ccxt/async_support/hitbtc.py +395 -167
- ccxt/async_support/hitobit.py +12 -12
- ccxt/async_support/hollaex.py +307 -119
- ccxt/async_support/htx.py +851 -383
- ccxt/async_support/huobi.py +2 -1
- ccxt/async_support/hyperliquid.py +1848 -536
- ccxt/async_support/independentreserve.py +288 -15
- ccxt/async_support/indodax.py +190 -33
- ccxt/async_support/jibitex.py +12 -12
- ccxt/async_support/kraken.py +795 -351
- ccxt/async_support/krakenfutures.py +214 -62
- ccxt/async_support/kucoin.py +715 -396
- ccxt/async_support/kucoinfutures.py +652 -89
- ccxt/async_support/latoken.py +217 -113
- ccxt/async_support/lbank.py +425 -97
- ccxt/async_support/luno.py +382 -35
- ccxt/async_support/mercado.py +113 -6
- ccxt/async_support/mexc.py +874 -437
- ccxt/async_support/modetrade.py +2818 -0
- ccxt/async_support/myokx.py +54 -0
- ccxt/async_support/ndax.py +221 -64
- ccxt/async_support/nobitex.py +31 -37
- ccxt/async_support/novadax.py +190 -34
- ccxt/async_support/oceanex.py +217 -28
- ccxt/async_support/okcoin.py +253 -145
- ccxt/async_support/okexchange.py +11 -11
- ccxt/async_support/okx.py +1088 -351
- ccxt/async_support/okxus.py +54 -0
- ccxt/async_support/ompfinex.py +25 -24
- ccxt/async_support/onetrading.py +213 -392
- ccxt/async_support/oxfun.py +245 -166
- ccxt/async_support/p2b.py +151 -29
- ccxt/async_support/paradex.py +562 -49
- ccxt/async_support/paymium.py +82 -19
- ccxt/async_support/phemex.py +713 -172
- ccxt/async_support/poloniex.py +1602 -283
- ccxt/async_support/probit.py +224 -95
- ccxt/async_support/ramzinex.py +30 -27
- ccxt/async_support/sarmayex.py +9 -9
- ccxt/async_support/sarrafex.py +13 -13
- ccxt/async_support/tabdeal.py +14 -13
- ccxt/async_support/tetherland.py +9 -9
- ccxt/async_support/timex.py +210 -51
- ccxt/async_support/tokocrypto.py +167 -47
- ccxt/async_support/tradeogre.py +266 -31
- ccxt/async_support/twox.py +9 -9
- ccxt/async_support/ubitex.py +12 -12
- ccxt/async_support/upbit.py +568 -165
- ccxt/async_support/vertex.py +160 -32
- ccxt/async_support/wallex.py +12 -12
- ccxt/async_support/wavesexchange.py +165 -30
- ccxt/async_support/whitebit.py +975 -127
- ccxt/async_support/woo.py +1918 -1016
- ccxt/async_support/woofipro.py +433 -141
- ccxt/async_support/xt.py +649 -193
- ccxt/async_support/yobit.py +195 -70
- ccxt/async_support/zaif.py +91 -15
- ccxt/async_support/zonda.py +151 -36
- ccxt/base/decimal_to_precision.py +14 -10
- ccxt/base/errors.py +49 -18
- ccxt/base/exchange.py +1556 -450
- ccxt/base/precise.py +10 -0
- ccxt/base/types.py +114 -6
- ccxt/bequant.py +5 -3
- ccxt/bigone.py +279 -144
- ccxt/binance.py +2347 -1158
- ccxt/binancecoinm.py +9 -3
- ccxt/binanceus.py +17 -3
- ccxt/binanceusdm.py +9 -4
- ccxt/bingx.py +2962 -920
- ccxt/bit2c.py +147 -27
- ccxt/bitbank.py +151 -23
- ccxt/bitbns.py +104 -30
- ccxt/bitfinex.py +3290 -1113
- ccxt/bitflyer.py +202 -27
- ccxt/bitget.py +3683 -1538
- ccxt/bithumb.py +194 -38
- ccxt/bitimen.py +9 -9
- ccxt/bitir.py +35 -35
- ccxt/bitmart.py +1288 -350
- ccxt/bitmex.py +260 -75
- ccxt/bitopro.py +262 -62
- ccxt/bitpin.py +15 -14
- ccxt/bitrue.py +459 -290
- ccxt/bitso.py +199 -54
- ccxt/bitstamp.py +230 -96
- ccxt/bitteam.py +167 -25
- ccxt/{huobijp.py → bittrade.py} +158 -30
- ccxt/bitvavo.py +213 -49
- ccxt/blockchaincom.py +160 -46
- ccxt/blofin.py +502 -120
- ccxt/btcalpha.py +169 -31
- ccxt/btcbox.py +291 -23
- ccxt/btcmarkets.py +211 -58
- ccxt/btcturk.py +161 -38
- ccxt/bybit.py +1775 -1030
- ccxt/cex.py +1439 -1303
- ccxt/coinbase.py +724 -212
- ccxt/coinbaseadvanced.py +2 -1
- ccxt/coinbaseexchange.py +388 -89
- ccxt/coinbaseinternational.py +412 -57
- ccxt/coincatch.py +177 -78
- ccxt/coincheck.py +135 -19
- ccxt/coinex.py +606 -232
- ccxt/coinmate.py +189 -63
- ccxt/coinmetro.py +194 -54
- ccxt/coinone.py +158 -51
- ccxt/coinsph.py +336 -61
- ccxt/coinspot.py +151 -52
- ccxt/cryptocom.py +661 -111
- ccxt/cryptomus.py +1137 -0
- ccxt/defx.py +2070 -0
- ccxt/delta.py +299 -99
- ccxt/deribit.py +348 -126
- ccxt/derive.py +2571 -0
- ccxt/digifinex.py +430 -214
- ccxt/ellipx.py +2029 -0
- ccxt/eterex.py +7 -7
- ccxt/excoino.py +29 -29
- ccxt/exir.py +11 -11
- ccxt/exmo.py +343 -131
- ccxt/exnovin.py +8 -8
- ccxt/farhadexchange.py +10 -10
- ccxt/fmfwio.py +2 -1
- ccxt/foxbit.py +1935 -0
- ccxt/gate.py +1351 -529
- ccxt/gateio.py +2 -1
- ccxt/gemini.py +144 -39
- ccxt/hashkey.py +152 -109
- ccxt/hibachi.py +2079 -0
- ccxt/hitbtc.py +395 -167
- ccxt/hitobit.py +9 -9
- ccxt/hollaex.py +307 -119
- ccxt/htx.py +851 -383
- ccxt/huobi.py +2 -1
- ccxt/hyperliquid.py +1848 -536
- ccxt/independentreserve.py +287 -15
- ccxt/indodax.py +190 -33
- ccxt/jibitex.py +9 -9
- ccxt/kraken.py +794 -351
- ccxt/krakenfutures.py +214 -62
- ccxt/kucoin.py +715 -396
- ccxt/kucoinfutures.py +652 -89
- ccxt/latoken.py +217 -113
- ccxt/lbank.py +425 -97
- ccxt/luno.py +382 -35
- ccxt/mercado.py +113 -6
- ccxt/mexc.py +873 -437
- ccxt/modetrade.py +2818 -0
- ccxt/myokx.py +54 -0
- ccxt/ndax.py +221 -64
- ccxt/nobitex.py +29 -35
- ccxt/novadax.py +190 -34
- ccxt/oceanex.py +217 -28
- ccxt/okcoin.py +253 -145
- ccxt/okexchange.py +9 -9
- ccxt/okx.py +1088 -351
- ccxt/okxus.py +54 -0
- ccxt/ompfinex.py +22 -21
- ccxt/onetrading.py +213 -392
- ccxt/oxfun.py +245 -166
- ccxt/p2b.py +151 -29
- ccxt/paradex.py +562 -49
- ccxt/paymium.py +82 -19
- ccxt/phemex.py +712 -172
- ccxt/poloniex.py +1601 -283
- ccxt/pro/__init__.py +76 -17
- ccxt/pro/alpaca.py +21 -6
- ccxt/pro/apex.py +984 -0
- ccxt/pro/ascendex.py +58 -10
- ccxt/pro/bequant.py +6 -1
- ccxt/pro/binance.py +728 -156
- ccxt/pro/binancecoinm.py +6 -2
- ccxt/pro/binanceus.py +8 -4
- ccxt/pro/binanceusdm.py +7 -2
- ccxt/pro/bingx.py +333 -142
- ccxt/pro/bitfinex.py +727 -262
- ccxt/pro/bitget.py +570 -79
- ccxt/pro/bithumb.py +20 -6
- ccxt/pro/bitmart.py +216 -87
- ccxt/pro/bitmex.py +47 -9
- ccxt/pro/bitopro.py +26 -14
- ccxt/pro/bitrue.py +22 -22
- ccxt/pro/bitstamp.py +54 -21
- ccxt/pro/{huobijp.py → bittrade.py} +7 -6
- ccxt/pro/bitvavo.py +191 -67
- ccxt/pro/blockchaincom.py +21 -8
- ccxt/pro/blofin.py +9 -1
- ccxt/pro/bybit.py +632 -245
- ccxt/pro/cex.py +59 -24
- ccxt/pro/coinbase.py +102 -73
- ccxt/pro/coinbaseadvanced.py +2 -1
- ccxt/pro/coinbaseexchange.py +8 -8
- ccxt/pro/coinbaseinternational.py +181 -25
- ccxt/pro/coincatch.py +6 -7
- ccxt/pro/coincheck.py +11 -6
- ccxt/pro/coinex.py +967 -665
- ccxt/pro/coinone.py +16 -9
- ccxt/pro/cryptocom.py +448 -45
- ccxt/pro/defx.py +831 -0
- ccxt/pro/deribit.py +150 -14
- ccxt/pro/derive.py +704 -0
- ccxt/pro/exmo.py +239 -6
- ccxt/pro/gate.py +623 -65
- ccxt/pro/gateio.py +2 -1
- ccxt/pro/gemini.py +27 -11
- ccxt/pro/hashkey.py +2 -2
- ccxt/pro/hitbtc.py +196 -91
- ccxt/pro/hollaex.py +23 -7
- ccxt/pro/htx.py +51 -14
- ccxt/pro/huobi.py +2 -1
- ccxt/pro/hyperliquid.py +591 -27
- ccxt/pro/independentreserve.py +9 -6
- ccxt/pro/kraken.py +640 -320
- ccxt/pro/krakenfutures.py +62 -35
- ccxt/pro/kucoin.py +267 -46
- ccxt/pro/kucoinfutures.py +165 -21
- ccxt/pro/lbank.py +102 -21
- ccxt/pro/luno.py +12 -8
- ccxt/pro/mexc.py +877 -111
- ccxt/pro/modetrade.py +1271 -0
- ccxt/pro/myokx.py +38 -0
- ccxt/pro/ndax.py +15 -2
- ccxt/pro/okcoin.py +23 -4
- ccxt/pro/okx.py +573 -98
- ccxt/pro/okxus.py +38 -0
- ccxt/pro/onetrading.py +30 -13
- ccxt/pro/oxfun.py +131 -27
- ccxt/pro/p2b.py +88 -22
- ccxt/pro/paradex.py +3 -3
- ccxt/pro/phemex.py +75 -21
- ccxt/pro/poloniex.py +124 -41
- ccxt/pro/probit.py +87 -80
- ccxt/pro/tradeogre.py +272 -0
- ccxt/pro/upbit.py +152 -12
- ccxt/pro/vertex.py +8 -3
- ccxt/pro/whitebit.py +58 -5
- ccxt/pro/woo.py +228 -37
- ccxt/pro/woofipro.py +106 -18
- ccxt/pro/xt.py +111 -5
- ccxt/probit.py +224 -95
- ccxt/protobuf/__init__.py +0 -0
- ccxt/protobuf/mexc/PrivateAccountV3Api_pb2.py +37 -0
- ccxt/protobuf/mexc/PrivateDealsV3Api_pb2.py +37 -0
- ccxt/protobuf/mexc/PrivateOrdersV3Api_pb2.py +37 -0
- ccxt/protobuf/mexc/PublicAggreBookTickerV3Api_pb2.py +37 -0
- ccxt/protobuf/mexc/PublicAggreDealsV3Api_pb2.py +39 -0
- ccxt/protobuf/mexc/PublicAggreDepthsV3Api_pb2.py +39 -0
- ccxt/protobuf/mexc/PublicBookTickerBatchV3Api_pb2.py +38 -0
- ccxt/protobuf/mexc/PublicBookTickerV3Api_pb2.py +37 -0
- ccxt/protobuf/mexc/PublicDealsV3Api_pb2.py +39 -0
- ccxt/protobuf/mexc/PublicIncreaseDepthsBatchV3Api_pb2.py +38 -0
- ccxt/protobuf/mexc/PublicIncreaseDepthsV3Api_pb2.py +39 -0
- ccxt/protobuf/mexc/PublicLimitDepthsV3Api_pb2.py +39 -0
- ccxt/protobuf/mexc/PublicMiniTickerV3Api_pb2.py +37 -0
- ccxt/protobuf/mexc/PublicMiniTickersV3Api_pb2.py +38 -0
- ccxt/protobuf/mexc/PublicSpotKlineV3Api_pb2.py +37 -0
- ccxt/protobuf/mexc/PushDataV3ApiWrapper_pb2.py +52 -0
- ccxt/protobuf/mexc/__init__.py +0 -0
- ccxt/ramzinex.py +28 -25
- ccxt/sarmayex.py +7 -7
- ccxt/sarrafex.py +10 -10
- ccxt/static_dependencies/__init__.py +1 -1
- ccxt/static_dependencies/lark/py.typed +0 -0
- ccxt/static_dependencies/marshmallow/py.typed +0 -0
- ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
- ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
- ccxt/tabdeal.py +12 -11
- ccxt/test/tests_async.py +261 -57
- ccxt/test/tests_helpers.py +1 -3
- ccxt/test/tests_init.py +4 -3
- ccxt/test/tests_sync.py +261 -57
- ccxt/tetherland.py +7 -7
- ccxt/timex.py +210 -51
- ccxt/tokocrypto.py +167 -47
- ccxt/tradeogre.py +266 -31
- ccxt/twox.py +7 -7
- ccxt/ubitex.py +9 -9
- ccxt/upbit.py +568 -165
- ccxt/vertex.py +160 -32
- ccxt/wallex.py +9 -9
- ccxt/wavesexchange.py +165 -30
- ccxt/whitebit.py +975 -127
- ccxt/woo.py +1917 -1016
- ccxt/woofipro.py +432 -141
- ccxt/xt.py +649 -193
- ccxt/yobit.py +194 -70
- ccxt/zaif.py +91 -15
- ccxt/zonda.py +151 -36
- {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.0.dist-info}/METADATA +225 -73
- ccxt_ir-4.5.0.dist-info/RECORD +743 -0
- {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.0.dist-info}/WHEEL +1 -1
- ccxt/__test__.py +0 -7
- ccxt/abstract/ace.py +0 -15
- ccxt/abstract/bitbay.py +0 -53
- ccxt/abstract/bitcoincom.py +0 -115
- ccxt/abstract/bitfinex2.py +0 -139
- ccxt/abstract/bitpanda.py +0 -35
- ccxt/abstract/bl3p.py +0 -19
- ccxt/abstract/coinlist.py +0 -54
- ccxt/abstract/currencycom.py +0 -68
- ccxt/abstract/hitbtc3.py +0 -115
- ccxt/abstract/idex.py +0 -26
- ccxt/abstract/kuna.py +0 -182
- ccxt/abstract/lykke.py +0 -29
- ccxt/abstract/poloniexfutures.py +0 -48
- ccxt/abstract/wazirx.py +0 -30
- ccxt/ace.py +0 -1012
- ccxt/async_support/ace.py +0 -1012
- ccxt/async_support/base/ws/aiohttp_client.py +0 -125
- ccxt/async_support/base/ws/fast_client.py +0 -96
- ccxt/async_support/bitbay.py +0 -17
- ccxt/async_support/bitcoincom.py +0 -17
- ccxt/async_support/bitfinex2.py +0 -3552
- ccxt/async_support/bitpanda.py +0 -16
- ccxt/async_support/bl3p.py +0 -485
- ccxt/async_support/coinlist.py +0 -2243
- ccxt/async_support/currencycom.py +0 -1950
- ccxt/async_support/hitbtc3.py +0 -16
- ccxt/async_support/idex.py +0 -1766
- ccxt/async_support/kuna.py +0 -1841
- ccxt/async_support/lykke.py +0 -1270
- ccxt/async_support/poloniexfutures.py +0 -1717
- ccxt/async_support/wazirx.py +0 -1224
- ccxt/bitbay.py +0 -17
- ccxt/bitcoincom.py +0 -17
- ccxt/bitfinex2.py +0 -3552
- ccxt/bitpanda.py +0 -16
- ccxt/bl3p.py +0 -485
- ccxt/coinlist.py +0 -2243
- ccxt/currencycom.py +0 -1950
- ccxt/hitbtc3.py +0 -16
- ccxt/idex.py +0 -1766
- ccxt/kuna.py +0 -1841
- ccxt/lykke.py +0 -1270
- ccxt/poloniexfutures.py +0 -1717
- ccxt/pro/bitcoincom.py +0 -34
- ccxt/pro/bitfinex2.py +0 -1083
- ccxt/pro/bitpanda.py +0 -15
- ccxt/pro/currencycom.py +0 -536
- ccxt/pro/idex.py +0 -672
- ccxt/pro/poloniexfutures.py +0 -990
- ccxt/pro/wazirx.py +0 -749
- ccxt/test/base/__init__.py +0 -29
- ccxt/test/base/test_account.py +0 -26
- ccxt/test/base/test_balance.py +0 -56
- ccxt/test/base/test_borrow_interest.py +0 -35
- ccxt/test/base/test_borrow_rate.py +0 -32
- ccxt/test/base/test_calculate_fee.py +0 -51
- ccxt/test/base/test_crypto.py +0 -127
- ccxt/test/base/test_currency.py +0 -76
- ccxt/test/base/test_datetime.py +0 -109
- ccxt/test/base/test_decimal_to_precision.py +0 -392
- ccxt/test/base/test_deep_extend.py +0 -68
- ccxt/test/base/test_deposit_withdrawal.py +0 -50
- ccxt/test/base/test_exchange_datetime_functions.py +0 -76
- ccxt/test/base/test_funding_rate_history.py +0 -29
- ccxt/test/base/test_last_price.py +0 -31
- ccxt/test/base/test_ledger_entry.py +0 -45
- ccxt/test/base/test_ledger_item.py +0 -48
- ccxt/test/base/test_leverage_tier.py +0 -33
- ccxt/test/base/test_liquidation.py +0 -50
- ccxt/test/base/test_margin_mode.py +0 -24
- ccxt/test/base/test_margin_modification.py +0 -35
- ccxt/test/base/test_market.py +0 -193
- ccxt/test/base/test_number.py +0 -411
- ccxt/test/base/test_ohlcv.py +0 -33
- ccxt/test/base/test_open_interest.py +0 -32
- ccxt/test/base/test_order.py +0 -64
- ccxt/test/base/test_order_book.py +0 -69
- ccxt/test/base/test_position.py +0 -60
- ccxt/test/base/test_shared_methods.py +0 -353
- ccxt/test/base/test_status.py +0 -24
- ccxt/test/base/test_throttle.py +0 -126
- ccxt/test/base/test_ticker.py +0 -92
- ccxt/test/base/test_trade.py +0 -47
- ccxt/test/base/test_trading_fee.py +0 -26
- ccxt/test/base/test_transaction.py +0 -39
- ccxt/test/test_async.py +0 -1649
- ccxt/test/test_sync.py +0 -1648
- ccxt/wazirx.py +0 -1224
- ccxt_ir-4.3.46.0.3.dist-info/RECORD +0 -773
- /ccxt/abstract/{huobijp.py → bittrade.py} +0 -0
- {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.0.dist-info/licenses}/LICENSE.txt +0 -0
- {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.0.dist-info}/top_level.txt +0 -0
ccxt/pro/coinex.py
CHANGED
|
@@ -4,45 +4,51 @@
|
|
|
4
4
|
# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
|
|
5
5
|
|
|
6
6
|
import ccxt.async_support
|
|
7
|
-
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById
|
|
8
|
-
|
|
7
|
+
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById
|
|
8
|
+
import hashlib
|
|
9
|
+
from ccxt.base.types import Any, Balances, Int, Order, OrderBook, Str, Strings, Ticker, Tickers, Trade
|
|
9
10
|
from ccxt.async_support.base.ws.client import Client
|
|
10
11
|
from typing import List
|
|
11
12
|
from ccxt.base.errors import ExchangeError
|
|
12
13
|
from ccxt.base.errors import AuthenticationError
|
|
13
14
|
from ccxt.base.errors import BadRequest
|
|
14
15
|
from ccxt.base.errors import NotSupported
|
|
16
|
+
from ccxt.base.errors import RateLimitExceeded
|
|
15
17
|
from ccxt.base.errors import ExchangeNotAvailable
|
|
16
18
|
from ccxt.base.errors import RequestTimeout
|
|
17
|
-
from ccxt.base.precise import Precise
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
class coinex(ccxt.async_support.coinex):
|
|
21
22
|
|
|
22
|
-
def describe(self):
|
|
23
|
+
def describe(self) -> Any:
|
|
23
24
|
return self.deep_extend(super(coinex, self).describe(), {
|
|
24
25
|
'has': {
|
|
25
26
|
'ws': True,
|
|
26
27
|
'watchBalance': True,
|
|
28
|
+
'watchBidsAsks': True,
|
|
27
29
|
'watchTicker': True,
|
|
28
30
|
'watchTickers': True,
|
|
29
31
|
'watchTrades': True,
|
|
30
|
-
'
|
|
32
|
+
'watchTradesForSymbols': True,
|
|
33
|
+
'watchMyTrades': True,
|
|
31
34
|
'watchOrders': True,
|
|
32
35
|
'watchOrderBook': True,
|
|
33
|
-
'
|
|
34
|
-
'
|
|
36
|
+
'watchOrderBookForSymbols': True,
|
|
37
|
+
'watchOHLCV': False,
|
|
38
|
+
'fetchOHLCVWs': False,
|
|
35
39
|
},
|
|
36
40
|
'urls': {
|
|
37
41
|
'api': {
|
|
38
42
|
'ws': {
|
|
39
|
-
'spot': 'wss://socket.coinex.com/',
|
|
40
|
-
'swap': 'wss://
|
|
43
|
+
'spot': 'wss://socket.coinex.com/v2/spot/',
|
|
44
|
+
'swap': 'wss://socket.coinex.com/v2/futures/',
|
|
41
45
|
},
|
|
42
46
|
},
|
|
43
47
|
},
|
|
44
48
|
'options': {
|
|
45
|
-
'
|
|
49
|
+
'ws': {
|
|
50
|
+
'gunzip': True,
|
|
51
|
+
},
|
|
46
52
|
'timeframes': {
|
|
47
53
|
'1m': 60,
|
|
48
54
|
'3m': 180,
|
|
@@ -62,21 +68,32 @@ class coinex(ccxt.async_support.coinex):
|
|
|
62
68
|
'watchOrderBook': {
|
|
63
69
|
'limits': [5, 10, 20, 50],
|
|
64
70
|
'defaultLimit': 50,
|
|
65
|
-
'aggregations': ['10', '1', '0', '0.1', '0.01'],
|
|
71
|
+
'aggregations': ['1000', '100', '10', '1', '0', '0.1', '0.01', '0.001', '0.0001', '0.00001', '0.000001', '0.0000001', '0.00000001', '0.000000001', '0.0000000001', '0.00000000001'],
|
|
66
72
|
'defaultAggregation': '0',
|
|
67
73
|
},
|
|
68
74
|
},
|
|
69
75
|
'streaming': {
|
|
70
76
|
},
|
|
71
77
|
'exceptions': {
|
|
72
|
-
'
|
|
73
|
-
'
|
|
74
|
-
'
|
|
75
|
-
'
|
|
76
|
-
'
|
|
77
|
-
'
|
|
78
|
-
'
|
|
78
|
+
'exact': {
|
|
79
|
+
'20001': BadRequest, # Invalid argument
|
|
80
|
+
'20002': NotSupported, # Method unavailable
|
|
81
|
+
'21001': AuthenticationError, # Authentication required
|
|
82
|
+
'21002': AuthenticationError, # Incorrect signature
|
|
83
|
+
'23001': RequestTimeout, # Request service timeout
|
|
84
|
+
'23002': RateLimitExceeded, # Requests too frequently
|
|
85
|
+
'24001': ExchangeError, # Internal error
|
|
86
|
+
'24002': ExchangeNotAvailable, # Service unavailable temporarily
|
|
87
|
+
'30001': BadRequest, # Invalid argument
|
|
88
|
+
'30002': NotSupported, # Method unavailable
|
|
89
|
+
'31001': AuthenticationError, # Authentication required
|
|
90
|
+
'31002': AuthenticationError, # Incorrect signature
|
|
91
|
+
'33001': RequestTimeout, # Request service timeout
|
|
92
|
+
'33002': RateLimitExceeded, # Requests too frequently
|
|
93
|
+
'34001': ExchangeError, # Internal error
|
|
94
|
+
'34002': ExchangeNotAvailable, # Service unavailable temporarily
|
|
79
95
|
},
|
|
96
|
+
'broad': {},
|
|
80
97
|
},
|
|
81
98
|
})
|
|
82
99
|
|
|
@@ -91,61 +108,66 @@ class coinex(ccxt.async_support.coinex):
|
|
|
91
108
|
#
|
|
92
109
|
# {
|
|
93
110
|
# "method": "state.update",
|
|
94
|
-
# "
|
|
95
|
-
# "
|
|
96
|
-
#
|
|
97
|
-
#
|
|
98
|
-
#
|
|
99
|
-
#
|
|
100
|
-
#
|
|
101
|
-
#
|
|
102
|
-
#
|
|
103
|
-
#
|
|
104
|
-
#
|
|
105
|
-
#
|
|
106
|
-
#
|
|
107
|
-
#
|
|
111
|
+
# "data": {
|
|
112
|
+
# "state_list": [
|
|
113
|
+
# {
|
|
114
|
+
# "market": "LATUSDT",
|
|
115
|
+
# "last": "0.008157",
|
|
116
|
+
# "open": "0.008286",
|
|
117
|
+
# "close": "0.008157",
|
|
118
|
+
# "high": "0.008390",
|
|
119
|
+
# "low": "0.008106",
|
|
120
|
+
# "volume": "807714.49139758",
|
|
121
|
+
# "volume_sell": "286170.69645599",
|
|
122
|
+
# "volume_buy": "266161.23236408",
|
|
123
|
+
# "value": "6689.21644207",
|
|
124
|
+
# "period": 86400
|
|
125
|
+
# },
|
|
126
|
+
# ]
|
|
127
|
+
# },
|
|
128
|
+
# "id": null
|
|
108
129
|
# }
|
|
109
130
|
#
|
|
110
131
|
# swap
|
|
111
132
|
#
|
|
112
133
|
# {
|
|
113
134
|
# "method": "state.update",
|
|
114
|
-
# "
|
|
115
|
-
# "
|
|
116
|
-
#
|
|
117
|
-
#
|
|
118
|
-
#
|
|
119
|
-
#
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
#
|
|
123
|
-
#
|
|
124
|
-
#
|
|
125
|
-
#
|
|
126
|
-
#
|
|
127
|
-
#
|
|
128
|
-
#
|
|
129
|
-
#
|
|
130
|
-
#
|
|
131
|
-
#
|
|
132
|
-
#
|
|
133
|
-
#
|
|
134
|
-
#
|
|
135
|
-
#
|
|
135
|
+
# "data": {
|
|
136
|
+
# "state_list": [
|
|
137
|
+
# {
|
|
138
|
+
# "market": "ETHUSD_SIGNPRICE",
|
|
139
|
+
# "last": "1892.29",
|
|
140
|
+
# "open": "1884.62",
|
|
141
|
+
# "close": "1892.29",
|
|
142
|
+
# "high": "1894.09",
|
|
143
|
+
# "low": "1863.72",
|
|
144
|
+
# "volume": "0",
|
|
145
|
+
# "value": "0",
|
|
146
|
+
# "volume_sell": "0",
|
|
147
|
+
# "volume_buy": "0",
|
|
148
|
+
# "open_interest_size": "0",
|
|
149
|
+
# "insurance_fund_size": "0",
|
|
150
|
+
# "latest_funding_rate": "0",
|
|
151
|
+
# "next_funding_rate": "0",
|
|
152
|
+
# "latest_funding_time": 0,
|
|
153
|
+
# "next_funding_time": 0,
|
|
154
|
+
# "period": 86400
|
|
155
|
+
# },
|
|
156
|
+
# ]
|
|
157
|
+
# ],
|
|
158
|
+
# "id": null
|
|
136
159
|
# }
|
|
137
160
|
#
|
|
138
161
|
defaultType = self.safe_string(self.options, 'defaultType')
|
|
139
|
-
|
|
140
|
-
rawTickers = self.
|
|
141
|
-
keys = list(rawTickers.keys())
|
|
162
|
+
data = self.safe_dict(message, 'data', {})
|
|
163
|
+
rawTickers = self.safe_list(data, 'state_list', [])
|
|
142
164
|
newTickers = []
|
|
143
|
-
for i in range(0, len(
|
|
144
|
-
|
|
145
|
-
|
|
165
|
+
for i in range(0, len(rawTickers)):
|
|
166
|
+
entry = rawTickers[i]
|
|
167
|
+
marketId = self.safe_string(entry, 'market')
|
|
146
168
|
symbol = self.safe_symbol(marketId, None, None, defaultType)
|
|
147
169
|
market = self.safe_market(marketId, None, None, defaultType)
|
|
148
|
-
parsedTicker = self.parse_ws_ticker(
|
|
170
|
+
parsedTicker = self.parse_ws_ticker(entry, market)
|
|
149
171
|
self.tickers[symbol] = parsedTicker
|
|
150
172
|
newTickers.append(parsedTicker)
|
|
151
173
|
messageHashes = self.find_message_hashes(client, 'tickers::')
|
|
@@ -166,52 +188,53 @@ class coinex(ccxt.async_support.coinex):
|
|
|
166
188
|
# spot
|
|
167
189
|
#
|
|
168
190
|
# {
|
|
169
|
-
# "
|
|
170
|
-
# "
|
|
171
|
-
# "
|
|
172
|
-
# "
|
|
173
|
-
# "
|
|
174
|
-
# "
|
|
175
|
-
# "
|
|
176
|
-
# "
|
|
177
|
-
# "
|
|
178
|
-
# "
|
|
191
|
+
# "market": "LATUSDT",
|
|
192
|
+
# "last": "0.008157",
|
|
193
|
+
# "open": "0.008286",
|
|
194
|
+
# "close": "0.008157",
|
|
195
|
+
# "high": "0.008390",
|
|
196
|
+
# "low": "0.008106",
|
|
197
|
+
# "volume": "807714.49139758",
|
|
198
|
+
# "volume_sell": "286170.69645599",
|
|
199
|
+
# "volume_buy": "266161.23236408",
|
|
200
|
+
# "value": "6689.21644207",
|
|
201
|
+
# "period": 86400
|
|
179
202
|
# }
|
|
180
203
|
#
|
|
181
204
|
# swap
|
|
182
205
|
#
|
|
183
206
|
# {
|
|
184
|
-
# "
|
|
185
|
-
# "
|
|
186
|
-
# "
|
|
187
|
-
# "
|
|
188
|
-
# "
|
|
189
|
-
# "
|
|
190
|
-
# "
|
|
191
|
-
# "
|
|
192
|
-
# "
|
|
193
|
-
# "
|
|
194
|
-
# "
|
|
195
|
-
# "
|
|
196
|
-
# "
|
|
197
|
-
# "
|
|
198
|
-
# "
|
|
199
|
-
# "
|
|
200
|
-
# "
|
|
201
|
-
# "buy_total": "25.7814"
|
|
207
|
+
# "market": "ETHUSD_SIGNPRICE",
|
|
208
|
+
# "last": "1892.29",
|
|
209
|
+
# "open": "1884.62",
|
|
210
|
+
# "close": "1892.29",
|
|
211
|
+
# "high": "1894.09",
|
|
212
|
+
# "low": "1863.72",
|
|
213
|
+
# "volume": "0",
|
|
214
|
+
# "value": "0",
|
|
215
|
+
# "volume_sell": "0",
|
|
216
|
+
# "volume_buy": "0",
|
|
217
|
+
# "open_interest_size": "0",
|
|
218
|
+
# "insurance_fund_size": "0",
|
|
219
|
+
# "latest_funding_rate": "0",
|
|
220
|
+
# "next_funding_rate": "0",
|
|
221
|
+
# "latest_funding_time": 0,
|
|
222
|
+
# "next_funding_time": 0,
|
|
223
|
+
# "period": 86400
|
|
202
224
|
# }
|
|
203
225
|
#
|
|
204
226
|
defaultType = self.safe_string(self.options, 'defaultType')
|
|
227
|
+
marketId = self.safe_string(ticker, 'market')
|
|
205
228
|
return self.safe_ticker({
|
|
206
|
-
'symbol': self.safe_symbol(
|
|
229
|
+
'symbol': self.safe_symbol(marketId, market, None, defaultType),
|
|
207
230
|
'timestamp': None,
|
|
208
231
|
'datetime': None,
|
|
209
232
|
'high': self.safe_string(ticker, 'high'),
|
|
210
233
|
'low': self.safe_string(ticker, 'low'),
|
|
211
234
|
'bid': None,
|
|
212
|
-
'bidVolume': self.safe_string(ticker, '
|
|
235
|
+
'bidVolume': self.safe_string(ticker, 'volume_buy'),
|
|
213
236
|
'ask': None,
|
|
214
|
-
'askVolume': self.safe_string(ticker, '
|
|
237
|
+
'askVolume': self.safe_string(ticker, 'volume_sell'),
|
|
215
238
|
'vwap': None,
|
|
216
239
|
'open': self.safe_string(ticker, 'open'),
|
|
217
240
|
'close': self.safe_string(ticker, 'close'),
|
|
@@ -221,84 +244,281 @@ class coinex(ccxt.async_support.coinex):
|
|
|
221
244
|
'percentage': None,
|
|
222
245
|
'average': None,
|
|
223
246
|
'baseVolume': self.safe_string(ticker, 'volume'),
|
|
224
|
-
'quoteVolume': self.safe_string(ticker, '
|
|
247
|
+
'quoteVolume': self.safe_string(ticker, 'value'),
|
|
225
248
|
'info': ticker,
|
|
226
249
|
}, market)
|
|
227
250
|
|
|
228
251
|
async def watch_balance(self, params={}) -> Balances:
|
|
229
252
|
"""
|
|
230
253
|
watch balance and get the amount of funds available for trading or funds locked in orders
|
|
254
|
+
|
|
255
|
+
https://docs.coinex.com/api/v2/assets/balance/ws/spot_balance
|
|
256
|
+
https://docs.coinex.com/api/v2/assets/balance/ws/futures_balance
|
|
257
|
+
|
|
231
258
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
232
259
|
:returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
|
|
233
260
|
"""
|
|
234
261
|
await self.load_markets()
|
|
235
|
-
await self.authenticate(params)
|
|
236
|
-
messageHash = 'balance'
|
|
237
262
|
type = None
|
|
238
|
-
type, params = self.handle_market_type_and_params('watchBalance', None, params)
|
|
263
|
+
type, params = self.handle_market_type_and_params('watchBalance', None, params, 'spot')
|
|
264
|
+
await self.authenticate(type)
|
|
239
265
|
url = self.urls['api']['ws'][type]
|
|
240
|
-
currencies
|
|
266
|
+
# coinex throws a closes the websocket when subscribing over 1422 currencies, therefore we filter out inactive currencies
|
|
267
|
+
activeCurrencies = self.filter_by(self.currencies_by_id, 'active', True)
|
|
268
|
+
activeCurrenciesById = self.index_by(activeCurrencies, 'id')
|
|
269
|
+
currencies = list(activeCurrenciesById.keys())
|
|
270
|
+
if currencies is None:
|
|
271
|
+
currencies = []
|
|
272
|
+
messageHash = 'balances'
|
|
273
|
+
if type == 'spot':
|
|
274
|
+
messageHash += ':spot'
|
|
275
|
+
else:
|
|
276
|
+
messageHash += ':swap'
|
|
241
277
|
subscribe: dict = {
|
|
242
|
-
'method': '
|
|
243
|
-
'params': currencies,
|
|
278
|
+
'method': 'balance.subscribe',
|
|
279
|
+
'params': {'ccy_list': currencies},
|
|
244
280
|
'id': self.request_id(),
|
|
245
281
|
}
|
|
246
282
|
request = self.deep_extend(subscribe, params)
|
|
247
283
|
return await self.watch(url, messageHash, request, messageHash)
|
|
248
284
|
|
|
249
285
|
def handle_balance(self, client: Client, message):
|
|
286
|
+
#
|
|
287
|
+
# spot
|
|
250
288
|
#
|
|
251
289
|
# {
|
|
252
|
-
# "method": "
|
|
253
|
-
# "
|
|
254
|
-
#
|
|
255
|
-
#
|
|
256
|
-
# "
|
|
257
|
-
# "
|
|
258
|
-
#
|
|
259
|
-
#
|
|
260
|
-
#
|
|
290
|
+
# "method": "balance.update",
|
|
291
|
+
# "data": {
|
|
292
|
+
# "balance_list": [
|
|
293
|
+
# {
|
|
294
|
+
# "margin_market": "BTCUSDT",
|
|
295
|
+
# "ccy": "BTC",
|
|
296
|
+
# "available": "44.62207740",
|
|
297
|
+
# "frozen": "0.00000000",
|
|
298
|
+
# "updated_at": 1689152421692
|
|
299
|
+
# },
|
|
300
|
+
# ]
|
|
301
|
+
# },
|
|
302
|
+
# "id": null
|
|
303
|
+
# }
|
|
304
|
+
#
|
|
305
|
+
# swap
|
|
306
|
+
#
|
|
307
|
+
# {
|
|
308
|
+
# "method": "balance.update",
|
|
309
|
+
# "data": {
|
|
310
|
+
# "balance_list": [
|
|
311
|
+
# {
|
|
312
|
+
# "ccy": "USDT",
|
|
313
|
+
# "available": "97.92470982756335000001",
|
|
314
|
+
# "frozen": "0.00000000000000000000",
|
|
315
|
+
# "margin": "0.61442700000000000000",
|
|
316
|
+
# "transferrable": "97.92470982756335000001",
|
|
317
|
+
# "unrealized_pnl": "-0.00807000000000000000",
|
|
318
|
+
# "equity": "97.92470982756335000001"
|
|
319
|
+
# },
|
|
320
|
+
# ]
|
|
321
|
+
# },
|
|
261
322
|
# "id": null
|
|
262
323
|
# }
|
|
263
324
|
#
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
self.
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
325
|
+
if self.balance is None:
|
|
326
|
+
self.balance = {}
|
|
327
|
+
data = self.safe_dict(message, 'data', {})
|
|
328
|
+
balances = self.safe_list(data, 'balance_list', [])
|
|
329
|
+
firstEntry = balances[0]
|
|
330
|
+
updated = self.safe_integer(firstEntry, 'updated_at')
|
|
331
|
+
unrealizedPnl = self.safe_string(firstEntry, 'unrealized_pnl')
|
|
332
|
+
isSpot = (updated is not None)
|
|
333
|
+
isSwap = (unrealizedPnl is not None)
|
|
334
|
+
info = None
|
|
335
|
+
account = None
|
|
336
|
+
rawBalances = []
|
|
337
|
+
if isSpot:
|
|
338
|
+
account = 'spot'
|
|
339
|
+
for i in range(0, len(balances)):
|
|
340
|
+
rawBalances = self.array_concat(rawBalances, balances)
|
|
341
|
+
info = rawBalances
|
|
342
|
+
if isSwap:
|
|
343
|
+
account = 'swap'
|
|
344
|
+
for i in range(0, len(balances)):
|
|
345
|
+
rawBalances = self.array_concat(rawBalances, balances)
|
|
346
|
+
info = rawBalances
|
|
347
|
+
for i in range(0, len(rawBalances)):
|
|
348
|
+
entry = rawBalances[i]
|
|
349
|
+
self.parse_ws_balance(entry, account)
|
|
350
|
+
messageHash = None
|
|
351
|
+
if account is not None:
|
|
352
|
+
if self.safe_value(self.balance, account) is None:
|
|
353
|
+
self.balance[account] = {}
|
|
354
|
+
self.balance[account]['info'] = info
|
|
355
|
+
self.balance[account] = self.safe_balance(self.balance[account])
|
|
356
|
+
messageHash = 'balances:' + account
|
|
357
|
+
client.resolve(self.balance[account], messageHash)
|
|
358
|
+
|
|
359
|
+
def parse_ws_balance(self, balance, accountType=None):
|
|
360
|
+
#
|
|
361
|
+
# spot
|
|
362
|
+
#
|
|
363
|
+
# {
|
|
364
|
+
# "margin_market": "BTCUSDT",
|
|
365
|
+
# "ccy": "BTC",
|
|
366
|
+
# "available": "44.62207740",
|
|
367
|
+
# "frozen": "0.00000000",
|
|
368
|
+
# "updated_at": 1689152421692
|
|
369
|
+
# }
|
|
370
|
+
#
|
|
371
|
+
# swap
|
|
372
|
+
#
|
|
373
|
+
# {
|
|
374
|
+
# "ccy": "USDT",
|
|
375
|
+
# "available": "97.92470982756335000001",
|
|
376
|
+
# "frozen": "0.00000000000000000000",
|
|
377
|
+
# "margin": "0.61442700000000000000",
|
|
378
|
+
# "transferrable": "97.92470982756335000001",
|
|
379
|
+
# "unrealized_pnl": "-0.00807000000000000000",
|
|
380
|
+
# "equity": "97.92470982756335000001"
|
|
381
|
+
# }
|
|
382
|
+
#
|
|
383
|
+
account = self.account()
|
|
384
|
+
currencyId = self.safe_string(balance, 'ccy')
|
|
385
|
+
code = self.safe_currency_code(currencyId)
|
|
386
|
+
account['free'] = self.safe_string(balance, 'available')
|
|
387
|
+
account['used'] = self.safe_string(balance, 'frozen')
|
|
388
|
+
if accountType is not None:
|
|
389
|
+
if self.safe_value(self.balance, accountType) is None:
|
|
390
|
+
self.balance[accountType] = {}
|
|
391
|
+
self.balance[accountType][code] = account
|
|
392
|
+
else:
|
|
276
393
|
self.balance[code] = account
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
394
|
+
|
|
395
|
+
async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
|
396
|
+
"""
|
|
397
|
+
watches information on multiple trades made by the user
|
|
398
|
+
|
|
399
|
+
https://docs.coinex.com/api/v2/spot/deal/ws/user-deals
|
|
400
|
+
https://docs.coinex.com/api/v2/futures/deal/ws/user-deals
|
|
401
|
+
|
|
402
|
+
:param str [symbol]: unified symbol of the market the trades were made in
|
|
403
|
+
:param int [since]: the earliest time in ms to watch trades
|
|
404
|
+
:param int [limit]: the maximum number of trade structures to retrieve
|
|
405
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
406
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
|
|
407
|
+
"""
|
|
408
|
+
await self.load_markets()
|
|
409
|
+
market = None
|
|
410
|
+
if symbol is not None:
|
|
411
|
+
market = self.market(symbol)
|
|
412
|
+
symbol = market['symbol']
|
|
413
|
+
type = None
|
|
414
|
+
type, params = self.handle_market_type_and_params('watchMyTrades', market, params, 'spot')
|
|
415
|
+
await self.authenticate(type)
|
|
416
|
+
url = self.urls['api']['ws'][type]
|
|
417
|
+
subscribedSymbols = []
|
|
418
|
+
messageHash = 'myTrades'
|
|
419
|
+
if market is not None:
|
|
420
|
+
messageHash += ':' + symbol
|
|
421
|
+
subscribedSymbols.append(market['id'])
|
|
422
|
+
else:
|
|
423
|
+
if type == 'spot':
|
|
424
|
+
messageHash += ':spot'
|
|
425
|
+
else:
|
|
426
|
+
messageHash += ':swap'
|
|
427
|
+
message: dict = {
|
|
428
|
+
'method': 'user_deals.subscribe',
|
|
429
|
+
'params': {'market_list': subscribedSymbols},
|
|
430
|
+
'id': self.request_id(),
|
|
431
|
+
}
|
|
432
|
+
request = self.deep_extend(message, params)
|
|
433
|
+
trades = await self.watch(url, messageHash, request, messageHash)
|
|
434
|
+
if self.newUpdates:
|
|
435
|
+
limit = trades.getLimit(symbol, limit)
|
|
436
|
+
return self.filter_by_symbol_since_limit(trades, symbol, since, limit, True)
|
|
437
|
+
|
|
438
|
+
def handle_my_trades(self, client: Client, message):
|
|
439
|
+
#
|
|
440
|
+
# {
|
|
441
|
+
# "method": "user_deals.update",
|
|
442
|
+
# "data": {
|
|
443
|
+
# "deal_id": 3514376759,
|
|
444
|
+
# "created_at": 1689152421692,
|
|
445
|
+
# "market": "BTCUSDT",
|
|
446
|
+
# "side": "buy",
|
|
447
|
+
# "order_id": 8678890,
|
|
448
|
+
# "margin_market": "BTCUSDT",
|
|
449
|
+
# "price": "30718.42",
|
|
450
|
+
# "amount": "0.00000325",
|
|
451
|
+
# "role": "taker",
|
|
452
|
+
# "fee": "0.0299",
|
|
453
|
+
# "fee_ccy": "USDT"
|
|
454
|
+
# },
|
|
455
|
+
# "id": null
|
|
456
|
+
# }
|
|
457
|
+
#
|
|
458
|
+
data = self.safe_dict(message, 'data', {})
|
|
459
|
+
marketId = self.safe_string(data, 'market')
|
|
460
|
+
isSpot = client.url.find('spot') > -1
|
|
461
|
+
defaultType = 'spot' if isSpot else 'swap'
|
|
462
|
+
market = self.safe_market(marketId, None, None, defaultType)
|
|
463
|
+
symbol = market['symbol']
|
|
464
|
+
messageHash = 'myTrades:' + symbol
|
|
465
|
+
messageWithType = 'myTrades:' + market['type']
|
|
466
|
+
stored = self.safe_value(self.trades, symbol)
|
|
467
|
+
if stored is None:
|
|
468
|
+
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
|
469
|
+
stored = ArrayCache(limit)
|
|
470
|
+
self.trades[symbol] = stored
|
|
471
|
+
parsed = self.parse_ws_trade(data, market)
|
|
472
|
+
stored.append(parsed)
|
|
473
|
+
self.trades[symbol] = stored
|
|
474
|
+
client.resolve(self.trades[symbol], messageWithType)
|
|
475
|
+
client.resolve(self.trades[symbol], messageHash)
|
|
280
476
|
|
|
281
477
|
def handle_trades(self, client: Client, message):
|
|
478
|
+
#
|
|
479
|
+
# spot
|
|
282
480
|
#
|
|
283
481
|
# {
|
|
284
482
|
# "method": "deals.update",
|
|
285
|
-
# "
|
|
286
|
-
# "
|
|
287
|
-
# [
|
|
288
|
-
#
|
|
289
|
-
#
|
|
290
|
-
#
|
|
291
|
-
#
|
|
292
|
-
#
|
|
293
|
-
#
|
|
294
|
-
#
|
|
483
|
+
# "data": {
|
|
484
|
+
# "market": "BTCUSDT",
|
|
485
|
+
# "deal_list": [
|
|
486
|
+
# {
|
|
487
|
+
# "deal_id": 3514376759,
|
|
488
|
+
# "created_at": 1689152421692,
|
|
489
|
+
# "side": "buy",
|
|
490
|
+
# "price": "30718.42",
|
|
491
|
+
# "amount": "0.00000325"
|
|
492
|
+
# },
|
|
493
|
+
# ]
|
|
494
|
+
# },
|
|
295
495
|
# "id": null
|
|
296
496
|
# }
|
|
297
497
|
#
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
498
|
+
# swap
|
|
499
|
+
#
|
|
500
|
+
# {
|
|
501
|
+
# "method": "deals.update",
|
|
502
|
+
# "data": {
|
|
503
|
+
# "market": "BTCUSDT",
|
|
504
|
+
# "deal_list": [
|
|
505
|
+
# {
|
|
506
|
+
# "deal_id": 3514376759,
|
|
507
|
+
# "created_at": 1689152421692,
|
|
508
|
+
# "side": "buy",
|
|
509
|
+
# "price": "30718.42",
|
|
510
|
+
# "amount": "0.00000325"
|
|
511
|
+
# },
|
|
512
|
+
# ]
|
|
513
|
+
# },
|
|
514
|
+
# "id": null
|
|
515
|
+
# }
|
|
516
|
+
#
|
|
517
|
+
data = self.safe_dict(message, 'data', {})
|
|
518
|
+
trades = self.safe_list(data, 'deal_list', [])
|
|
519
|
+
marketId = self.safe_string(data, 'market')
|
|
520
|
+
isSpot = client.url.find('spot') > -1
|
|
521
|
+
defaultType = 'spot' if isSpot else 'swap'
|
|
302
522
|
market = self.safe_market(marketId, None, None, defaultType)
|
|
303
523
|
symbol = market['symbol']
|
|
304
524
|
messageHash = 'trades:' + symbol
|
|
@@ -315,289 +535,251 @@ class coinex(ccxt.async_support.coinex):
|
|
|
315
535
|
client.resolve(self.trades[symbol], messageHash)
|
|
316
536
|
|
|
317
537
|
def parse_ws_trade(self, trade, market=None):
|
|
538
|
+
#
|
|
539
|
+
# spot watchTrades
|
|
318
540
|
#
|
|
319
541
|
# {
|
|
320
|
-
# "
|
|
321
|
-
# "
|
|
322
|
-
# "
|
|
323
|
-
# "
|
|
324
|
-
# "amount": "0.
|
|
542
|
+
# "deal_id": 3514376759,
|
|
543
|
+
# "created_at": 1689152421692,
|
|
544
|
+
# "side": "buy",
|
|
545
|
+
# "price": "30718.42",
|
|
546
|
+
# "amount": "0.00000325"
|
|
325
547
|
# }
|
|
326
548
|
#
|
|
327
|
-
|
|
328
|
-
|
|
549
|
+
# swap watchTrades
|
|
550
|
+
#
|
|
551
|
+
# {
|
|
552
|
+
# "deal_id": 3514376759,
|
|
553
|
+
# "created_at": 1689152421692,
|
|
554
|
+
# "side": "buy",
|
|
555
|
+
# "price": "30718.42",
|
|
556
|
+
# "amount": "0.00000325"
|
|
557
|
+
# }
|
|
558
|
+
#
|
|
559
|
+
# spot and swap watchMyTrades
|
|
560
|
+
#
|
|
561
|
+
# {
|
|
562
|
+
# "deal_id": 3514376759,
|
|
563
|
+
# "created_at": 1689152421692,
|
|
564
|
+
# "market": "BTCUSDT",
|
|
565
|
+
# "side": "buy",
|
|
566
|
+
# "order_id": 8678890,
|
|
567
|
+
# "margin_market": "BTCUSDT",
|
|
568
|
+
# "price": "30718.42",
|
|
569
|
+
# "amount": "0.00000325",
|
|
570
|
+
# "role": "taker",
|
|
571
|
+
# "fee": "0.0299",
|
|
572
|
+
# "fee_ccy": "USDT"
|
|
573
|
+
# }
|
|
574
|
+
#
|
|
575
|
+
timestamp = self.safe_integer(trade, 'created_at')
|
|
576
|
+
isSpot = ('margin_market' in trade)
|
|
577
|
+
defaultType = 'spot' if isSpot else 'swap'
|
|
578
|
+
marketId = self.safe_string(trade, 'market')
|
|
579
|
+
market = self.safe_market(marketId, market, None, defaultType)
|
|
580
|
+
fee: dict = {}
|
|
581
|
+
feeCost = self.omit_zero(self.safe_string(trade, 'fee'))
|
|
582
|
+
if feeCost is not None:
|
|
583
|
+
feeCurrencyId = self.safe_string(trade, 'fee_ccy', market['quote'])
|
|
584
|
+
fee = {
|
|
585
|
+
'currency': self.safe_currency_code(feeCurrencyId),
|
|
586
|
+
'cost': feeCost,
|
|
587
|
+
}
|
|
329
588
|
return self.safe_trade({
|
|
330
|
-
'id': self.safe_string(trade, '
|
|
589
|
+
'id': self.safe_string(trade, 'deal_id'),
|
|
331
590
|
'info': trade,
|
|
332
591
|
'timestamp': timestamp,
|
|
333
592
|
'datetime': self.iso8601(timestamp),
|
|
334
|
-
'symbol': self.safe_symbol(
|
|
335
|
-
'order':
|
|
593
|
+
'symbol': self.safe_symbol(marketId, market, None, defaultType),
|
|
594
|
+
'order': self.safe_string(trade, 'order_id'),
|
|
336
595
|
'type': None,
|
|
337
|
-
'side': self.safe_string(trade, '
|
|
338
|
-
'takerOrMaker':
|
|
596
|
+
'side': self.safe_string(trade, 'side'),
|
|
597
|
+
'takerOrMaker': self.safe_string(trade, 'role'),
|
|
339
598
|
'price': self.safe_string(trade, 'price'),
|
|
340
599
|
'amount': self.safe_string(trade, 'amount'),
|
|
341
600
|
'cost': None,
|
|
342
|
-
'fee':
|
|
601
|
+
'fee': fee,
|
|
343
602
|
}, market)
|
|
344
603
|
|
|
345
|
-
def handle_ohlcv(self, client: Client, message):
|
|
346
|
-
#
|
|
347
|
-
# spot
|
|
348
|
-
# {
|
|
349
|
-
# "error": null,
|
|
350
|
-
# "result": [
|
|
351
|
-
# [
|
|
352
|
-
# 1673846940,
|
|
353
|
-
# "21148.74",
|
|
354
|
-
# "21148.38",
|
|
355
|
-
# "21148.75",
|
|
356
|
-
# "21138.66",
|
|
357
|
-
# "1.57060173",
|
|
358
|
-
# "33214.9138778914"
|
|
359
|
-
# ],
|
|
360
|
-
# ]
|
|
361
|
-
# "id": 1,
|
|
362
|
-
# }
|
|
363
|
-
# swap
|
|
364
|
-
# {
|
|
365
|
-
# "method": "kline.update",
|
|
366
|
-
# "params": [
|
|
367
|
-
# [
|
|
368
|
-
# 1654019640, # timestamp
|
|
369
|
-
# "32061.99", # open
|
|
370
|
-
# "32061.28", # close
|
|
371
|
-
# "32061.99", # high
|
|
372
|
-
# "32061.28", # low
|
|
373
|
-
# "0.1285", # amount base
|
|
374
|
-
# "4119.943736" # amount quote
|
|
375
|
-
# ]
|
|
376
|
-
# ],
|
|
377
|
-
# "id": null
|
|
378
|
-
# }
|
|
379
|
-
#
|
|
380
|
-
candles = self.safe_value_2(message, 'params', 'result', [])
|
|
381
|
-
messageHash = 'ohlcv'
|
|
382
|
-
id = self.safe_string(message, 'id')
|
|
383
|
-
ohlcvs = self.parse_ohlcvs(candles)
|
|
384
|
-
if id is not None:
|
|
385
|
-
# spot subscription response
|
|
386
|
-
client.resolve(ohlcvs, messageHash)
|
|
387
|
-
return
|
|
388
|
-
keys = list(self.ohlcvs.keys())
|
|
389
|
-
keysLength = len(keys)
|
|
390
|
-
if keysLength == 0:
|
|
391
|
-
self.ohlcvs['unknown'] = {}
|
|
392
|
-
limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
|
|
393
|
-
stored = ArrayCacheByTimestamp(limit)
|
|
394
|
-
self.ohlcvs['unknown']['unknown'] = stored
|
|
395
|
-
ohlcv = self.ohlcvs['unknown']['unknown']
|
|
396
|
-
for i in range(0, len(ohlcvs)):
|
|
397
|
-
candle = ohlcvs[i]
|
|
398
|
-
ohlcv.append(candle)
|
|
399
|
-
client.resolve(ohlcv, messageHash)
|
|
400
|
-
|
|
401
604
|
async def watch_ticker(self, symbol: str, params={}) -> Ticker:
|
|
402
605
|
"""
|
|
403
|
-
:see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot004_websocket007_state_subscribe
|
|
404
606
|
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
607
|
+
|
|
608
|
+
https://docs.coinex.com/api/v2/spot/market/ws/market
|
|
609
|
+
https://docs.coinex.com/api/v2/futures/market/ws/market-state
|
|
610
|
+
|
|
405
611
|
:param str symbol: unified symbol of the market to fetch the ticker for
|
|
406
612
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
407
613
|
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
|
408
614
|
"""
|
|
615
|
+
await self.load_markets()
|
|
616
|
+
market = self.market(symbol)
|
|
409
617
|
tickers = await self.watch_tickers([symbol], params)
|
|
410
|
-
return
|
|
618
|
+
return tickers[market['symbol']]
|
|
411
619
|
|
|
412
620
|
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
|
413
621
|
"""
|
|
414
|
-
:see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot004_websocket007_state_subscribe
|
|
415
622
|
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
|
623
|
+
|
|
624
|
+
https://docs.coinex.com/api/v2/spot/market/ws/market
|
|
625
|
+
https://docs.coinex.com/api/v2/futures/market/ws/market-state
|
|
626
|
+
|
|
416
627
|
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
|
417
628
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
418
629
|
:returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
|
|
419
630
|
"""
|
|
420
631
|
await self.load_markets()
|
|
421
|
-
|
|
632
|
+
marketIds = self.market_ids(symbols)
|
|
633
|
+
market = None
|
|
634
|
+
messageHashes = []
|
|
635
|
+
symbolsDefined = (symbols is not None)
|
|
636
|
+
if symbolsDefined:
|
|
637
|
+
for i in range(0, len(symbols)):
|
|
638
|
+
symbol = symbols[i]
|
|
639
|
+
market = self.market(symbol)
|
|
640
|
+
messageHashes.append('tickers::' + market['symbol'])
|
|
641
|
+
else:
|
|
642
|
+
messageHashes.append('tickers')
|
|
422
643
|
type = None
|
|
423
|
-
type, params = self.handle_market_type_and_params('watchTickers',
|
|
644
|
+
type, params = self.handle_market_type_and_params('watchTickers', market, params)
|
|
424
645
|
url = self.urls['api']['ws'][type]
|
|
425
|
-
|
|
426
|
-
if symbols is not None:
|
|
427
|
-
messageHash = 'tickers::' + ','.join(symbols)
|
|
646
|
+
subscriptionHashes = ['all@ticker']
|
|
428
647
|
subscribe: dict = {
|
|
429
648
|
'method': 'state.subscribe',
|
|
649
|
+
'params': {'market_list': marketIds},
|
|
430
650
|
'id': self.request_id(),
|
|
431
|
-
'params': [],
|
|
432
651
|
}
|
|
433
|
-
|
|
434
|
-
newTickers = await self.watch(url, messageHash, request, messageHash)
|
|
652
|
+
result = await self.watch_multiple(url, messageHashes, self.deep_extend(subscribe, params), subscriptionHashes)
|
|
435
653
|
if self.newUpdates:
|
|
436
|
-
return
|
|
654
|
+
return result
|
|
437
655
|
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
|
438
656
|
|
|
439
657
|
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
|
440
658
|
"""
|
|
441
|
-
:see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot004_websocket012_deal_subcribe
|
|
442
|
-
:see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures002_websocket019_deal_subcribe
|
|
443
659
|
get the list of most recent trades for a particular symbol
|
|
660
|
+
|
|
661
|
+
https://docs.coinex.com/api/v2/spot/market/ws/market-deals
|
|
662
|
+
https://docs.coinex.com/api/v2/futures/market/ws/market-deals
|
|
663
|
+
|
|
444
664
|
:param str symbol: unified symbol of the market to fetch trades for
|
|
445
665
|
:param int [since]: timestamp in ms of the earliest trade to fetch
|
|
446
666
|
:param int [limit]: the maximum amount of trades to fetch
|
|
447
667
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
448
668
|
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
|
449
669
|
"""
|
|
670
|
+
params['callerMethodName'] = 'watchTrades'
|
|
671
|
+
return await self.watch_trades_for_symbols([symbol], since, limit, params)
|
|
672
|
+
|
|
673
|
+
async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
|
674
|
+
"""
|
|
675
|
+
watch the most recent trades for a list of symbols
|
|
676
|
+
|
|
677
|
+
https://docs.coinex.com/api/v2/spot/market/ws/market-deals
|
|
678
|
+
https://docs.coinex.com/api/v2/futures/market/ws/market-deals
|
|
679
|
+
|
|
680
|
+
:param str[] symbols: unified symbols of the markets to fetch trades for
|
|
681
|
+
:param int [since]: timestamp in ms of the earliest trade to fetch
|
|
682
|
+
:param int [limit]: the maximum amount of trades to fetch
|
|
683
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
684
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
|
685
|
+
"""
|
|
450
686
|
await self.load_markets()
|
|
451
|
-
|
|
687
|
+
subscribedSymbols = []
|
|
688
|
+
messageHashes = []
|
|
689
|
+
market = None
|
|
690
|
+
callerMethodName = None
|
|
691
|
+
callerMethodName, params = self.handle_param_string(params, 'callerMethodName', 'watchTradesForSymbols')
|
|
692
|
+
symbolsDefined = (symbols is not None)
|
|
693
|
+
if symbolsDefined:
|
|
694
|
+
for i in range(0, len(symbols)):
|
|
695
|
+
symbol = symbols[i]
|
|
696
|
+
market = self.market(symbol)
|
|
697
|
+
subscribedSymbols.append(market['id'])
|
|
698
|
+
messageHashes.append('trades:' + market['symbol'])
|
|
699
|
+
else:
|
|
700
|
+
messageHashes.append('trades')
|
|
452
701
|
type = None
|
|
453
|
-
type, params = self.handle_market_type_and_params(
|
|
702
|
+
type, params = self.handle_market_type_and_params(callerMethodName, market, params)
|
|
454
703
|
url = self.urls['api']['ws'][type]
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
subscribedSymbols = self.safe_value(self.options, 'watchTradesSubscriptions', [])
|
|
458
|
-
subscribedSymbols.append(market['id'])
|
|
459
|
-
message: dict = {
|
|
704
|
+
subscriptionHashes = ['trades']
|
|
705
|
+
subscribe: dict = {
|
|
460
706
|
'method': 'deals.subscribe',
|
|
461
|
-
'params': subscribedSymbols,
|
|
707
|
+
'params': {'market_list': subscribedSymbols},
|
|
462
708
|
'id': self.request_id(),
|
|
463
709
|
}
|
|
464
|
-
self.
|
|
465
|
-
|
|
466
|
-
|
|
710
|
+
trades = await self.watch_multiple(url, messageHashes, self.deep_extend(subscribe, params), subscriptionHashes)
|
|
711
|
+
if self.newUpdates:
|
|
712
|
+
return trades
|
|
467
713
|
return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
|
|
468
714
|
|
|
469
|
-
async def
|
|
715
|
+
async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
|
|
470
716
|
"""
|
|
471
|
-
:see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot004_websocket017_depth_subscribe_multi
|
|
472
|
-
:see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures002_websocket011_depth_subscribe_multi
|
|
473
717
|
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
|
474
|
-
|
|
718
|
+
|
|
719
|
+
https://docs.coinex.com/api/v2/spot/market/ws/market-depth
|
|
720
|
+
https://docs.coinex.com/api/v2/futures/market/ws/market-depth
|
|
721
|
+
|
|
722
|
+
:param str[] symbols: unified array of symbols
|
|
475
723
|
:param int [limit]: the maximum amount of order book entries to return
|
|
476
724
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
477
725
|
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
|
478
726
|
"""
|
|
479
727
|
await self.load_markets()
|
|
480
|
-
|
|
481
|
-
|
|
728
|
+
watchOrderBookSubscriptions: dict = {}
|
|
729
|
+
messageHashes = []
|
|
730
|
+
market = None
|
|
482
731
|
type = None
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
limits = self.safe_value(options, 'limits', [])
|
|
732
|
+
callerMethodName = None
|
|
733
|
+
callerMethodName, params = self.handle_param_string(params, 'callerMethodName', 'watchOrderBookForSymbols')
|
|
734
|
+
type, params = self.handle_market_type_and_params(callerMethodName, None, params)
|
|
735
|
+
options = self.safe_dict(self.options, 'watchOrderBook', {})
|
|
736
|
+
limits = self.safe_list(options, 'limits', [])
|
|
489
737
|
if limit is None:
|
|
490
|
-
limit = self.
|
|
738
|
+
limit = self.safe_integer(options, 'defaultLimit', 50)
|
|
491
739
|
if not self.in_array(limit, limits):
|
|
492
|
-
raise NotSupported(self.id + '
|
|
740
|
+
raise NotSupported(self.id + ' watchOrderBookForSymbols() limit must be one of ' + ', '.join(limits))
|
|
493
741
|
defaultAggregation = self.safe_string(options, 'defaultAggregation', '0')
|
|
494
|
-
aggregations = self.
|
|
742
|
+
aggregations = self.safe_list(options, 'aggregations', [])
|
|
495
743
|
aggregation = self.safe_string(params, 'aggregation', defaultAggregation)
|
|
496
744
|
if not self.in_array(aggregation, aggregations):
|
|
497
|
-
raise NotSupported(self.id + '
|
|
745
|
+
raise NotSupported(self.id + ' watchOrderBookForSymbols() aggregation must be one of ' + ', '.join(aggregations))
|
|
498
746
|
params = self.omit(params, 'aggregation')
|
|
499
|
-
|
|
500
|
-
|
|
747
|
+
symbolsDefined = (symbols is not None)
|
|
748
|
+
if symbolsDefined:
|
|
749
|
+
for i in range(0, len(symbols)):
|
|
750
|
+
symbol = symbols[i]
|
|
751
|
+
market = self.market(symbol)
|
|
752
|
+
messageHashes.append('orderbook:' + market['symbol'])
|
|
753
|
+
watchOrderBookSubscriptions[symbol] = [market['id'], limit, aggregation, True]
|
|
754
|
+
else:
|
|
755
|
+
messageHashes.append('orderbook')
|
|
756
|
+
marketList = list(watchOrderBookSubscriptions.values())
|
|
501
757
|
subscribe: dict = {
|
|
502
|
-
'method': 'depth.
|
|
758
|
+
'method': 'depth.subscribe',
|
|
759
|
+
'params': {'market_list': marketList},
|
|
503
760
|
'id': self.request_id(),
|
|
504
|
-
'params': list(watchOrderBookSubscriptions.values()),
|
|
505
761
|
}
|
|
506
|
-
self.
|
|
507
|
-
subscriptionHash = self.hash(self.encode(self.json(watchOrderBookSubscriptions)), 'sha256')
|
|
508
|
-
request = self.deep_extend(subscribe, params)
|
|
509
|
-
orderbook = await self.watch(url, messageHash, request, subscriptionHash, request)
|
|
510
|
-
return orderbook.limit()
|
|
511
|
-
|
|
512
|
-
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
|
513
|
-
"""
|
|
514
|
-
:see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures002_websocket023_kline_subscribe
|
|
515
|
-
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
516
|
-
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
|
517
|
-
:param str timeframe: the length of time each candle represents
|
|
518
|
-
:param int [since]: timestamp in ms of the earliest candle to fetch
|
|
519
|
-
:param int [limit]: the maximum amount of candles to fetch
|
|
520
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
521
|
-
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
|
522
|
-
"""
|
|
523
|
-
await self.load_markets()
|
|
524
|
-
market = self.market(symbol)
|
|
525
|
-
symbol = market['symbol']
|
|
526
|
-
type = None
|
|
527
|
-
type, params = self.handle_market_type_and_params('watchOHLCV', market, params)
|
|
528
|
-
if type != 'swap':
|
|
529
|
-
raise NotSupported(self.id + ' watchOHLCV() is only supported for swap markets. Try using fetchOHLCV() instead')
|
|
762
|
+
subscriptionHashes = self.hash(self.encode(self.json(watchOrderBookSubscriptions)), 'sha256')
|
|
530
763
|
url = self.urls['api']['ws'][type]
|
|
531
|
-
|
|
532
|
-
watchOHLCVWarning = self.safe_bool(self.options, 'watchOHLCVWarning', True)
|
|
533
|
-
client = self.safe_value(self.clients, url, {})
|
|
534
|
-
clientSub = self.safe_value(client, 'subscriptions', {})
|
|
535
|
-
existingSubscription = self.safe_value(clientSub, messageHash)
|
|
536
|
-
subSymbol = self.safe_string(existingSubscription, 'symbol')
|
|
537
|
-
subTimeframe = self.safe_string(existingSubscription, 'timeframe')
|
|
538
|
-
# due to nature of coinex response can only watch one symbol at a time
|
|
539
|
-
if watchOHLCVWarning and existingSubscription is not None and (subSymbol != symbol or subTimeframe != timeframe):
|
|
540
|
-
raise ExchangeError(self.id + ' watchOHLCV() can only watch one symbol and timeframe at a time. To supress self warning set watchOHLCVWarning to False in options')
|
|
541
|
-
timeframes = self.safe_value(self.options, 'timeframes', {})
|
|
542
|
-
subscribe: dict = {
|
|
543
|
-
'method': 'kline.subscribe',
|
|
544
|
-
'id': self.request_id(),
|
|
545
|
-
'params': [
|
|
546
|
-
market['id'],
|
|
547
|
-
self.safe_integer(timeframes, timeframe),
|
|
548
|
-
],
|
|
549
|
-
}
|
|
550
|
-
subscription: dict = {
|
|
551
|
-
'symbol': symbol,
|
|
552
|
-
'timeframe': timeframe,
|
|
553
|
-
}
|
|
554
|
-
request = self.deep_extend(subscribe, params)
|
|
555
|
-
ohlcvs = await self.watch(url, messageHash, request, messageHash, subscription)
|
|
764
|
+
orderbooks = await self.watch_multiple(url, messageHashes, self.deep_extend(subscribe, params), subscriptionHashes)
|
|
556
765
|
if self.newUpdates:
|
|
557
|
-
|
|
558
|
-
return
|
|
766
|
+
return orderbooks
|
|
767
|
+
return orderbooks.limit()
|
|
559
768
|
|
|
560
|
-
async def
|
|
769
|
+
async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
|
561
770
|
"""
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
:param
|
|
568
|
-
:param
|
|
569
|
-
:param
|
|
570
|
-
:returns
|
|
771
|
+
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
|
772
|
+
|
|
773
|
+
https://docs.coinex.com/api/v2/spot/market/ws/market-depth
|
|
774
|
+
https://docs.coinex.com/api/v2/futures/market/ws/market-depth
|
|
775
|
+
|
|
776
|
+
:param str symbol: unified symbol of the market to fetch the order book for
|
|
777
|
+
:param int [limit]: the maximum amount of order book entries to return
|
|
778
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
779
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
|
571
780
|
"""
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
type, query = self.handle_market_type_and_params('fetchOHLCV', market, params)
|
|
575
|
-
url = self.urls['api']['ws'][type]
|
|
576
|
-
symbol = market['symbol']
|
|
577
|
-
messageHash = 'ohlcv'
|
|
578
|
-
timeframes = self.safe_value(self.options, 'timeframes', {})
|
|
579
|
-
timeframe = self.safe_string(timeframes, timeframe, timeframe)
|
|
580
|
-
if since is None:
|
|
581
|
-
since = 1640995200 # January 1, 2022
|
|
582
|
-
id = self.request_id()
|
|
583
|
-
subscribe: dict = {
|
|
584
|
-
'method': 'kline.query',
|
|
585
|
-
'params': [
|
|
586
|
-
market['id'],
|
|
587
|
-
self.parse_to_int(since / 1000),
|
|
588
|
-
self.safe_integer(params, 'end', self.seconds()),
|
|
589
|
-
self.parse_to_int(timeframe),
|
|
590
|
-
],
|
|
591
|
-
'id': id,
|
|
592
|
-
}
|
|
593
|
-
subscription: dict = {
|
|
594
|
-
'id': id,
|
|
595
|
-
'future': messageHash,
|
|
596
|
-
}
|
|
597
|
-
subscriptionHash = id
|
|
598
|
-
request = self.deep_extend(subscribe, query)
|
|
599
|
-
ohlcvs = await self.watch(url, messageHash, request, subscriptionHash, subscription)
|
|
600
|
-
return self.filter_by_since_limit(ohlcvs, since, limit, 0)
|
|
781
|
+
params['callerMethodName'] = 'watchOrderBook'
|
|
782
|
+
return await self.watch_order_book_for_symbols([symbol], limit, params)
|
|
601
783
|
|
|
602
784
|
def handle_delta(self, bookside, delta):
|
|
603
785
|
bidAsk = self.parse_bid_ask(delta, 0, 1)
|
|
@@ -611,49 +793,51 @@ class coinex(ccxt.async_support.coinex):
|
|
|
611
793
|
#
|
|
612
794
|
# {
|
|
613
795
|
# "method": "depth.update",
|
|
614
|
-
# "
|
|
615
|
-
#
|
|
616
|
-
#
|
|
796
|
+
# "data": {
|
|
797
|
+
# "market": "BTCUSDT",
|
|
798
|
+
# "is_full": True,
|
|
799
|
+
# "depth": {
|
|
617
800
|
# "asks": [
|
|
618
|
-
# [
|
|
619
|
-
#
|
|
801
|
+
# [
|
|
802
|
+
# "30740.00",
|
|
803
|
+
# "0.31763545"
|
|
804
|
+
# ],
|
|
620
805
|
# ],
|
|
621
806
|
# "bids": [
|
|
622
|
-
# [
|
|
623
|
-
#
|
|
807
|
+
# [
|
|
808
|
+
# "30736.00",
|
|
809
|
+
# "0.04857373"
|
|
810
|
+
# ],
|
|
624
811
|
# ],
|
|
625
|
-
# "last": "
|
|
626
|
-
# "
|
|
627
|
-
# "checksum":
|
|
628
|
-
# }
|
|
629
|
-
#
|
|
630
|
-
# ],
|
|
812
|
+
# "last": "30746.28",
|
|
813
|
+
# "updated_at": 1689152421692,
|
|
814
|
+
# "checksum": 2578768879
|
|
815
|
+
# }
|
|
816
|
+
# },
|
|
631
817
|
# "id": null
|
|
632
818
|
# }
|
|
633
819
|
#
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
marketId = self.safe_string(params, 2)
|
|
640
|
-
market = self.safe_market(marketId, None, None, marketType)
|
|
820
|
+
defaultType = self.safe_string(self.options, 'defaultType')
|
|
821
|
+
data = self.safe_dict(message, 'data', {})
|
|
822
|
+
depth = self.safe_dict(data, 'depth', {})
|
|
823
|
+
marketId = self.safe_string(data, 'market')
|
|
824
|
+
market = self.safe_market(marketId, None, None, defaultType)
|
|
641
825
|
symbol = market['symbol']
|
|
642
826
|
name = 'orderbook'
|
|
643
827
|
messageHash = name + ':' + symbol
|
|
644
|
-
timestamp = self.safe_integer(
|
|
828
|
+
timestamp = self.safe_integer(depth, 'updated_at')
|
|
645
829
|
currentOrderBook = self.safe_value(self.orderbooks, symbol)
|
|
830
|
+
fullOrderBook = self.safe_bool(data, 'is_full', False)
|
|
646
831
|
if fullOrderBook:
|
|
647
|
-
snapshot = self.parse_order_book(
|
|
832
|
+
snapshot = self.parse_order_book(depth, symbol, timestamp)
|
|
648
833
|
if currentOrderBook is None:
|
|
649
|
-
|
|
650
|
-
self.orderbooks[symbol] = orderbook
|
|
834
|
+
self.orderbooks[symbol] = self.order_book(snapshot)
|
|
651
835
|
else:
|
|
652
836
|
orderbook = self.orderbooks[symbol]
|
|
653
837
|
orderbook.reset(snapshot)
|
|
654
838
|
else:
|
|
655
|
-
asks = self.
|
|
656
|
-
bids = self.
|
|
839
|
+
asks = self.safe_list(depth, 'asks', [])
|
|
840
|
+
bids = self.safe_list(depth, 'bids', [])
|
|
657
841
|
self.handle_deltas(currentOrderBook['asks'], asks)
|
|
658
842
|
self.handle_deltas(currentOrderBook['bids'], bids)
|
|
659
843
|
currentOrderBook['nonce'] = timestamp
|
|
@@ -664,24 +848,52 @@ class coinex(ccxt.async_support.coinex):
|
|
|
664
848
|
client.resolve(self.orderbooks[symbol], messageHash)
|
|
665
849
|
|
|
666
850
|
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
|
851
|
+
"""
|
|
852
|
+
watches information on multiple orders made by the user
|
|
853
|
+
|
|
854
|
+
https://docs.coinex.com/api/v2/spot/order/ws/user-order
|
|
855
|
+
https://docs.coinex.com/api/v2/futures/order/ws/user-order
|
|
856
|
+
|
|
857
|
+
:param str symbol: unified market symbol of the market orders were made in
|
|
858
|
+
:param int [since]: the earliest time in ms to fetch orders for
|
|
859
|
+
:param int [limit]: the maximum number of order structures to retrieve
|
|
860
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
861
|
+
:param bool [params.trigger]: if the orders to watch are trigger orders or not
|
|
862
|
+
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
|
863
|
+
"""
|
|
667
864
|
await self.load_markets()
|
|
668
|
-
|
|
865
|
+
trigger = self.safe_bool_2(params, 'trigger', 'stop')
|
|
866
|
+
params = self.omit(params, ['trigger', 'stop'])
|
|
669
867
|
messageHash = 'orders'
|
|
670
868
|
market = None
|
|
671
|
-
|
|
672
|
-
message: dict = {
|
|
673
|
-
'method': 'order.subscribe',
|
|
674
|
-
'id': self.request_id(),
|
|
675
|
-
}
|
|
869
|
+
marketList = None
|
|
676
870
|
if symbol is not None:
|
|
677
871
|
market = self.market(symbol)
|
|
678
872
|
symbol = market['symbol']
|
|
679
|
-
|
|
873
|
+
type = None
|
|
874
|
+
type, params = self.handle_market_type_and_params('watchOrders', market, params, 'spot')
|
|
875
|
+
await self.authenticate(type)
|
|
876
|
+
if symbol is not None:
|
|
877
|
+
marketList = [market['id']]
|
|
680
878
|
messageHash += ':' + symbol
|
|
681
879
|
else:
|
|
682
|
-
|
|
880
|
+
marketList = []
|
|
881
|
+
if type == 'spot':
|
|
882
|
+
messageHash += ':spot'
|
|
883
|
+
else:
|
|
884
|
+
messageHash += ':swap'
|
|
885
|
+
method = None
|
|
886
|
+
if trigger:
|
|
887
|
+
method = 'stop.subscribe'
|
|
888
|
+
else:
|
|
889
|
+
method = 'order.subscribe'
|
|
890
|
+
message: dict = {
|
|
891
|
+
'method': method,
|
|
892
|
+
'params': {'market_list': marketList},
|
|
893
|
+
'id': self.request_id(),
|
|
894
|
+
}
|
|
683
895
|
url = self.urls['api']['ws'][type]
|
|
684
|
-
request = self.deep_extend(message,
|
|
896
|
+
request = self.deep_extend(message, params)
|
|
685
897
|
orders = await self.watch(url, messageHash, request, messageHash, request)
|
|
686
898
|
if self.newUpdates:
|
|
687
899
|
limit = orders.getLimit(symbol, limit)
|
|
@@ -689,255 +901,260 @@ class coinex(ccxt.async_support.coinex):
|
|
|
689
901
|
|
|
690
902
|
def handle_orders(self, client: Client, message):
|
|
691
903
|
#
|
|
692
|
-
#
|
|
904
|
+
# spot
|
|
693
905
|
#
|
|
694
|
-
#
|
|
695
|
-
#
|
|
696
|
-
#
|
|
697
|
-
#
|
|
698
|
-
#
|
|
699
|
-
#
|
|
700
|
-
#
|
|
701
|
-
#
|
|
702
|
-
#
|
|
703
|
-
#
|
|
704
|
-
#
|
|
705
|
-
#
|
|
706
|
-
#
|
|
707
|
-
#
|
|
708
|
-
#
|
|
709
|
-
#
|
|
710
|
-
#
|
|
711
|
-
#
|
|
712
|
-
#
|
|
713
|
-
#
|
|
714
|
-
#
|
|
715
|
-
#
|
|
716
|
-
#
|
|
717
|
-
#
|
|
718
|
-
#
|
|
719
|
-
#
|
|
720
|
-
#
|
|
721
|
-
#
|
|
722
|
-
# "last_deal_price": "0",
|
|
723
|
-
# "last_deal_time": 0,
|
|
724
|
-
# "last_deal_id": 0,
|
|
725
|
-
# "last_role": 0,
|
|
726
|
-
# "fee_asset": null,
|
|
727
|
-
# "stop_id": 0
|
|
728
|
-
# }
|
|
729
|
-
# ],
|
|
730
|
-
# "id": null
|
|
731
|
-
# }
|
|
906
|
+
# {
|
|
907
|
+
# "method": "order.update",
|
|
908
|
+
# "data": {
|
|
909
|
+
# "event": "put",
|
|
910
|
+
# "order": {
|
|
911
|
+
# "order_id": 12750,
|
|
912
|
+
# "market": "BTCUSDT",
|
|
913
|
+
# "margin_market": "BTCUSDT",
|
|
914
|
+
# "type": "limit",
|
|
915
|
+
# "side": "buy",
|
|
916
|
+
# "price": "5999.00",
|
|
917
|
+
# "amount": "1.50000000",
|
|
918
|
+
# "unfill_amount": "1.50000000",
|
|
919
|
+
# "fill_value": "1.50000000",
|
|
920
|
+
# "taker_fee_rate": "0.0001",
|
|
921
|
+
# "maker_fee_rate": "0.0001",
|
|
922
|
+
# "base_ccy_fee": "0.0001",
|
|
923
|
+
# "quote_ccy_fee": "0.0001",
|
|
924
|
+
# "discount_ccy_fee": "0.0001",
|
|
925
|
+
# "last_fill_amount": "0",
|
|
926
|
+
# "last_fill_price": "0",
|
|
927
|
+
# "client_id": "buy1_1234",
|
|
928
|
+
# "created_at": 1689152421692,
|
|
929
|
+
# "updated_at": 1689152421692,
|
|
930
|
+
# }
|
|
931
|
+
# },
|
|
932
|
+
# "id": null
|
|
933
|
+
# }
|
|
732
934
|
#
|
|
733
|
-
#
|
|
935
|
+
# spot stop
|
|
734
936
|
#
|
|
735
|
-
#
|
|
736
|
-
#
|
|
737
|
-
#
|
|
738
|
-
#
|
|
739
|
-
#
|
|
740
|
-
#
|
|
741
|
-
#
|
|
742
|
-
#
|
|
743
|
-
#
|
|
744
|
-
#
|
|
745
|
-
#
|
|
746
|
-
#
|
|
747
|
-
#
|
|
748
|
-
#
|
|
749
|
-
#
|
|
750
|
-
#
|
|
751
|
-
#
|
|
752
|
-
#
|
|
753
|
-
#
|
|
754
|
-
#
|
|
755
|
-
#
|
|
756
|
-
#
|
|
757
|
-
#
|
|
758
|
-
#
|
|
759
|
-
#
|
|
760
|
-
#
|
|
761
|
-
#
|
|
762
|
-
#
|
|
763
|
-
#
|
|
764
|
-
#
|
|
765
|
-
#
|
|
766
|
-
#
|
|
767
|
-
#
|
|
768
|
-
#
|
|
769
|
-
#
|
|
770
|
-
#
|
|
771
|
-
#
|
|
772
|
-
#
|
|
773
|
-
#
|
|
774
|
-
#
|
|
775
|
-
#
|
|
776
|
-
#
|
|
777
|
-
|
|
778
|
-
|
|
937
|
+
# {
|
|
938
|
+
# "method": "stop.update",
|
|
939
|
+
# "data": {
|
|
940
|
+
# "event": 1,
|
|
941
|
+
# "stop": {
|
|
942
|
+
# "stop_id": 102067022299,
|
|
943
|
+
# "market": "BTCUSDT",
|
|
944
|
+
# "margin_market": "BTCUSDT",
|
|
945
|
+
# "type": "limit",
|
|
946
|
+
# "side": "buy",
|
|
947
|
+
# "price": "20000.00",
|
|
948
|
+
# "amount": "0.10000000",
|
|
949
|
+
# "trigger_price": "20000.00",
|
|
950
|
+
# "trigger_direction": "lower",
|
|
951
|
+
# "taker_fee_rate": "0.0016",
|
|
952
|
+
# "maker_fee_rate": "0.0016",
|
|
953
|
+
# "status": "active_success",
|
|
954
|
+
# "client_id": "",
|
|
955
|
+
# "created_at": 1689152996689,
|
|
956
|
+
# "updated_at": 1689152996689,
|
|
957
|
+
# }
|
|
958
|
+
# },
|
|
959
|
+
# "id": null
|
|
960
|
+
# }
|
|
961
|
+
#
|
|
962
|
+
# swap
|
|
963
|
+
#
|
|
964
|
+
# {
|
|
965
|
+
# "method": "order.update",
|
|
966
|
+
# "data": {
|
|
967
|
+
# "event": "put",
|
|
968
|
+
# "order": {
|
|
969
|
+
# "order_id": 98388656341,
|
|
970
|
+
# "stop_id": 0,
|
|
971
|
+
# "market": "BTCUSDT",
|
|
972
|
+
# "side": "buy",
|
|
973
|
+
# "type": "limit",
|
|
974
|
+
# "amount": "0.0010",
|
|
975
|
+
# "price": "50000.00",
|
|
976
|
+
# "unfilled_amount": "0.0010",
|
|
977
|
+
# "filled_amount": "0",
|
|
978
|
+
# "filled_value": "0",
|
|
979
|
+
# "fee": "0",
|
|
980
|
+
# "fee_ccy": "USDT",
|
|
981
|
+
# "taker_fee_rate": "0.00046",
|
|
982
|
+
# "maker_fee_rate": "0.00000000000000000000",
|
|
983
|
+
# "client_id": "",
|
|
984
|
+
# "last_filled_amount": "0.0010",
|
|
985
|
+
# "last_filled_price": "30721.35",
|
|
986
|
+
# "created_at": 1689145715129,
|
|
987
|
+
# "updated_at": 1689145715129
|
|
988
|
+
# }
|
|
989
|
+
# },
|
|
990
|
+
# "id": null
|
|
991
|
+
# }
|
|
992
|
+
#
|
|
993
|
+
# swap stop
|
|
994
|
+
#
|
|
995
|
+
# {
|
|
996
|
+
# "method": "stop.update",
|
|
997
|
+
# "data": {
|
|
998
|
+
# "event": "put",
|
|
999
|
+
# "stop": {
|
|
1000
|
+
# "stop_id": 98389557871,
|
|
1001
|
+
# "market": "BTCUSDT",
|
|
1002
|
+
# "side": "sell",
|
|
1003
|
+
# "type": "limit",
|
|
1004
|
+
# "price": "20000.00",
|
|
1005
|
+
# "amount": "0.0100",
|
|
1006
|
+
# "trigger_price": "20000.00",
|
|
1007
|
+
# "trigger_direction": "higer",
|
|
1008
|
+
# "trigger_price_type": "index_price",
|
|
1009
|
+
# "taker_fee_rate": "0.00046",
|
|
1010
|
+
# "maker_fee_rate": "0.00026",
|
|
1011
|
+
# "client_id": "",
|
|
1012
|
+
# "created_at": 1689146382674,
|
|
1013
|
+
# "updated_at": 1689146382674
|
|
1014
|
+
# }
|
|
1015
|
+
# },
|
|
1016
|
+
# "id": null
|
|
1017
|
+
# }
|
|
1018
|
+
#
|
|
1019
|
+
data = self.safe_dict(message, 'data', {})
|
|
1020
|
+
order = self.safe_dict_2(data, 'order', 'stop', {})
|
|
779
1021
|
parsedOrder = self.parse_ws_order(order)
|
|
1022
|
+
symbol = parsedOrder['symbol']
|
|
1023
|
+
market = self.market(symbol)
|
|
780
1024
|
if self.orders is None:
|
|
781
1025
|
limit = self.safe_integer(self.options, 'ordersLimit', 1000)
|
|
782
1026
|
self.orders = ArrayCacheBySymbolById(limit)
|
|
783
1027
|
orders = self.orders
|
|
784
1028
|
orders.append(parsedOrder)
|
|
785
1029
|
messageHash = 'orders'
|
|
786
|
-
|
|
787
|
-
|
|
1030
|
+
messageWithType = messageHash + ':' + market['type']
|
|
1031
|
+
client.resolve(self.orders, messageWithType)
|
|
1032
|
+
messageHash += ':' + symbol
|
|
788
1033
|
client.resolve(self.orders, messageHash)
|
|
789
1034
|
|
|
790
1035
|
def parse_ws_order(self, order, market=None):
|
|
791
1036
|
#
|
|
792
|
-
#
|
|
1037
|
+
# spot
|
|
793
1038
|
#
|
|
794
|
-
#
|
|
795
|
-
#
|
|
796
|
-
#
|
|
797
|
-
#
|
|
798
|
-
#
|
|
799
|
-
#
|
|
800
|
-
#
|
|
801
|
-
#
|
|
802
|
-
#
|
|
803
|
-
#
|
|
804
|
-
#
|
|
805
|
-
#
|
|
806
|
-
#
|
|
807
|
-
#
|
|
808
|
-
#
|
|
809
|
-
#
|
|
810
|
-
#
|
|
811
|
-
#
|
|
812
|
-
#
|
|
813
|
-
#
|
|
814
|
-
#
|
|
815
|
-
# "asset_fee": "0",
|
|
816
|
-
# "fee_discount": "1",
|
|
817
|
-
# "last_deal_amount": "0",
|
|
818
|
-
# "last_deal_price": "0",
|
|
819
|
-
# "last_deal_time": 0,
|
|
820
|
-
# "last_deal_id": 0,
|
|
821
|
-
# "last_role": 0,
|
|
822
|
-
# "fee_asset": null,
|
|
823
|
-
# "stop_id": 0
|
|
824
|
-
# }
|
|
1039
|
+
# {
|
|
1040
|
+
# "order_id": 12750,
|
|
1041
|
+
# "market": "BTCUSDT",
|
|
1042
|
+
# "margin_market": "BTCUSDT",
|
|
1043
|
+
# "type": "limit",
|
|
1044
|
+
# "side": "buy",
|
|
1045
|
+
# "price": "5999.00",
|
|
1046
|
+
# "amount": "1.50000000",
|
|
1047
|
+
# "unfill_amount": "1.50000000",
|
|
1048
|
+
# "fill_value": "1.50000000",
|
|
1049
|
+
# "taker_fee_rate": "0.0001",
|
|
1050
|
+
# "maker_fee_rate": "0.0001",
|
|
1051
|
+
# "base_ccy_fee": "0.0001",
|
|
1052
|
+
# "quote_ccy_fee": "0.0001",
|
|
1053
|
+
# "discount_ccy_fee": "0.0001",
|
|
1054
|
+
# "last_fill_amount": "0",
|
|
1055
|
+
# "last_fill_price": "0",
|
|
1056
|
+
# "client_id": "buy1_1234",
|
|
1057
|
+
# "created_at": 1689152421692,
|
|
1058
|
+
# "updated_at": 1689152421692,
|
|
1059
|
+
# }
|
|
825
1060
|
#
|
|
826
|
-
#
|
|
1061
|
+
# spot stop
|
|
1062
|
+
#
|
|
1063
|
+
# {
|
|
1064
|
+
# "stop_id": 102067022299,
|
|
1065
|
+
# "market": "BTCUSDT",
|
|
1066
|
+
# "margin_market": "BTCUSDT",
|
|
1067
|
+
# "type": "limit",
|
|
1068
|
+
# "side": "buy",
|
|
1069
|
+
# "price": "20000.00",
|
|
1070
|
+
# "amount": "0.10000000",
|
|
1071
|
+
# "trigger_price": "20000.00",
|
|
1072
|
+
# "trigger_direction": "lower",
|
|
1073
|
+
# "taker_fee_rate": "0.0016",
|
|
1074
|
+
# "maker_fee_rate": "0.0016",
|
|
1075
|
+
# "status": "active_success",
|
|
1076
|
+
# "client_id": "",
|
|
1077
|
+
# "created_at": 1689152996689,
|
|
1078
|
+
# "updated_at": 1689152996689,
|
|
1079
|
+
# }
|
|
1080
|
+
#
|
|
1081
|
+
# swap
|
|
1082
|
+
#
|
|
1083
|
+
# {
|
|
1084
|
+
# "order_id": 98388656341,
|
|
1085
|
+
# "stop_id": 0,
|
|
1086
|
+
# "market": "BTCUSDT",
|
|
1087
|
+
# "side": "buy",
|
|
1088
|
+
# "type": "limit",
|
|
1089
|
+
# "amount": "0.0010",
|
|
1090
|
+
# "price": "50000.00",
|
|
1091
|
+
# "unfilled_amount": "0.0010",
|
|
1092
|
+
# "filled_amount": "0",
|
|
1093
|
+
# "filled_value": "0",
|
|
1094
|
+
# "fee": "0",
|
|
1095
|
+
# "fee_ccy": "USDT",
|
|
1096
|
+
# "taker_fee_rate": "0.00046",
|
|
1097
|
+
# "maker_fee_rate": "0.00000000000000000000",
|
|
1098
|
+
# "client_id": "",
|
|
1099
|
+
# "last_filled_amount": "0.0010",
|
|
1100
|
+
# "last_filled_price": "30721.35",
|
|
1101
|
+
# "created_at": 1689145715129,
|
|
1102
|
+
# "updated_at": 1689145715129
|
|
1103
|
+
# }
|
|
827
1104
|
#
|
|
828
|
-
#
|
|
829
|
-
#
|
|
830
|
-
#
|
|
831
|
-
#
|
|
832
|
-
#
|
|
833
|
-
#
|
|
834
|
-
#
|
|
835
|
-
#
|
|
836
|
-
#
|
|
837
|
-
#
|
|
838
|
-
#
|
|
839
|
-
#
|
|
840
|
-
#
|
|
841
|
-
#
|
|
842
|
-
#
|
|
843
|
-
#
|
|
844
|
-
#
|
|
845
|
-
#
|
|
846
|
-
#
|
|
847
|
-
|
|
848
|
-
# "deal_profit": "0.00000000000000000000",
|
|
849
|
-
# "last_deal_amount": "0.00000000000000000000",
|
|
850
|
-
# "last_deal_price": "0.00000000000000000000",
|
|
851
|
-
# "last_deal_time": 0,
|
|
852
|
-
# "last_deal_id": 0,
|
|
853
|
-
# "last_deal_type": 0,
|
|
854
|
-
# "last_deal_role": 0,
|
|
855
|
-
# "client_id": '',
|
|
856
|
-
# "fee_asset": '',
|
|
857
|
-
# "fee_discount": "0.00000000000000000000",
|
|
858
|
-
# "deal_asset_fee": "0.00000000000000000000",
|
|
859
|
-
# "leverage": "3",
|
|
860
|
-
# "position_type": 2
|
|
861
|
-
# }
|
|
862
|
-
#
|
|
863
|
-
# order.update_stop
|
|
864
|
-
#
|
|
865
|
-
# {
|
|
866
|
-
# "id": 78006745870,
|
|
867
|
-
# "type": 1,
|
|
868
|
-
# "side": 2,
|
|
869
|
-
# "user": 1849116,
|
|
870
|
-
# "account": 1,
|
|
871
|
-
# "option": 70,
|
|
872
|
-
# "direction": 1,
|
|
873
|
-
# "ctime": 1654171725.131976,
|
|
874
|
-
# "mtime": 1654171725.131976,
|
|
875
|
-
# "market": "BTCUSDT",
|
|
876
|
-
# "source": "web",
|
|
877
|
-
# "client_id": '',
|
|
878
|
-
# "stop_price": "1.00",
|
|
879
|
-
# "price": "1.00",
|
|
880
|
-
# "amount": "1.00000000",
|
|
881
|
-
# "taker_fee": "0.0020",
|
|
882
|
-
# "maker_fee": "0.0020",
|
|
883
|
-
# "fee_discount": "1",
|
|
884
|
-
# "fee_asset": null,
|
|
885
|
-
# "status": 0
|
|
886
|
-
# }
|
|
887
|
-
#
|
|
888
|
-
timestamp = self.safe_timestamp_2(order, 'update_time', 'mtime')
|
|
1105
|
+
# swap stop
|
|
1106
|
+
#
|
|
1107
|
+
# {
|
|
1108
|
+
# "stop_id": 98389557871,
|
|
1109
|
+
# "market": "BTCUSDT",
|
|
1110
|
+
# "side": "sell",
|
|
1111
|
+
# "type": "limit",
|
|
1112
|
+
# "price": "20000.00",
|
|
1113
|
+
# "amount": "0.0100",
|
|
1114
|
+
# "trigger_price": "20000.00",
|
|
1115
|
+
# "trigger_direction": "higer",
|
|
1116
|
+
# "trigger_price_type": "index_price",
|
|
1117
|
+
# "taker_fee_rate": "0.00046",
|
|
1118
|
+
# "maker_fee_rate": "0.00026",
|
|
1119
|
+
# "client_id": "",
|
|
1120
|
+
# "created_at": 1689146382674,
|
|
1121
|
+
# "updated_at": 1689146382674
|
|
1122
|
+
# }
|
|
1123
|
+
#
|
|
1124
|
+
timestamp = self.safe_integer(order, 'created_at')
|
|
889
1125
|
marketId = self.safe_string(order, 'market')
|
|
890
|
-
typeCode = self.safe_string(order, 'type')
|
|
891
|
-
type = self.safe_string({
|
|
892
|
-
'1': 'limit',
|
|
893
|
-
'2': 'market',
|
|
894
|
-
}, typeCode)
|
|
895
|
-
sideCode = self.safe_string(order, 'side')
|
|
896
|
-
side = self.safe_string({
|
|
897
|
-
'1': 'sell',
|
|
898
|
-
'2': 'buy',
|
|
899
|
-
}, sideCode)
|
|
900
|
-
remaining = self.safe_string(order, 'left')
|
|
901
|
-
amount = self.safe_string(order, 'amount')
|
|
902
1126
|
status = self.safe_string(order, 'status')
|
|
903
|
-
|
|
1127
|
+
isSpot = ('margin_market' in order)
|
|
1128
|
+
defaultType = 'spot' if isSpot else 'swap'
|
|
904
1129
|
market = self.safe_market(marketId, market, None, defaultType)
|
|
905
|
-
cost = self.safe_string(order, 'deal_money')
|
|
906
|
-
filled = self.safe_string(order, 'deal_stock')
|
|
907
|
-
average = None
|
|
908
|
-
if market['swap']:
|
|
909
|
-
leverage = self.safe_string(order, 'leverage')
|
|
910
|
-
cost = Precise.string_div(filled, leverage)
|
|
911
|
-
average = Precise.string_div(filled, amount)
|
|
912
|
-
filled = None
|
|
913
1130
|
fee = None
|
|
914
|
-
feeCost = self.omit_zero(self.
|
|
1131
|
+
feeCost = self.omit_zero(self.safe_string_2(order, 'fee', 'quote_ccy_fee'))
|
|
915
1132
|
if feeCost is not None:
|
|
916
|
-
feeCurrencyId = self.safe_string(order, '
|
|
1133
|
+
feeCurrencyId = self.safe_string(order, 'fee_ccy', market['quote'])
|
|
917
1134
|
fee = {
|
|
918
1135
|
'currency': self.safe_currency_code(feeCurrencyId),
|
|
919
1136
|
'cost': feeCost,
|
|
920
1137
|
}
|
|
921
1138
|
return self.safe_order({
|
|
922
1139
|
'info': order,
|
|
923
|
-
'id': self.safe_string_2(order, 'order_id', '
|
|
1140
|
+
'id': self.safe_string_2(order, 'order_id', 'stop_id'),
|
|
924
1141
|
'clientOrderId': self.safe_string(order, 'client_id'),
|
|
925
1142
|
'datetime': self.iso8601(timestamp),
|
|
926
1143
|
'timestamp': timestamp,
|
|
927
|
-
'lastTradeTimestamp': self.
|
|
1144
|
+
'lastTradeTimestamp': self.safe_integer(order, 'updated_at'),
|
|
928
1145
|
'symbol': market['symbol'],
|
|
929
|
-
'type': type,
|
|
1146
|
+
'type': self.safe_string(order, 'type'),
|
|
930
1147
|
'timeInForce': None,
|
|
931
1148
|
'postOnly': None,
|
|
932
|
-
'side': side,
|
|
1149
|
+
'side': self.safe_string(order, 'side'),
|
|
933
1150
|
'price': self.safe_string(order, 'price'),
|
|
934
|
-
'stopPrice': self.safe_string(order, '
|
|
935
|
-
'triggerPrice': self.safe_string(order, '
|
|
936
|
-
'amount': amount,
|
|
937
|
-
'filled':
|
|
938
|
-
'remaining':
|
|
939
|
-
'cost':
|
|
940
|
-
'average':
|
|
1151
|
+
'stopPrice': self.safe_string(order, 'trigger_price'),
|
|
1152
|
+
'triggerPrice': self.safe_string(order, 'trigger_price'),
|
|
1153
|
+
'amount': self.safe_string(order, 'amount'),
|
|
1154
|
+
'filled': self.safe_string_2(order, 'filled_amount', 'fill_value'),
|
|
1155
|
+
'remaining': self.safe_string_2(order, 'unfilled_amount', 'unfill_amount'),
|
|
1156
|
+
'cost': None,
|
|
1157
|
+
'average': None,
|
|
941
1158
|
'status': self.parse_ws_order_status(status),
|
|
942
1159
|
'fee': fee,
|
|
943
1160
|
'trades': None,
|
|
@@ -945,24 +1162,111 @@ class coinex(ccxt.async_support.coinex):
|
|
|
945
1162
|
|
|
946
1163
|
def parse_ws_order_status(self, status):
|
|
947
1164
|
statuses: dict = {
|
|
948
|
-
'
|
|
949
|
-
'
|
|
1165
|
+
'active_success': 'open',
|
|
1166
|
+
'active_fail': 'canceled',
|
|
1167
|
+
'cancel': 'canceled',
|
|
950
1168
|
}
|
|
951
1169
|
return self.safe_string(statuses, status, status)
|
|
952
1170
|
|
|
1171
|
+
async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
|
|
1172
|
+
"""
|
|
1173
|
+
watches best bid & ask for symbols
|
|
1174
|
+
|
|
1175
|
+
https://docs.coinex.com/api/v2/spot/market/ws/market-bbo
|
|
1176
|
+
https://docs.coinex.com/api/v2/futures/market/ws/market-bbo
|
|
1177
|
+
|
|
1178
|
+
:param str[] [symbols]: unified symbol of the market to fetch the ticker for
|
|
1179
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
1180
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
|
1181
|
+
"""
|
|
1182
|
+
await self.load_markets()
|
|
1183
|
+
marketIds = self.market_ids(symbols)
|
|
1184
|
+
messageHashes = []
|
|
1185
|
+
market = None
|
|
1186
|
+
symbolsDefined = (symbols is not None)
|
|
1187
|
+
if symbolsDefined:
|
|
1188
|
+
for i in range(0, len(symbols)):
|
|
1189
|
+
symbol = symbols[i]
|
|
1190
|
+
market = self.market(symbol)
|
|
1191
|
+
messageHashes.append('bidsasks:' + market['symbol'])
|
|
1192
|
+
else:
|
|
1193
|
+
messageHashes.append('bidsasks')
|
|
1194
|
+
type = None
|
|
1195
|
+
type, params = self.handle_market_type_and_params('watchBidsAsks', market, params)
|
|
1196
|
+
url = self.urls['api']['ws'][type]
|
|
1197
|
+
subscriptionHashes = ['all@bidsasks']
|
|
1198
|
+
subscribe: dict = {
|
|
1199
|
+
'method': 'bbo.subscribe',
|
|
1200
|
+
'params': {'market_list': marketIds},
|
|
1201
|
+
'id': self.request_id(),
|
|
1202
|
+
}
|
|
1203
|
+
result = await self.watch_multiple(url, messageHashes, self.deep_extend(subscribe, params), subscriptionHashes)
|
|
1204
|
+
if self.newUpdates:
|
|
1205
|
+
return result
|
|
1206
|
+
return self.filter_by_array(self.bidsasks, 'symbol', symbols)
|
|
1207
|
+
|
|
1208
|
+
def handle_bid_ask(self, client: Client, message):
|
|
1209
|
+
#
|
|
1210
|
+
# {
|
|
1211
|
+
# "method": "bbo.update",
|
|
1212
|
+
# "data": {
|
|
1213
|
+
# "market": "BTCUSDT",
|
|
1214
|
+
# "updated_at": 1656660154,
|
|
1215
|
+
# "best_bid_price": "20000",
|
|
1216
|
+
# "best_bid_size": "0.1",
|
|
1217
|
+
# "best_ask_price": "20001",
|
|
1218
|
+
# "best_ask_size": "0.15"
|
|
1219
|
+
# },
|
|
1220
|
+
# "id": null
|
|
1221
|
+
# }
|
|
1222
|
+
#
|
|
1223
|
+
data = self.safe_dict(message, 'data', {})
|
|
1224
|
+
parsedTicker = self.parse_ws_bid_ask(data)
|
|
1225
|
+
symbol = parsedTicker['symbol']
|
|
1226
|
+
self.bidsasks[symbol] = parsedTicker
|
|
1227
|
+
messageHash = 'bidsasks:' + symbol
|
|
1228
|
+
client.resolve(parsedTicker, messageHash)
|
|
1229
|
+
|
|
1230
|
+
def parse_ws_bid_ask(self, ticker, market=None):
|
|
1231
|
+
#
|
|
1232
|
+
# {
|
|
1233
|
+
# "market": "BTCUSDT",
|
|
1234
|
+
# "updated_at": 1656660154,
|
|
1235
|
+
# "best_bid_price": "20000",
|
|
1236
|
+
# "best_bid_size": "0.1",
|
|
1237
|
+
# "best_ask_price": "20001",
|
|
1238
|
+
# "best_ask_size": "0.15"
|
|
1239
|
+
# }
|
|
1240
|
+
#
|
|
1241
|
+
defaultType = self.safe_string(self.options, 'defaultType')
|
|
1242
|
+
marketId = self.safe_string(ticker, 'market')
|
|
1243
|
+
market = self.safe_market(marketId, market, None, defaultType)
|
|
1244
|
+
timestamp = self.safe_integer(ticker, 'updated_at')
|
|
1245
|
+
return self.safe_ticker({
|
|
1246
|
+
'symbol': self.safe_symbol(marketId, market, None, defaultType),
|
|
1247
|
+
'timestamp': timestamp,
|
|
1248
|
+
'datetime': self.iso8601(timestamp),
|
|
1249
|
+
'ask': self.safe_number(ticker, 'best_ask_price'),
|
|
1250
|
+
'askVolume': self.safe_number(ticker, 'best_ask_size'),
|
|
1251
|
+
'bid': self.safe_number(ticker, 'best_bid_price'),
|
|
1252
|
+
'bidVolume': self.safe_number(ticker, 'best_bid_size'),
|
|
1253
|
+
'info': ticker,
|
|
1254
|
+
}, market)
|
|
1255
|
+
|
|
953
1256
|
def handle_message(self, client: Client, message):
|
|
954
|
-
error = self.safe_value(message, 'error')
|
|
955
|
-
if error is not None:
|
|
956
|
-
raise ExchangeError(self.id + ' ' + self.json(error))
|
|
957
1257
|
method = self.safe_string(message, 'method')
|
|
1258
|
+
error = self.safe_string(message, 'message')
|
|
1259
|
+
if error is not None:
|
|
1260
|
+
self.handle_errors(1, '', client.url, method, {}, self.json(error), message, {}, {})
|
|
958
1261
|
handlers: dict = {
|
|
959
1262
|
'state.update': self.handle_ticker,
|
|
960
|
-
'
|
|
1263
|
+
'balance.update': self.handle_balance,
|
|
961
1264
|
'deals.update': self.handle_trades,
|
|
1265
|
+
'user_deals.update': self.handle_my_trades,
|
|
962
1266
|
'depth.update': self.handle_order_book,
|
|
963
1267
|
'order.update': self.handle_orders,
|
|
964
|
-
'
|
|
965
|
-
'
|
|
1268
|
+
'stop.update': self.handle_orders,
|
|
1269
|
+
'bbo.update': self.handle_bid_ask,
|
|
966
1270
|
}
|
|
967
1271
|
handler = self.safe_value(handlers, method)
|
|
968
1272
|
if handler is not None:
|
|
@@ -970,92 +1274,90 @@ class coinex(ccxt.async_support.coinex):
|
|
|
970
1274
|
return
|
|
971
1275
|
self.handle_subscription_status(client, message)
|
|
972
1276
|
|
|
1277
|
+
def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
|
|
1278
|
+
if response is None:
|
|
1279
|
+
return None
|
|
1280
|
+
#
|
|
1281
|
+
# {"id": 1, "code": 20001, "message": "invalid argument"}
|
|
1282
|
+
# {"id": 2, "code": 21001, "message": "require auth"}
|
|
1283
|
+
# {"id": 1, "code": 21002, "message": "Signature Incorrect"}
|
|
1284
|
+
#
|
|
1285
|
+
message = self.safe_string_lower(response, 'message')
|
|
1286
|
+
isErrorMessage = (message is not None) and (message != 'ok')
|
|
1287
|
+
errorCode = self.safe_string(response, 'code')
|
|
1288
|
+
isErrorCode = (errorCode is not None) and (errorCode != '0')
|
|
1289
|
+
if isErrorCode or isErrorMessage:
|
|
1290
|
+
feedback = self.id + ' ' + body
|
|
1291
|
+
self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
|
|
1292
|
+
self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
|
|
1293
|
+
raise ExchangeError(feedback)
|
|
1294
|
+
return None
|
|
1295
|
+
|
|
973
1296
|
def handle_authentication_message(self, client: Client, message):
|
|
1297
|
+
#
|
|
1298
|
+
# success
|
|
974
1299
|
#
|
|
975
1300
|
# {
|
|
976
|
-
# "
|
|
977
|
-
# "
|
|
978
|
-
#
|
|
979
|
-
# },
|
|
980
|
-
# "id": 1
|
|
1301
|
+
# "id": 1,
|
|
1302
|
+
# "code": 0,
|
|
1303
|
+
# "message": "OK"
|
|
981
1304
|
# }
|
|
982
1305
|
#
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
#
|
|
986
|
-
#
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
1306
|
+
# fail
|
|
1307
|
+
#
|
|
1308
|
+
# {
|
|
1309
|
+
# "id": 1,
|
|
1310
|
+
# "code": 21002,
|
|
1311
|
+
# "message": ""
|
|
1312
|
+
# }
|
|
1313
|
+
#
|
|
1314
|
+
status = self.safe_string_lower(message, 'message')
|
|
1315
|
+
errorCode = self.safe_string(message, 'code')
|
|
1316
|
+
messageHash = 'authenticated'
|
|
1317
|
+
if (status == 'ok') or (errorCode == '0'):
|
|
1318
|
+
future = self.safe_value(client.futures, messageHash)
|
|
1319
|
+
future.resolve(True)
|
|
1320
|
+
else:
|
|
1321
|
+
error = AuthenticationError(self.json(message))
|
|
1322
|
+
client.reject(error, messageHash)
|
|
1323
|
+
if messageHash in client.subscriptions:
|
|
1324
|
+
del client.subscriptions[messageHash]
|
|
992
1325
|
|
|
993
1326
|
def handle_subscription_status(self, client: Client, message):
|
|
994
1327
|
id = self.safe_integer(message, 'id')
|
|
995
1328
|
subscription = self.safe_value(client.subscriptions, id)
|
|
996
1329
|
if subscription is not None:
|
|
997
1330
|
futureIndex = self.safe_string(subscription, 'future')
|
|
998
|
-
if futureIndex == 'ohlcv':
|
|
999
|
-
self.handle_ohlcv(client, message)
|
|
1000
|
-
return
|
|
1001
1331
|
future = self.safe_value(client.futures, futureIndex)
|
|
1002
1332
|
if future is not None:
|
|
1003
1333
|
future.resolve(True)
|
|
1004
1334
|
del client.subscriptions[id]
|
|
1005
1335
|
|
|
1006
|
-
async def authenticate(self,
|
|
1007
|
-
type = None
|
|
1008
|
-
type, params = self.handle_market_type_and_params('authenticate', None, params)
|
|
1336
|
+
async def authenticate(self, type: str):
|
|
1009
1337
|
url = self.urls['api']['ws'][type]
|
|
1010
1338
|
client = self.client(url)
|
|
1011
1339
|
time = self.milliseconds()
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
swapMessageHash = 'authenticated:swap'
|
|
1015
|
-
messageHash = spotMessageHash if isSpot else swapMessageHash
|
|
1340
|
+
timestamp = str(time)
|
|
1341
|
+
messageHash = 'authenticated'
|
|
1016
1342
|
future = client.future(messageHash)
|
|
1017
1343
|
authenticated = self.safe_value(client.subscriptions, messageHash)
|
|
1018
|
-
if
|
|
1019
|
-
if authenticated is not None:
|
|
1020
|
-
return await future
|
|
1021
|
-
requestId = self.request_id()
|
|
1022
|
-
subscribe: dict = {
|
|
1023
|
-
'id': requestId,
|
|
1024
|
-
'future': spotMessageHash,
|
|
1025
|
-
}
|
|
1026
|
-
signData = 'access_id=' + self.apiKey + '&tonce=' + self.number_to_string(time) + '&secret_key=' + self.secret
|
|
1027
|
-
hash = self.hash(self.encode(signData), 'md5')
|
|
1028
|
-
request: dict = {
|
|
1029
|
-
'method': 'server.sign',
|
|
1030
|
-
'params': [
|
|
1031
|
-
self.apiKey,
|
|
1032
|
-
hash.upper(),
|
|
1033
|
-
time,
|
|
1034
|
-
],
|
|
1035
|
-
'id': requestId,
|
|
1036
|
-
}
|
|
1037
|
-
self.watch(url, messageHash, request, requestId, subscribe)
|
|
1038
|
-
client.subscriptions[messageHash] = True
|
|
1039
|
-
return await future
|
|
1040
|
-
else:
|
|
1041
|
-
if authenticated is not None:
|
|
1042
|
-
return await future
|
|
1043
|
-
requestId = self.request_id()
|
|
1044
|
-
subscribe: dict = {
|
|
1045
|
-
'id': requestId,
|
|
1046
|
-
'future': swapMessageHash,
|
|
1047
|
-
}
|
|
1048
|
-
signData = 'access_id=' + self.apiKey + '×tamp=' + self.number_to_string(time) + '&secret_key=' + self.secret
|
|
1049
|
-
hash = self.hash(self.encode(signData), 'sha256', 'hex')
|
|
1050
|
-
request: dict = {
|
|
1051
|
-
'method': 'server.sign',
|
|
1052
|
-
'params': [
|
|
1053
|
-
self.apiKey,
|
|
1054
|
-
hash.lower(),
|
|
1055
|
-
time,
|
|
1056
|
-
],
|
|
1057
|
-
'id': requestId,
|
|
1058
|
-
}
|
|
1059
|
-
self.watch(url, messageHash, request, requestId, subscribe)
|
|
1060
|
-
client.subscriptions[messageHash] = True
|
|
1344
|
+
if authenticated is not None:
|
|
1061
1345
|
return await future
|
|
1346
|
+
requestId = self.request_id()
|
|
1347
|
+
subscribe: dict = {
|
|
1348
|
+
'id': requestId,
|
|
1349
|
+
'future': messageHash,
|
|
1350
|
+
}
|
|
1351
|
+
hmac = self.hmac(self.encode(timestamp), self.encode(self.secret), hashlib.sha256, 'hex')
|
|
1352
|
+
request: dict = {
|
|
1353
|
+
'id': requestId,
|
|
1354
|
+
'method': 'server.sign',
|
|
1355
|
+
'params': {
|
|
1356
|
+
'access_id': self.apiKey,
|
|
1357
|
+
'signed_str': hmac.lower(),
|
|
1358
|
+
'timestamp': time,
|
|
1359
|
+
},
|
|
1360
|
+
}
|
|
1361
|
+
self.watch(url, messageHash, request, requestId, subscribe)
|
|
1362
|
+
client.subscriptions[messageHash] = True
|
|
1363
|
+
return await future
|