ccxt 4.2.76__py2.py3-none-any.whl → 4.4.48__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 +36 -14
- ccxt/abstract/alpaca.py +4 -0
- ccxt/abstract/bigone.py +1 -1
- ccxt/abstract/binance.py +112 -48
- ccxt/abstract/binancecoinm.py +112 -48
- ccxt/abstract/binanceus.py +147 -83
- ccxt/abstract/binanceusdm.py +112 -48
- ccxt/abstract/bingx.py +133 -78
- ccxt/abstract/bitbank.py +5 -0
- ccxt/abstract/bitfinex.py +136 -65
- ccxt/abstract/bitfinex1.py +69 -0
- ccxt/abstract/bitflyer.py +1 -0
- ccxt/abstract/bitget.py +8 -1
- ccxt/abstract/bitmart.py +13 -1
- ccxt/abstract/bitopro.py +1 -0
- ccxt/abstract/bitpanda.py +0 -12
- ccxt/abstract/bitrue.py +3 -3
- ccxt/abstract/bitstamp.py +26 -3
- ccxt/abstract/blofin.py +24 -0
- ccxt/abstract/btcbox.py +1 -0
- ccxt/abstract/bybit.py +29 -14
- ccxt/abstract/cex.py +28 -29
- ccxt/abstract/coinbase.py +6 -0
- ccxt/abstract/coinbaseadvanced.py +94 -0
- ccxt/abstract/{coinbasepro.py → coinbaseexchange.py} +1 -0
- ccxt/abstract/coinbaseinternational.py +1 -1
- ccxt/abstract/coincatch.py +94 -0
- ccxt/abstract/coinex.py +233 -123
- ccxt/abstract/coinmetro.py +1 -0
- ccxt/abstract/cryptocom.py +14 -0
- ccxt/abstract/defx.py +69 -0
- ccxt/abstract/deribit.py +1 -0
- ccxt/abstract/digifinex.py +1 -0
- ccxt/abstract/ellipx.py +25 -0
- ccxt/abstract/gate.py +20 -0
- ccxt/abstract/gateio.py +20 -0
- ccxt/abstract/gemini.py +1 -0
- ccxt/abstract/hashkey.py +67 -0
- ccxt/abstract/hyperliquid.py +1 -1
- ccxt/abstract/independentreserve.py +6 -0
- ccxt/abstract/kraken.py +4 -3
- ccxt/abstract/krakenfutures.py +4 -0
- ccxt/abstract/kucoin.py +25 -0
- ccxt/abstract/kucoinfutures.py +35 -0
- ccxt/abstract/luno.py +2 -0
- ccxt/abstract/mexc.py +4 -0
- ccxt/abstract/myokx.py +340 -0
- ccxt/abstract/oceanex.py +5 -0
- ccxt/abstract/okx.py +30 -0
- ccxt/abstract/onetrading.py +0 -12
- ccxt/abstract/oxfun.py +34 -0
- ccxt/abstract/paradex.py +40 -0
- ccxt/abstract/phemex.py +1 -0
- ccxt/abstract/upbit.py +4 -0
- ccxt/abstract/vertex.py +19 -0
- ccxt/abstract/whitebit.py +31 -1
- ccxt/abstract/woo.py +6 -2
- ccxt/abstract/woofipro.py +119 -0
- ccxt/abstract/xt.py +153 -0
- ccxt/abstract/zonda.py +6 -0
- ccxt/ace.py +164 -60
- ccxt/alpaca.py +727 -63
- ccxt/ascendex.py +395 -249
- ccxt/async_support/__init__.py +36 -14
- ccxt/async_support/ace.py +164 -60
- ccxt/async_support/alpaca.py +727 -63
- ccxt/async_support/ascendex.py +396 -249
- ccxt/async_support/base/exchange.py +531 -155
- ccxt/async_support/base/ws/aiohttp_client.py +28 -5
- ccxt/async_support/base/ws/cache.py +3 -2
- ccxt/async_support/base/ws/client.py +26 -5
- ccxt/async_support/base/ws/fast_client.py +4 -3
- ccxt/async_support/base/ws/functions.py +1 -1
- ccxt/async_support/base/ws/future.py +40 -31
- ccxt/async_support/base/ws/order_book_side.py +3 -0
- ccxt/async_support/bequant.py +1 -1
- ccxt/async_support/bigone.py +329 -202
- ccxt/async_support/binance.py +3513 -1511
- ccxt/async_support/binancecoinm.py +2 -1
- ccxt/async_support/binanceus.py +12 -1
- ccxt/async_support/binanceusdm.py +3 -1
- ccxt/async_support/bingx.py +3105 -881
- ccxt/async_support/bit2c.py +119 -38
- ccxt/async_support/bitbank.py +215 -76
- ccxt/async_support/bitbns.py +124 -53
- ccxt/async_support/bitfinex.py +3236 -1078
- ccxt/async_support/bitfinex1.py +1711 -0
- ccxt/async_support/bitflyer.py +239 -50
- ccxt/async_support/bitget.py +1513 -563
- ccxt/async_support/bithumb.py +201 -67
- ccxt/async_support/bitmart.py +1320 -435
- ccxt/async_support/bitmex.py +308 -111
- ccxt/async_support/bitopro.py +256 -96
- ccxt/async_support/bitrue.py +365 -233
- ccxt/async_support/bitso.py +201 -89
- ccxt/async_support/bitstamp.py +438 -269
- ccxt/async_support/bitteam.py +179 -73
- ccxt/async_support/bitvavo.py +180 -70
- ccxt/async_support/bl3p.py +92 -25
- ccxt/async_support/blockchaincom.py +193 -79
- ccxt/async_support/blofin.py +403 -150
- ccxt/async_support/btcalpha.py +161 -55
- ccxt/async_support/btcbox.py +250 -34
- ccxt/async_support/btcmarkets.py +232 -85
- ccxt/async_support/btcturk.py +159 -60
- ccxt/async_support/bybit.py +2326 -1255
- ccxt/async_support/cex.py +1409 -1329
- ccxt/async_support/coinbase.py +1455 -288
- ccxt/async_support/coinbaseadvanced.py +17 -0
- ccxt/async_support/{coinbasepro.py → coinbaseexchange.py} +233 -99
- ccxt/async_support/coinbaseinternational.py +428 -88
- ccxt/async_support/coincatch.py +5152 -0
- ccxt/async_support/coincheck.py +121 -38
- ccxt/async_support/coinex.py +4020 -3339
- ccxt/async_support/coinlist.py +273 -116
- ccxt/async_support/coinmate.py +204 -97
- ccxt/async_support/coinmetro.py +203 -110
- ccxt/async_support/coinone.py +142 -68
- ccxt/async_support/coinsph.py +206 -89
- ccxt/async_support/coinspot.py +137 -62
- ccxt/async_support/cryptocom.py +515 -185
- ccxt/async_support/currencycom.py +203 -85
- ccxt/async_support/defx.py +2066 -0
- ccxt/async_support/delta.py +467 -158
- ccxt/async_support/deribit.py +558 -324
- ccxt/async_support/digifinex.py +340 -223
- ccxt/async_support/ellipx.py +1826 -0
- ccxt/async_support/exmo.py +259 -128
- ccxt/async_support/gate.py +1473 -464
- ccxt/async_support/gemini.py +206 -84
- ccxt/async_support/hashkey.py +4164 -0
- ccxt/async_support/hitbtc.py +334 -178
- ccxt/async_support/hollaex.py +134 -83
- ccxt/async_support/htx.py +1095 -563
- ccxt/async_support/huobijp.py +105 -56
- ccxt/async_support/hyperliquid.py +1634 -269
- ccxt/async_support/idex.py +148 -95
- ccxt/async_support/independentreserve.py +236 -31
- ccxt/async_support/indodax.py +165 -62
- ccxt/async_support/kraken.py +871 -354
- ccxt/async_support/krakenfutures.py +324 -100
- ccxt/async_support/kucoin.py +1050 -355
- ccxt/async_support/kucoinfutures.py +1004 -149
- ccxt/async_support/kuna.py +138 -106
- ccxt/async_support/latoken.py +135 -79
- ccxt/async_support/lbank.py +290 -113
- ccxt/async_support/luno.py +112 -62
- ccxt/async_support/lykke.py +104 -55
- ccxt/async_support/mercado.py +36 -29
- ccxt/async_support/mexc.py +995 -429
- ccxt/async_support/myokx.py +43 -0
- ccxt/async_support/ndax.py +163 -82
- ccxt/async_support/novadax.py +121 -75
- ccxt/async_support/oceanex.py +175 -59
- ccxt/async_support/okcoin.py +222 -163
- ccxt/async_support/okx.py +1777 -455
- ccxt/async_support/onetrading.py +132 -414
- ccxt/async_support/oxfun.py +2832 -0
- ccxt/async_support/p2b.py +79 -51
- ccxt/async_support/paradex.py +2017 -0
- ccxt/async_support/paymium.py +56 -32
- ccxt/async_support/phemex.py +572 -196
- ccxt/async_support/poloniex.py +218 -95
- ccxt/async_support/poloniexfutures.py +260 -92
- ccxt/async_support/probit.py +143 -110
- ccxt/async_support/timex.py +123 -70
- ccxt/async_support/tokocrypto.py +129 -93
- ccxt/async_support/tradeogre.py +39 -25
- ccxt/async_support/upbit.py +322 -113
- ccxt/async_support/vertex.py +2983 -0
- ccxt/async_support/wavesexchange.py +227 -173
- ccxt/async_support/wazirx.py +145 -65
- ccxt/async_support/whitebit.py +533 -138
- ccxt/async_support/woo.py +1155 -295
- ccxt/async_support/woofipro.py +2716 -0
- ccxt/async_support/xt.py +4628 -0
- ccxt/async_support/yobit.py +160 -92
- ccxt/async_support/zaif.py +80 -33
- ccxt/async_support/zonda.py +140 -69
- ccxt/base/errors.py +51 -20
- ccxt/base/exchange.py +1729 -482
- ccxt/base/precise.py +10 -0
- ccxt/base/types.py +223 -4
- ccxt/bequant.py +1 -1
- ccxt/bigone.py +329 -202
- ccxt/binance.py +3513 -1511
- ccxt/binancecoinm.py +2 -1
- ccxt/binanceus.py +12 -1
- ccxt/binanceusdm.py +3 -1
- ccxt/bingx.py +3105 -881
- ccxt/bit2c.py +119 -38
- ccxt/bitbank.py +215 -76
- ccxt/bitbns.py +124 -53
- ccxt/bitfinex.py +3235 -1078
- ccxt/bitfinex1.py +1710 -0
- ccxt/bitflyer.py +239 -50
- ccxt/bitget.py +1513 -563
- ccxt/bithumb.py +200 -67
- ccxt/bitmart.py +1320 -435
- ccxt/bitmex.py +308 -111
- ccxt/bitopro.py +256 -96
- ccxt/bitrue.py +365 -233
- ccxt/bitso.py +201 -89
- ccxt/bitstamp.py +438 -269
- ccxt/bitteam.py +179 -73
- ccxt/bitvavo.py +180 -70
- ccxt/bl3p.py +92 -25
- ccxt/blockchaincom.py +193 -79
- ccxt/blofin.py +403 -150
- ccxt/btcalpha.py +161 -55
- ccxt/btcbox.py +250 -34
- ccxt/btcmarkets.py +232 -85
- ccxt/btcturk.py +159 -60
- ccxt/bybit.py +2326 -1255
- ccxt/cex.py +1408 -1329
- ccxt/coinbase.py +1455 -288
- ccxt/coinbaseadvanced.py +17 -0
- ccxt/{coinbasepro.py → coinbaseexchange.py} +233 -99
- ccxt/coinbaseinternational.py +428 -88
- ccxt/coincatch.py +5152 -0
- ccxt/coincheck.py +121 -38
- ccxt/coinex.py +4020 -3339
- ccxt/coinlist.py +273 -116
- ccxt/coinmate.py +204 -97
- ccxt/coinmetro.py +203 -110
- ccxt/coinone.py +142 -68
- ccxt/coinsph.py +206 -89
- ccxt/coinspot.py +137 -62
- ccxt/cryptocom.py +515 -185
- ccxt/currencycom.py +203 -85
- ccxt/defx.py +2065 -0
- ccxt/delta.py +467 -158
- ccxt/deribit.py +558 -324
- ccxt/digifinex.py +340 -223
- ccxt/ellipx.py +1826 -0
- ccxt/exmo.py +259 -128
- ccxt/gate.py +1473 -464
- ccxt/gemini.py +206 -84
- ccxt/hashkey.py +4164 -0
- ccxt/hitbtc.py +334 -178
- ccxt/hollaex.py +134 -83
- ccxt/htx.py +1095 -563
- ccxt/huobijp.py +105 -56
- ccxt/hyperliquid.py +1633 -269
- ccxt/idex.py +148 -95
- ccxt/independentreserve.py +235 -31
- ccxt/indodax.py +165 -62
- ccxt/kraken.py +871 -354
- ccxt/krakenfutures.py +324 -100
- ccxt/kucoin.py +1050 -355
- ccxt/kucoinfutures.py +1004 -149
- ccxt/kuna.py +138 -106
- ccxt/latoken.py +135 -79
- ccxt/lbank.py +290 -113
- ccxt/luno.py +112 -62
- ccxt/lykke.py +104 -55
- ccxt/mercado.py +36 -29
- ccxt/mexc.py +994 -429
- ccxt/myokx.py +43 -0
- ccxt/ndax.py +163 -82
- ccxt/novadax.py +121 -75
- ccxt/oceanex.py +175 -59
- ccxt/okcoin.py +222 -163
- ccxt/okx.py +1777 -455
- ccxt/onetrading.py +132 -414
- ccxt/oxfun.py +2831 -0
- ccxt/p2b.py +79 -51
- ccxt/paradex.py +2017 -0
- ccxt/paymium.py +56 -32
- ccxt/phemex.py +572 -196
- ccxt/poloniex.py +218 -95
- ccxt/poloniexfutures.py +260 -92
- ccxt/pro/__init__.py +29 -5
- ccxt/pro/alpaca.py +32 -17
- ccxt/pro/ascendex.py +63 -15
- ccxt/pro/bequant.py +4 -0
- ccxt/pro/binance.py +1596 -329
- ccxt/pro/binancecoinm.py +1 -0
- ccxt/pro/binanceus.py +2 -9
- ccxt/pro/binanceusdm.py +2 -0
- ccxt/pro/bingx.py +527 -134
- ccxt/pro/bitcoincom.py +4 -1
- ccxt/pro/bitfinex.py +731 -266
- ccxt/pro/bitfinex1.py +635 -0
- ccxt/pro/bitget.py +726 -357
- ccxt/pro/bithumb.py +380 -0
- ccxt/pro/bitmart.py +138 -39
- ccxt/pro/bitmex.py +199 -40
- ccxt/pro/bitopro.py +25 -13
- ccxt/pro/bitrue.py +31 -32
- ccxt/pro/bitstamp.py +7 -6
- ccxt/pro/bitvavo.py +204 -82
- ccxt/pro/blockchaincom.py +30 -17
- ccxt/pro/blofin.py +692 -0
- ccxt/pro/bybit.py +791 -82
- ccxt/pro/cex.py +99 -51
- ccxt/pro/coinbase.py +220 -30
- ccxt/{async_support/hitbtc3.py → pro/coinbaseadvanced.py} +5 -5
- ccxt/pro/{coinbasepro.py → coinbaseexchange.py} +19 -19
- ccxt/pro/coinbaseinternational.py +193 -30
- ccxt/pro/coincatch.py +1464 -0
- ccxt/pro/coincheck.py +11 -6
- ccxt/pro/coinex.py +967 -661
- ccxt/pro/coinone.py +17 -10
- ccxt/pro/cryptocom.py +446 -66
- ccxt/pro/currencycom.py +11 -10
- ccxt/pro/defx.py +832 -0
- ccxt/pro/deribit.py +168 -32
- ccxt/pro/exmo.py +253 -21
- ccxt/pro/gate.py +729 -64
- ccxt/pro/gemini.py +44 -26
- ccxt/pro/hashkey.py +802 -0
- ccxt/pro/hitbtc.py +208 -103
- ccxt/pro/hollaex.py +25 -9
- ccxt/pro/htx.py +83 -39
- ccxt/pro/huobijp.py +17 -16
- ccxt/pro/hyperliquid.py +502 -31
- ccxt/pro/idex.py +28 -13
- ccxt/pro/independentreserve.py +21 -16
- ccxt/pro/kraken.py +298 -51
- ccxt/pro/krakenfutures.py +166 -75
- ccxt/pro/kucoin.py +395 -77
- ccxt/pro/kucoinfutures.py +400 -99
- ccxt/pro/lbank.py +52 -31
- ccxt/pro/luno.py +12 -10
- ccxt/pro/mexc.py +400 -50
- ccxt/pro/myokx.py +28 -0
- ccxt/pro/ndax.py +25 -12
- ccxt/pro/okcoin.py +28 -9
- ccxt/pro/okx.py +935 -124
- ccxt/pro/onetrading.py +41 -24
- ccxt/pro/oxfun.py +1054 -0
- ccxt/pro/p2b.py +100 -24
- ccxt/pro/paradex.py +352 -0
- ccxt/pro/phemex.py +93 -34
- ccxt/pro/poloniex.py +129 -50
- ccxt/pro/poloniexfutures.py +53 -32
- ccxt/pro/probit.py +93 -86
- ccxt/pro/upbit.py +401 -8
- ccxt/pro/vertex.py +943 -0
- ccxt/pro/wazirx.py +46 -28
- ccxt/pro/whitebit.py +65 -12
- ccxt/pro/woo.py +486 -70
- ccxt/pro/woofipro.py +1271 -0
- ccxt/pro/xt.py +1067 -0
- ccxt/probit.py +143 -110
- ccxt/static_dependencies/__init__.py +1 -1
- ccxt/static_dependencies/lark/__init__.py +38 -0
- ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
- ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
- ccxt/static_dependencies/lark/ast_utils.py +59 -0
- ccxt/static_dependencies/lark/common.py +86 -0
- ccxt/static_dependencies/lark/exceptions.py +292 -0
- ccxt/static_dependencies/lark/grammar.py +130 -0
- ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
- ccxt/static_dependencies/lark/indenter.py +143 -0
- ccxt/static_dependencies/lark/lark.py +658 -0
- ccxt/static_dependencies/lark/lexer.py +678 -0
- ccxt/static_dependencies/lark/load_grammar.py +1428 -0
- ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
- ccxt/static_dependencies/lark/parser_frontends.py +257 -0
- ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
- ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
- ccxt/static_dependencies/lark/parsers/earley.py +314 -0
- ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
- ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
- ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
- ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
- ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
- ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
- ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
- ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
- ccxt/static_dependencies/lark/py.typed +0 -0
- ccxt/static_dependencies/lark/reconstruct.py +107 -0
- ccxt/static_dependencies/lark/tools/__init__.py +70 -0
- ccxt/static_dependencies/lark/tools/nearley.py +202 -0
- ccxt/static_dependencies/lark/tools/serialize.py +32 -0
- ccxt/static_dependencies/lark/tools/standalone.py +196 -0
- ccxt/static_dependencies/lark/tree.py +267 -0
- ccxt/static_dependencies/lark/tree_matcher.py +186 -0
- ccxt/static_dependencies/lark/tree_templates.py +180 -0
- ccxt/static_dependencies/lark/utils.py +343 -0
- ccxt/static_dependencies/lark/visitors.py +596 -0
- ccxt/static_dependencies/marshmallow/__init__.py +81 -0
- ccxt/static_dependencies/marshmallow/base.py +65 -0
- ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
- ccxt/static_dependencies/marshmallow/decorators.py +231 -0
- ccxt/static_dependencies/marshmallow/error_store.py +60 -0
- ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
- ccxt/static_dependencies/marshmallow/fields.py +2114 -0
- ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
- ccxt/static_dependencies/marshmallow/py.typed +0 -0
- ccxt/static_dependencies/marshmallow/schema.py +1228 -0
- ccxt/static_dependencies/marshmallow/types.py +12 -0
- ccxt/static_dependencies/marshmallow/utils.py +378 -0
- ccxt/static_dependencies/marshmallow/validate.py +678 -0
- ccxt/static_dependencies/marshmallow/warnings.py +2 -0
- ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
- ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
- ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
- ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
- ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
- ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
- ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
- ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
- ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
- ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
- ccxt/static_dependencies/starknet/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
- ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
- ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
- ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
- ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
- ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
- ccxt/static_dependencies/starknet/common.py +15 -0
- ccxt/static_dependencies/starknet/constants.py +39 -0
- ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
- ccxt/static_dependencies/starknet/hash/address.py +79 -0
- ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
- ccxt/static_dependencies/starknet/hash/selector.py +16 -0
- ccxt/static_dependencies/starknet/hash/storage.py +12 -0
- ccxt/static_dependencies/starknet/hash/utils.py +78 -0
- ccxt/static_dependencies/starknet/models/__init__.py +0 -0
- ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
- ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
- ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
- ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
- ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
- ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
- ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
- ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
- ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
- ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
- ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
- ccxt/static_dependencies/starknet/utils/schema.py +13 -0
- ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
- ccxt/static_dependencies/starkware/__init__.py +0 -0
- ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
- ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
- ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
- ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
- ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
- ccxt/static_dependencies/sympy/__init__.py +0 -0
- ccxt/static_dependencies/sympy/core/__init__.py +0 -0
- ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
- ccxt/static_dependencies/sympy/external/__init__.py +0 -0
- ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
- ccxt/static_dependencies/sympy/external/importtools.py +187 -0
- ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
- ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
- ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
- ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
- ccxt/test/{test_async.py → tests_async.py} +465 -407
- ccxt/test/tests_helpers.py +285 -0
- ccxt/test/tests_init.py +39 -0
- ccxt/test/{test_sync.py → tests_sync.py} +465 -409
- ccxt/timex.py +123 -70
- ccxt/tokocrypto.py +129 -93
- ccxt/tradeogre.py +39 -25
- ccxt/upbit.py +322 -113
- ccxt/vertex.py +2983 -0
- ccxt/wavesexchange.py +227 -173
- ccxt/wazirx.py +145 -65
- ccxt/whitebit.py +533 -138
- ccxt/woo.py +1155 -295
- ccxt/woofipro.py +2716 -0
- ccxt/xt.py +4627 -0
- ccxt/yobit.py +159 -92
- ccxt/zaif.py +80 -33
- ccxt/zonda.py +140 -69
- ccxt-4.4.48.dist-info/LICENSE.txt +21 -0
- ccxt-4.4.48.dist-info/METADATA +646 -0
- ccxt-4.4.48.dist-info/RECORD +669 -0
- {ccxt-4.2.76.dist-info → ccxt-4.4.48.dist-info}/WHEEL +1 -1
- ccxt/abstract/bitbay.py +0 -47
- ccxt/abstract/bitfinex2.py +0 -139
- ccxt/abstract/hitbtc3.py +0 -115
- ccxt/async_support/bitbay.py +0 -17
- ccxt/async_support/bitfinex2.py +0 -3496
- ccxt/async_support/flowbtc.py +0 -34
- ccxt/bitbay.py +0 -17
- ccxt/bitfinex2.py +0 -3496
- ccxt/flowbtc.py +0 -34
- ccxt/hitbtc3.py +0 -16
- ccxt/pro/bitfinex2.py +0 -1081
- ccxt/test/base/__init__.py +0 -28
- 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 -103
- 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 -32
- 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_margin_mode.py +0 -24
- ccxt/test/base/test_margin_modification.py +0 -35
- ccxt/test/base/test_market.py +0 -190
- ccxt/test/base/test_number.py +0 -411
- ccxt/test/base/test_ohlcv.py +0 -32
- 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 -63
- ccxt/test/base/test_position.py +0 -60
- ccxt/test/base/test_shared_methods.py +0 -345
- ccxt/test/base/test_status.py +0 -24
- ccxt/test/base/test_throttle.py +0 -126
- ccxt/test/base/test_ticker.py +0 -86
- 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-4.2.76.dist-info/METADATA +0 -626
- ccxt-4.2.76.dist-info/RECORD +0 -534
- {ccxt-4.2.76.dist-info → ccxt-4.4.48.dist-info}/top_level.txt +0 -0
ccxt/pro/coinex.py
CHANGED
@@ -4,17 +4,18 @@
|
|
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
|
7
|
+
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById
|
8
|
+
import hashlib
|
8
9
|
from ccxt.base.types import 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
|
13
|
+
from ccxt.base.errors import AuthenticationError
|
12
14
|
from ccxt.base.errors import BadRequest
|
13
15
|
from ccxt.base.errors import NotSupported
|
16
|
+
from ccxt.base.errors import RateLimitExceeded
|
14
17
|
from ccxt.base.errors import ExchangeNotAvailable
|
15
18
|
from ccxt.base.errors import RequestTimeout
|
16
|
-
from ccxt.base.errors import AuthenticationError
|
17
|
-
from ccxt.base.precise import Precise
|
18
19
|
|
19
20
|
|
20
21
|
class coinex(ccxt.async_support.coinex):
|
@@ -24,25 +25,30 @@ class coinex(ccxt.async_support.coinex):
|
|
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,278 @@ 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
266
|
currencies = list(self.currencies_by_id.keys())
|
241
|
-
|
242
|
-
|
243
|
-
|
267
|
+
if currencies is None:
|
268
|
+
currencies = []
|
269
|
+
messageHash = 'balances'
|
270
|
+
if type == 'spot':
|
271
|
+
messageHash += ':spot'
|
272
|
+
else:
|
273
|
+
messageHash += ':swap'
|
274
|
+
subscribe: dict = {
|
275
|
+
'method': 'balance.subscribe',
|
276
|
+
'params': {'ccy_list': currencies},
|
244
277
|
'id': self.request_id(),
|
245
278
|
}
|
246
279
|
request = self.deep_extend(subscribe, params)
|
247
280
|
return await self.watch(url, messageHash, request, messageHash)
|
248
281
|
|
249
282
|
def handle_balance(self, client: Client, message):
|
283
|
+
#
|
284
|
+
# spot
|
250
285
|
#
|
251
286
|
# {
|
252
|
-
# "method": "
|
253
|
-
# "
|
254
|
-
#
|
255
|
-
#
|
256
|
-
# "
|
257
|
-
# "
|
258
|
-
#
|
259
|
-
#
|
260
|
-
#
|
287
|
+
# "method": "balance.update",
|
288
|
+
# "data": {
|
289
|
+
# "balance_list": [
|
290
|
+
# {
|
291
|
+
# "margin_market": "BTCUSDT",
|
292
|
+
# "ccy": "BTC",
|
293
|
+
# "available": "44.62207740",
|
294
|
+
# "frozen": "0.00000000",
|
295
|
+
# "updated_at": 1689152421692
|
296
|
+
# },
|
297
|
+
# ]
|
298
|
+
# },
|
261
299
|
# "id": null
|
262
300
|
# }
|
263
301
|
#
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
302
|
+
# swap
|
303
|
+
#
|
304
|
+
# {
|
305
|
+
# "method": "balance.update",
|
306
|
+
# "data": {
|
307
|
+
# "balance_list": [
|
308
|
+
# {
|
309
|
+
# "ccy": "USDT",
|
310
|
+
# "available": "97.92470982756335000001",
|
311
|
+
# "frozen": "0.00000000000000000000",
|
312
|
+
# "margin": "0.61442700000000000000",
|
313
|
+
# "transferrable": "97.92470982756335000001",
|
314
|
+
# "unrealized_pnl": "-0.00807000000000000000",
|
315
|
+
# "equity": "97.92470982756335000001"
|
316
|
+
# },
|
317
|
+
# ]
|
318
|
+
# },
|
319
|
+
# "id": null
|
320
|
+
# }
|
321
|
+
#
|
322
|
+
if self.balance is None:
|
323
|
+
self.balance = {}
|
324
|
+
data = self.safe_dict(message, 'data', {})
|
325
|
+
balances = self.safe_list(data, 'balance_list', [])
|
326
|
+
firstEntry = balances[0]
|
327
|
+
updated = self.safe_integer(firstEntry, 'updated_at')
|
328
|
+
unrealizedPnl = self.safe_string(firstEntry, 'unrealized_pnl')
|
329
|
+
isSpot = (updated is not None)
|
330
|
+
isSwap = (unrealizedPnl is not None)
|
331
|
+
info = None
|
332
|
+
account = None
|
333
|
+
rawBalances = []
|
334
|
+
if isSpot:
|
335
|
+
account = 'spot'
|
336
|
+
for i in range(0, len(balances)):
|
337
|
+
rawBalances = self.array_concat(rawBalances, balances)
|
338
|
+
info = rawBalances
|
339
|
+
if isSwap:
|
340
|
+
account = 'swap'
|
341
|
+
for i in range(0, len(balances)):
|
342
|
+
rawBalances = self.array_concat(rawBalances, balances)
|
343
|
+
info = rawBalances
|
344
|
+
for i in range(0, len(rawBalances)):
|
345
|
+
entry = rawBalances[i]
|
346
|
+
self.parse_ws_balance(entry, account)
|
347
|
+
messageHash = None
|
348
|
+
if account is not None:
|
349
|
+
if self.safe_value(self.balance, account) is None:
|
350
|
+
self.balance[account] = {}
|
351
|
+
self.balance[account]['info'] = info
|
352
|
+
self.balance[account] = self.safe_balance(self.balance[account])
|
353
|
+
messageHash = 'balances:' + account
|
354
|
+
client.resolve(self.balance[account], messageHash)
|
355
|
+
|
356
|
+
def parse_ws_balance(self, balance, accountType=None):
|
357
|
+
#
|
358
|
+
# spot
|
359
|
+
#
|
360
|
+
# {
|
361
|
+
# "margin_market": "BTCUSDT",
|
362
|
+
# "ccy": "BTC",
|
363
|
+
# "available": "44.62207740",
|
364
|
+
# "frozen": "0.00000000",
|
365
|
+
# "updated_at": 1689152421692
|
366
|
+
# }
|
367
|
+
#
|
368
|
+
# swap
|
369
|
+
#
|
370
|
+
# {
|
371
|
+
# "ccy": "USDT",
|
372
|
+
# "available": "97.92470982756335000001",
|
373
|
+
# "frozen": "0.00000000000000000000",
|
374
|
+
# "margin": "0.61442700000000000000",
|
375
|
+
# "transferrable": "97.92470982756335000001",
|
376
|
+
# "unrealized_pnl": "-0.00807000000000000000",
|
377
|
+
# "equity": "97.92470982756335000001"
|
378
|
+
# }
|
379
|
+
#
|
380
|
+
account = self.account()
|
381
|
+
currencyId = self.safe_string(balance, 'ccy')
|
382
|
+
code = self.safe_currency_code(currencyId)
|
383
|
+
account['free'] = self.safe_string(balance, 'available')
|
384
|
+
account['used'] = self.safe_string(balance, 'frozen')
|
385
|
+
if accountType is not None:
|
386
|
+
if self.safe_value(self.balance, accountType) is None:
|
387
|
+
self.balance[accountType] = {}
|
388
|
+
self.balance[accountType][code] = account
|
389
|
+
else:
|
276
390
|
self.balance[code] = account
|
277
|
-
|
278
|
-
|
279
|
-
|
391
|
+
|
392
|
+
async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
393
|
+
"""
|
394
|
+
watches information on multiple trades made by the user
|
395
|
+
|
396
|
+
https://docs.coinex.com/api/v2/spot/deal/ws/user-deals
|
397
|
+
https://docs.coinex.com/api/v2/futures/deal/ws/user-deals
|
398
|
+
|
399
|
+
:param str [symbol]: unified symbol of the market the trades were made in
|
400
|
+
:param int [since]: the earliest time in ms to watch trades
|
401
|
+
:param int [limit]: the maximum number of trade structures to retrieve
|
402
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
403
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
|
404
|
+
"""
|
405
|
+
await self.load_markets()
|
406
|
+
market = None
|
407
|
+
if symbol is not None:
|
408
|
+
market = self.market(symbol)
|
409
|
+
symbol = market['symbol']
|
410
|
+
type = None
|
411
|
+
type, params = self.handle_market_type_and_params('watchMyTrades', market, params, 'spot')
|
412
|
+
await self.authenticate(type)
|
413
|
+
url = self.urls['api']['ws'][type]
|
414
|
+
subscribedSymbols = []
|
415
|
+
messageHash = 'myTrades'
|
416
|
+
if market is not None:
|
417
|
+
messageHash += ':' + symbol
|
418
|
+
subscribedSymbols.append(market['id'])
|
419
|
+
else:
|
420
|
+
if type == 'spot':
|
421
|
+
messageHash += ':spot'
|
422
|
+
else:
|
423
|
+
messageHash += ':swap'
|
424
|
+
message: dict = {
|
425
|
+
'method': 'user_deals.subscribe',
|
426
|
+
'params': {'market_list': subscribedSymbols},
|
427
|
+
'id': self.request_id(),
|
428
|
+
}
|
429
|
+
request = self.deep_extend(message, params)
|
430
|
+
trades = await self.watch(url, messageHash, request, messageHash)
|
431
|
+
if self.newUpdates:
|
432
|
+
limit = trades.getLimit(symbol, limit)
|
433
|
+
return self.filter_by_symbol_since_limit(trades, symbol, since, limit, True)
|
434
|
+
|
435
|
+
def handle_my_trades(self, client: Client, message):
|
436
|
+
#
|
437
|
+
# {
|
438
|
+
# "method": "user_deals.update",
|
439
|
+
# "data": {
|
440
|
+
# "deal_id": 3514376759,
|
441
|
+
# "created_at": 1689152421692,
|
442
|
+
# "market": "BTCUSDT",
|
443
|
+
# "side": "buy",
|
444
|
+
# "order_id": 8678890,
|
445
|
+
# "margin_market": "BTCUSDT",
|
446
|
+
# "price": "30718.42",
|
447
|
+
# "amount": "0.00000325",
|
448
|
+
# "role": "taker",
|
449
|
+
# "fee": "0.0299",
|
450
|
+
# "fee_ccy": "USDT"
|
451
|
+
# },
|
452
|
+
# "id": null
|
453
|
+
# }
|
454
|
+
#
|
455
|
+
data = self.safe_dict(message, 'data', {})
|
456
|
+
marketId = self.safe_string(data, 'market')
|
457
|
+
isSpot = client.url.find('spot') > -1
|
458
|
+
defaultType = 'spot' if isSpot else 'swap'
|
459
|
+
market = self.safe_market(marketId, None, None, defaultType)
|
460
|
+
symbol = market['symbol']
|
461
|
+
messageHash = 'myTrades:' + symbol
|
462
|
+
messageWithType = 'myTrades:' + market['type']
|
463
|
+
stored = self.safe_value(self.trades, symbol)
|
464
|
+
if stored is None:
|
465
|
+
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
466
|
+
stored = ArrayCache(limit)
|
467
|
+
self.trades[symbol] = stored
|
468
|
+
parsed = self.parse_ws_trade(data, market)
|
469
|
+
stored.append(parsed)
|
470
|
+
self.trades[symbol] = stored
|
471
|
+
client.resolve(self.trades[symbol], messageWithType)
|
472
|
+
client.resolve(self.trades[symbol], messageHash)
|
280
473
|
|
281
474
|
def handle_trades(self, client: Client, message):
|
475
|
+
#
|
476
|
+
# spot
|
282
477
|
#
|
283
478
|
# {
|
284
479
|
# "method": "deals.update",
|
285
|
-
# "
|
286
|
-
# "
|
287
|
-
# [
|
288
|
-
#
|
289
|
-
#
|
290
|
-
#
|
291
|
-
#
|
292
|
-
#
|
293
|
-
#
|
294
|
-
#
|
480
|
+
# "data": {
|
481
|
+
# "market": "BTCUSDT",
|
482
|
+
# "deal_list": [
|
483
|
+
# {
|
484
|
+
# "deal_id": 3514376759,
|
485
|
+
# "created_at": 1689152421692,
|
486
|
+
# "side": "buy",
|
487
|
+
# "price": "30718.42",
|
488
|
+
# "amount": "0.00000325"
|
489
|
+
# },
|
490
|
+
# ]
|
491
|
+
# },
|
295
492
|
# "id": null
|
296
493
|
# }
|
297
494
|
#
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
495
|
+
# swap
|
496
|
+
#
|
497
|
+
# {
|
498
|
+
# "method": "deals.update",
|
499
|
+
# "data": {
|
500
|
+
# "market": "BTCUSDT",
|
501
|
+
# "deal_list": [
|
502
|
+
# {
|
503
|
+
# "deal_id": 3514376759,
|
504
|
+
# "created_at": 1689152421692,
|
505
|
+
# "side": "buy",
|
506
|
+
# "price": "30718.42",
|
507
|
+
# "amount": "0.00000325"
|
508
|
+
# },
|
509
|
+
# ]
|
510
|
+
# },
|
511
|
+
# "id": null
|
512
|
+
# }
|
513
|
+
#
|
514
|
+
data = self.safe_dict(message, 'data', {})
|
515
|
+
trades = self.safe_list(data, 'deal_list', [])
|
516
|
+
marketId = self.safe_string(data, 'market')
|
517
|
+
isSpot = client.url.find('spot') > -1
|
518
|
+
defaultType = 'spot' if isSpot else 'swap'
|
302
519
|
market = self.safe_market(marketId, None, None, defaultType)
|
303
520
|
symbol = market['symbol']
|
304
521
|
messageHash = 'trades:' + symbol
|
@@ -315,289 +532,251 @@ class coinex(ccxt.async_support.coinex):
|
|
315
532
|
client.resolve(self.trades[symbol], messageHash)
|
316
533
|
|
317
534
|
def parse_ws_trade(self, trade, market=None):
|
535
|
+
#
|
536
|
+
# spot watchTrades
|
318
537
|
#
|
319
538
|
# {
|
320
|
-
# "
|
321
|
-
# "
|
322
|
-
# "
|
323
|
-
# "
|
324
|
-
# "amount": "0.
|
539
|
+
# "deal_id": 3514376759,
|
540
|
+
# "created_at": 1689152421692,
|
541
|
+
# "side": "buy",
|
542
|
+
# "price": "30718.42",
|
543
|
+
# "amount": "0.00000325"
|
325
544
|
# }
|
326
545
|
#
|
327
|
-
|
328
|
-
|
546
|
+
# swap watchTrades
|
547
|
+
#
|
548
|
+
# {
|
549
|
+
# "deal_id": 3514376759,
|
550
|
+
# "created_at": 1689152421692,
|
551
|
+
# "side": "buy",
|
552
|
+
# "price": "30718.42",
|
553
|
+
# "amount": "0.00000325"
|
554
|
+
# }
|
555
|
+
#
|
556
|
+
# spot and swap watchMyTrades
|
557
|
+
#
|
558
|
+
# {
|
559
|
+
# "deal_id": 3514376759,
|
560
|
+
# "created_at": 1689152421692,
|
561
|
+
# "market": "BTCUSDT",
|
562
|
+
# "side": "buy",
|
563
|
+
# "order_id": 8678890,
|
564
|
+
# "margin_market": "BTCUSDT",
|
565
|
+
# "price": "30718.42",
|
566
|
+
# "amount": "0.00000325",
|
567
|
+
# "role": "taker",
|
568
|
+
# "fee": "0.0299",
|
569
|
+
# "fee_ccy": "USDT"
|
570
|
+
# }
|
571
|
+
#
|
572
|
+
timestamp = self.safe_integer(trade, 'created_at')
|
573
|
+
isSpot = ('margin_market' in trade)
|
574
|
+
defaultType = 'spot' if isSpot else 'swap'
|
575
|
+
marketId = self.safe_string(trade, 'market')
|
576
|
+
market = self.safe_market(marketId, market, None, defaultType)
|
577
|
+
fee: dict = {}
|
578
|
+
feeCost = self.omit_zero(self.safe_string(trade, 'fee'))
|
579
|
+
if feeCost is not None:
|
580
|
+
feeCurrencyId = self.safe_string(trade, 'fee_ccy', market['quote'])
|
581
|
+
fee = {
|
582
|
+
'currency': self.safe_currency_code(feeCurrencyId),
|
583
|
+
'cost': feeCost,
|
584
|
+
}
|
329
585
|
return self.safe_trade({
|
330
|
-
'id': self.safe_string(trade, '
|
586
|
+
'id': self.safe_string(trade, 'deal_id'),
|
331
587
|
'info': trade,
|
332
588
|
'timestamp': timestamp,
|
333
589
|
'datetime': self.iso8601(timestamp),
|
334
|
-
'symbol': self.safe_symbol(
|
335
|
-
'order':
|
590
|
+
'symbol': self.safe_symbol(marketId, market, None, defaultType),
|
591
|
+
'order': self.safe_string(trade, 'order_id'),
|
336
592
|
'type': None,
|
337
|
-
'side': self.safe_string(trade, '
|
338
|
-
'takerOrMaker':
|
593
|
+
'side': self.safe_string(trade, 'side'),
|
594
|
+
'takerOrMaker': self.safe_string(trade, 'role'),
|
339
595
|
'price': self.safe_string(trade, 'price'),
|
340
596
|
'amount': self.safe_string(trade, 'amount'),
|
341
597
|
'cost': None,
|
342
|
-
'fee':
|
598
|
+
'fee': fee,
|
343
599
|
}, market)
|
344
600
|
|
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
601
|
async def watch_ticker(self, symbol: str, params={}) -> Ticker:
|
402
602
|
"""
|
403
|
-
:see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot004_websocket007_state_subscribe
|
404
603
|
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
604
|
+
|
605
|
+
https://docs.coinex.com/api/v2/spot/market/ws/market
|
606
|
+
https://docs.coinex.com/api/v2/futures/market/ws/market-state
|
607
|
+
|
405
608
|
:param str symbol: unified symbol of the market to fetch the ticker for
|
406
609
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
407
610
|
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
408
611
|
"""
|
612
|
+
await self.load_markets()
|
613
|
+
market = self.market(symbol)
|
409
614
|
tickers = await self.watch_tickers([symbol], params)
|
410
|
-
return
|
615
|
+
return tickers[market['symbol']]
|
411
616
|
|
412
617
|
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
413
618
|
"""
|
414
|
-
:see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot004_websocket007_state_subscribe
|
415
619
|
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
620
|
+
|
621
|
+
https://docs.coinex.com/api/v2/spot/market/ws/market
|
622
|
+
https://docs.coinex.com/api/v2/futures/market/ws/market-state
|
623
|
+
|
416
624
|
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
417
625
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
418
626
|
:returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
|
419
627
|
"""
|
420
628
|
await self.load_markets()
|
421
|
-
|
629
|
+
marketIds = self.market_ids(symbols)
|
630
|
+
market = None
|
631
|
+
messageHashes = []
|
632
|
+
symbolsDefined = (symbols is not None)
|
633
|
+
if symbolsDefined:
|
634
|
+
for i in range(0, len(symbols)):
|
635
|
+
symbol = symbols[i]
|
636
|
+
market = self.market(symbol)
|
637
|
+
messageHashes.append('tickers::' + market['symbol'])
|
638
|
+
else:
|
639
|
+
messageHashes.append('tickers')
|
422
640
|
type = None
|
423
|
-
type, params = self.handle_market_type_and_params('watchTickers',
|
641
|
+
type, params = self.handle_market_type_and_params('watchTickers', market, params)
|
424
642
|
url = self.urls['api']['ws'][type]
|
425
|
-
|
426
|
-
|
427
|
-
messageHash = 'tickers::' + ','.join(symbols)
|
428
|
-
subscribe = {
|
643
|
+
subscriptionHashes = ['all@ticker']
|
644
|
+
subscribe: dict = {
|
429
645
|
'method': 'state.subscribe',
|
646
|
+
'params': {'market_list': marketIds},
|
430
647
|
'id': self.request_id(),
|
431
|
-
'params': [],
|
432
648
|
}
|
433
|
-
|
434
|
-
newTickers = await self.watch(url, messageHash, request, messageHash)
|
649
|
+
result = await self.watch_multiple(url, messageHashes, self.deep_extend(subscribe, params), subscriptionHashes)
|
435
650
|
if self.newUpdates:
|
436
|
-
return
|
651
|
+
return result
|
437
652
|
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
438
653
|
|
439
654
|
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
440
655
|
"""
|
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
656
|
get the list of most recent trades for a particular symbol
|
657
|
+
|
658
|
+
https://docs.coinex.com/api/v2/spot/market/ws/market-deals
|
659
|
+
https://docs.coinex.com/api/v2/futures/market/ws/market-deals
|
660
|
+
|
444
661
|
:param str symbol: unified symbol of the market to fetch trades for
|
445
662
|
:param int [since]: timestamp in ms of the earliest trade to fetch
|
446
663
|
:param int [limit]: the maximum amount of trades to fetch
|
447
664
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
448
665
|
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
449
666
|
"""
|
667
|
+
params['callerMethodName'] = 'watchTrades'
|
668
|
+
return await self.watch_trades_for_symbols([symbol], since, limit, params)
|
669
|
+
|
670
|
+
async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
671
|
+
"""
|
672
|
+
watch the most recent trades for a list of symbols
|
673
|
+
|
674
|
+
https://docs.coinex.com/api/v2/spot/market/ws/market-deals
|
675
|
+
https://docs.coinex.com/api/v2/futures/market/ws/market-deals
|
676
|
+
|
677
|
+
:param str[] symbols: unified symbols of the markets to fetch trades for
|
678
|
+
:param int [since]: timestamp in ms of the earliest trade to fetch
|
679
|
+
:param int [limit]: the maximum amount of trades to fetch
|
680
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
681
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
682
|
+
"""
|
450
683
|
await self.load_markets()
|
451
|
-
|
684
|
+
subscribedSymbols = []
|
685
|
+
messageHashes = []
|
686
|
+
market = None
|
687
|
+
callerMethodName = None
|
688
|
+
callerMethodName, params = self.handle_param_string(params, 'callerMethodName', 'watchTradesForSymbols')
|
689
|
+
symbolsDefined = (symbols is not None)
|
690
|
+
if symbolsDefined:
|
691
|
+
for i in range(0, len(symbols)):
|
692
|
+
symbol = symbols[i]
|
693
|
+
market = self.market(symbol)
|
694
|
+
subscribedSymbols.append(market['id'])
|
695
|
+
messageHashes.append('trades:' + market['symbol'])
|
696
|
+
else:
|
697
|
+
messageHashes.append('trades')
|
452
698
|
type = None
|
453
|
-
type, params = self.handle_market_type_and_params(
|
699
|
+
type, params = self.handle_market_type_and_params(callerMethodName, market, params)
|
454
700
|
url = self.urls['api']['ws'][type]
|
455
|
-
|
456
|
-
|
457
|
-
subscribedSymbols = self.safe_value(self.options, 'watchTradesSubscriptions', [])
|
458
|
-
subscribedSymbols.append(market['id'])
|
459
|
-
message = {
|
701
|
+
subscriptionHashes = ['trades']
|
702
|
+
subscribe: dict = {
|
460
703
|
'method': 'deals.subscribe',
|
461
|
-
'params': subscribedSymbols,
|
704
|
+
'params': {'market_list': subscribedSymbols},
|
462
705
|
'id': self.request_id(),
|
463
706
|
}
|
464
|
-
self.
|
465
|
-
|
466
|
-
|
707
|
+
trades = await self.watch_multiple(url, messageHashes, self.deep_extend(subscribe, params), subscriptionHashes)
|
708
|
+
if self.newUpdates:
|
709
|
+
return trades
|
467
710
|
return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
|
468
711
|
|
469
|
-
async def
|
712
|
+
async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
|
470
713
|
"""
|
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
714
|
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
474
|
-
|
715
|
+
|
716
|
+
https://docs.coinex.com/api/v2/spot/market/ws/market-depth
|
717
|
+
https://docs.coinex.com/api/v2/futures/market/ws/market-depth
|
718
|
+
|
719
|
+
:param str[] symbols: unified array of symbols
|
475
720
|
:param int [limit]: the maximum amount of order book entries to return
|
476
721
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
477
722
|
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
478
723
|
"""
|
479
724
|
await self.load_markets()
|
480
|
-
|
481
|
-
|
725
|
+
watchOrderBookSubscriptions: dict = {}
|
726
|
+
messageHashes = []
|
727
|
+
market = None
|
482
728
|
type = None
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
limits = self.safe_value(options, 'limits', [])
|
729
|
+
callerMethodName = None
|
730
|
+
callerMethodName, params = self.handle_param_string(params, 'callerMethodName', 'watchOrderBookForSymbols')
|
731
|
+
type, params = self.handle_market_type_and_params(callerMethodName, None, params)
|
732
|
+
options = self.safe_dict(self.options, 'watchOrderBook', {})
|
733
|
+
limits = self.safe_list(options, 'limits', [])
|
489
734
|
if limit is None:
|
490
|
-
limit = self.
|
735
|
+
limit = self.safe_integer(options, 'defaultLimit', 50)
|
491
736
|
if not self.in_array(limit, limits):
|
492
|
-
raise NotSupported(self.id + '
|
737
|
+
raise NotSupported(self.id + ' watchOrderBookForSymbols() limit must be one of ' + ', '.join(limits))
|
493
738
|
defaultAggregation = self.safe_string(options, 'defaultAggregation', '0')
|
494
|
-
aggregations = self.
|
739
|
+
aggregations = self.safe_list(options, 'aggregations', [])
|
495
740
|
aggregation = self.safe_string(params, 'aggregation', defaultAggregation)
|
496
741
|
if not self.in_array(aggregation, aggregations):
|
497
|
-
raise NotSupported(self.id + '
|
742
|
+
raise NotSupported(self.id + ' watchOrderBookForSymbols() aggregation must be one of ' + ', '.join(aggregations))
|
498
743
|
params = self.omit(params, 'aggregation')
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
744
|
+
symbolsDefined = (symbols is not None)
|
745
|
+
if symbolsDefined:
|
746
|
+
for i in range(0, len(symbols)):
|
747
|
+
symbol = symbols[i]
|
748
|
+
market = self.market(symbol)
|
749
|
+
messageHashes.append('orderbook:' + market['symbol'])
|
750
|
+
watchOrderBookSubscriptions[symbol] = [market['id'], limit, aggregation, True]
|
751
|
+
else:
|
752
|
+
messageHashes.append('orderbook')
|
753
|
+
marketList = list(watchOrderBookSubscriptions.values())
|
754
|
+
subscribe: dict = {
|
755
|
+
'method': 'depth.subscribe',
|
756
|
+
'params': {'market_list': marketList},
|
503
757
|
'id': self.request_id(),
|
504
|
-
'params': list(watchOrderBookSubscriptions.values()),
|
505
758
|
}
|
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')
|
759
|
+
subscriptionHashes = self.hash(self.encode(self.json(watchOrderBookSubscriptions)), 'sha256')
|
530
760
|
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 = {
|
543
|
-
'method': 'kline.subscribe',
|
544
|
-
'id': self.request_id(),
|
545
|
-
'params': [
|
546
|
-
market['id'],
|
547
|
-
self.safe_integer(timeframes, timeframe),
|
548
|
-
],
|
549
|
-
}
|
550
|
-
subscription = {
|
551
|
-
'symbol': symbol,
|
552
|
-
'timeframe': timeframe,
|
553
|
-
}
|
554
|
-
request = self.deep_extend(subscribe, params)
|
555
|
-
ohlcvs = await self.watch(url, messageHash, request, messageHash, subscription)
|
761
|
+
orderbooks = await self.watch_multiple(url, messageHashes, self.deep_extend(subscribe, params), subscriptionHashes)
|
556
762
|
if self.newUpdates:
|
557
|
-
|
558
|
-
return
|
763
|
+
return orderbooks
|
764
|
+
return orderbooks.limit()
|
559
765
|
|
560
|
-
async def
|
766
|
+
async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
561
767
|
"""
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
:param
|
568
|
-
:param
|
569
|
-
:param
|
570
|
-
:returns
|
768
|
+
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
769
|
+
|
770
|
+
https://docs.coinex.com/api/v2/spot/market/ws/market-depth
|
771
|
+
https://docs.coinex.com/api/v2/futures/market/ws/market-depth
|
772
|
+
|
773
|
+
:param str symbol: unified symbol of the market to fetch the order book for
|
774
|
+
:param int [limit]: the maximum amount of order book entries to return
|
775
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
776
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
571
777
|
"""
|
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 = {
|
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 = {
|
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)
|
778
|
+
params['callerMethodName'] = 'watchOrderBook'
|
779
|
+
return await self.watch_order_book_for_symbols([symbol], limit, params)
|
601
780
|
|
602
781
|
def handle_delta(self, bookside, delta):
|
603
782
|
bidAsk = self.parse_bid_ask(delta, 0, 1)
|
@@ -611,48 +790,51 @@ class coinex(ccxt.async_support.coinex):
|
|
611
790
|
#
|
612
791
|
# {
|
613
792
|
# "method": "depth.update",
|
614
|
-
# "
|
615
|
-
#
|
616
|
-
#
|
793
|
+
# "data": {
|
794
|
+
# "market": "BTCUSDT",
|
795
|
+
# "is_full": True,
|
796
|
+
# "depth": {
|
617
797
|
# "asks": [
|
618
|
-
# [
|
619
|
-
#
|
798
|
+
# [
|
799
|
+
# "30740.00",
|
800
|
+
# "0.31763545"
|
801
|
+
# ],
|
620
802
|
# ],
|
621
803
|
# "bids": [
|
622
|
-
# [
|
623
|
-
#
|
804
|
+
# [
|
805
|
+
# "30736.00",
|
806
|
+
# "0.04857373"
|
807
|
+
# ],
|
624
808
|
# ],
|
625
|
-
# "last": "
|
626
|
-
# "
|
627
|
-
# "checksum":
|
628
|
-
# }
|
629
|
-
#
|
630
|
-
# ],
|
809
|
+
# "last": "30746.28",
|
810
|
+
# "updated_at": 1689152421692,
|
811
|
+
# "checksum": 2578768879
|
812
|
+
# }
|
813
|
+
# },
|
631
814
|
# "id": null
|
632
815
|
# }
|
633
816
|
#
|
634
|
-
params = self.safe_value(message, 'params', [])
|
635
|
-
fullOrderBook = self.safe_value(params, 0)
|
636
|
-
orderbook = self.safe_value(params, 1)
|
637
|
-
marketId = self.safe_string(params, 2)
|
638
817
|
defaultType = self.safe_string(self.options, 'defaultType')
|
818
|
+
data = self.safe_dict(message, 'data', {})
|
819
|
+
depth = self.safe_dict(data, 'depth', {})
|
820
|
+
marketId = self.safe_string(data, 'market')
|
639
821
|
market = self.safe_market(marketId, None, None, defaultType)
|
640
822
|
symbol = market['symbol']
|
641
823
|
name = 'orderbook'
|
642
824
|
messageHash = name + ':' + symbol
|
643
|
-
timestamp = self.safe_integer(
|
825
|
+
timestamp = self.safe_integer(depth, 'updated_at')
|
644
826
|
currentOrderBook = self.safe_value(self.orderbooks, symbol)
|
827
|
+
fullOrderBook = self.safe_bool(data, 'is_full', False)
|
645
828
|
if fullOrderBook:
|
646
|
-
snapshot = self.parse_order_book(
|
829
|
+
snapshot = self.parse_order_book(depth, symbol, timestamp)
|
647
830
|
if currentOrderBook is None:
|
648
|
-
|
649
|
-
self.orderbooks[symbol] = orderbook
|
831
|
+
self.orderbooks[symbol] = self.order_book(snapshot)
|
650
832
|
else:
|
651
833
|
orderbook = self.orderbooks[symbol]
|
652
834
|
orderbook.reset(snapshot)
|
653
835
|
else:
|
654
|
-
asks = self.
|
655
|
-
bids = self.
|
836
|
+
asks = self.safe_list(depth, 'asks', [])
|
837
|
+
bids = self.safe_list(depth, 'bids', [])
|
656
838
|
self.handle_deltas(currentOrderBook['asks'], asks)
|
657
839
|
self.handle_deltas(currentOrderBook['bids'], bids)
|
658
840
|
currentOrderBook['nonce'] = timestamp
|
@@ -663,24 +845,52 @@ class coinex(ccxt.async_support.coinex):
|
|
663
845
|
client.resolve(self.orderbooks[symbol], messageHash)
|
664
846
|
|
665
847
|
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
848
|
+
"""
|
849
|
+
watches information on multiple orders made by the user
|
850
|
+
|
851
|
+
https://docs.coinex.com/api/v2/spot/order/ws/user-order
|
852
|
+
https://docs.coinex.com/api/v2/futures/order/ws/user-order
|
853
|
+
|
854
|
+
:param str symbol: unified market symbol of the market orders were made in
|
855
|
+
:param int [since]: the earliest time in ms to fetch orders for
|
856
|
+
:param int [limit]: the maximum number of order structures to retrieve
|
857
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
858
|
+
:param bool [params.trigger]: if the orders to watch are trigger orders or not
|
859
|
+
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
860
|
+
"""
|
666
861
|
await self.load_markets()
|
667
|
-
|
862
|
+
trigger = self.safe_bool_2(params, 'trigger', 'stop')
|
863
|
+
params = self.omit(params, ['trigger', 'stop'])
|
668
864
|
messageHash = 'orders'
|
669
865
|
market = None
|
670
|
-
|
671
|
-
message = {
|
672
|
-
'method': 'order.subscribe',
|
673
|
-
'id': self.request_id(),
|
674
|
-
}
|
866
|
+
marketList = None
|
675
867
|
if symbol is not None:
|
676
868
|
market = self.market(symbol)
|
677
869
|
symbol = market['symbol']
|
678
|
-
|
870
|
+
type = None
|
871
|
+
type, params = self.handle_market_type_and_params('watchOrders', market, params, 'spot')
|
872
|
+
await self.authenticate(type)
|
873
|
+
if symbol is not None:
|
874
|
+
marketList = [market['id']]
|
679
875
|
messageHash += ':' + symbol
|
680
876
|
else:
|
681
|
-
|
877
|
+
marketList = []
|
878
|
+
if type == 'spot':
|
879
|
+
messageHash += ':spot'
|
880
|
+
else:
|
881
|
+
messageHash += ':swap'
|
882
|
+
method = None
|
883
|
+
if trigger:
|
884
|
+
method = 'stop.subscribe'
|
885
|
+
else:
|
886
|
+
method = 'order.subscribe'
|
887
|
+
message: dict = {
|
888
|
+
'method': method,
|
889
|
+
'params': {'market_list': marketList},
|
890
|
+
'id': self.request_id(),
|
891
|
+
}
|
682
892
|
url = self.urls['api']['ws'][type]
|
683
|
-
request = self.deep_extend(message,
|
893
|
+
request = self.deep_extend(message, params)
|
684
894
|
orders = await self.watch(url, messageHash, request, messageHash, request)
|
685
895
|
if self.newUpdates:
|
686
896
|
limit = orders.getLimit(symbol, limit)
|
@@ -688,280 +898,372 @@ class coinex(ccxt.async_support.coinex):
|
|
688
898
|
|
689
899
|
def handle_orders(self, client: Client, message):
|
690
900
|
#
|
691
|
-
#
|
901
|
+
# spot
|
692
902
|
#
|
693
|
-
#
|
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
|
-
# "last_deal_price": "0",
|
722
|
-
# "last_deal_time": 0,
|
723
|
-
# "last_deal_id": 0,
|
724
|
-
# "last_role": 0,
|
725
|
-
# "fee_asset": null,
|
726
|
-
# "stop_id": 0
|
727
|
-
# }
|
728
|
-
# ],
|
729
|
-
# "id": null
|
730
|
-
# }
|
903
|
+
# {
|
904
|
+
# "method": "order.update",
|
905
|
+
# "data": {
|
906
|
+
# "event": "put",
|
907
|
+
# "order": {
|
908
|
+
# "order_id": 12750,
|
909
|
+
# "market": "BTCUSDT",
|
910
|
+
# "margin_market": "BTCUSDT",
|
911
|
+
# "type": "limit",
|
912
|
+
# "side": "buy",
|
913
|
+
# "price": "5999.00",
|
914
|
+
# "amount": "1.50000000",
|
915
|
+
# "unfill_amount": "1.50000000",
|
916
|
+
# "fill_value": "1.50000000",
|
917
|
+
# "taker_fee_rate": "0.0001",
|
918
|
+
# "maker_fee_rate": "0.0001",
|
919
|
+
# "base_ccy_fee": "0.0001",
|
920
|
+
# "quote_ccy_fee": "0.0001",
|
921
|
+
# "discount_ccy_fee": "0.0001",
|
922
|
+
# "last_fill_amount": "0",
|
923
|
+
# "last_fill_price": "0",
|
924
|
+
# "client_id": "buy1_1234",
|
925
|
+
# "created_at": 1689152421692,
|
926
|
+
# "updated_at": 1689152421692,
|
927
|
+
# }
|
928
|
+
# },
|
929
|
+
# "id": null
|
930
|
+
# }
|
731
931
|
#
|
732
|
-
#
|
932
|
+
# spot stop
|
933
|
+
#
|
934
|
+
# {
|
935
|
+
# "method": "stop.update",
|
936
|
+
# "data": {
|
937
|
+
# "event": 1,
|
938
|
+
# "stop": {
|
939
|
+
# "stop_id": 102067022299,
|
940
|
+
# "market": "BTCUSDT",
|
941
|
+
# "margin_market": "BTCUSDT",
|
942
|
+
# "type": "limit",
|
943
|
+
# "side": "buy",
|
944
|
+
# "price": "20000.00",
|
945
|
+
# "amount": "0.10000000",
|
946
|
+
# "trigger_price": "20000.00",
|
947
|
+
# "trigger_direction": "lower",
|
948
|
+
# "taker_fee_rate": "0.0016",
|
949
|
+
# "maker_fee_rate": "0.0016",
|
950
|
+
# "status": "active_success",
|
951
|
+
# "client_id": "",
|
952
|
+
# "created_at": 1689152996689,
|
953
|
+
# "updated_at": 1689152996689,
|
954
|
+
# }
|
955
|
+
# },
|
956
|
+
# "id": null
|
957
|
+
# }
|
733
958
|
#
|
734
|
-
#
|
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
|
-
|
959
|
+
# swap
|
960
|
+
#
|
961
|
+
# {
|
962
|
+
# "method": "order.update",
|
963
|
+
# "data": {
|
964
|
+
# "event": "put",
|
965
|
+
# "order": {
|
966
|
+
# "order_id": 98388656341,
|
967
|
+
# "stop_id": 0,
|
968
|
+
# "market": "BTCUSDT",
|
969
|
+
# "side": "buy",
|
970
|
+
# "type": "limit",
|
971
|
+
# "amount": "0.0010",
|
972
|
+
# "price": "50000.00",
|
973
|
+
# "unfilled_amount": "0.0010",
|
974
|
+
# "filled_amount": "0",
|
975
|
+
# "filled_value": "0",
|
976
|
+
# "fee": "0",
|
977
|
+
# "fee_ccy": "USDT",
|
978
|
+
# "taker_fee_rate": "0.00046",
|
979
|
+
# "maker_fee_rate": "0.00000000000000000000",
|
980
|
+
# "client_id": "",
|
981
|
+
# "last_filled_amount": "0.0010",
|
982
|
+
# "last_filled_price": "30721.35",
|
983
|
+
# "created_at": 1689145715129,
|
984
|
+
# "updated_at": 1689145715129
|
985
|
+
# }
|
986
|
+
# },
|
987
|
+
# "id": null
|
988
|
+
# }
|
989
|
+
#
|
990
|
+
# swap stop
|
991
|
+
#
|
992
|
+
# {
|
993
|
+
# "method": "stop.update",
|
994
|
+
# "data": {
|
995
|
+
# "event": "put",
|
996
|
+
# "stop": {
|
997
|
+
# "stop_id": 98389557871,
|
998
|
+
# "market": "BTCUSDT",
|
999
|
+
# "side": "sell",
|
1000
|
+
# "type": "limit",
|
1001
|
+
# "price": "20000.00",
|
1002
|
+
# "amount": "0.0100",
|
1003
|
+
# "trigger_price": "20000.00",
|
1004
|
+
# "trigger_direction": "higer",
|
1005
|
+
# "trigger_price_type": "index_price",
|
1006
|
+
# "taker_fee_rate": "0.00046",
|
1007
|
+
# "maker_fee_rate": "0.00026",
|
1008
|
+
# "client_id": "",
|
1009
|
+
# "created_at": 1689146382674,
|
1010
|
+
# "updated_at": 1689146382674
|
1011
|
+
# }
|
1012
|
+
# },
|
1013
|
+
# "id": null
|
1014
|
+
# }
|
1015
|
+
#
|
1016
|
+
data = self.safe_dict(message, 'data', {})
|
1017
|
+
order = self.safe_dict_2(data, 'order', 'stop', {})
|
778
1018
|
parsedOrder = self.parse_ws_order(order)
|
1019
|
+
symbol = parsedOrder['symbol']
|
1020
|
+
market = self.market(symbol)
|
779
1021
|
if self.orders is None:
|
780
1022
|
limit = self.safe_integer(self.options, 'ordersLimit', 1000)
|
781
1023
|
self.orders = ArrayCacheBySymbolById(limit)
|
782
1024
|
orders = self.orders
|
783
1025
|
orders.append(parsedOrder)
|
784
1026
|
messageHash = 'orders'
|
785
|
-
|
786
|
-
|
1027
|
+
messageWithType = messageHash + ':' + market['type']
|
1028
|
+
client.resolve(self.orders, messageWithType)
|
1029
|
+
messageHash += ':' + symbol
|
787
1030
|
client.resolve(self.orders, messageHash)
|
788
1031
|
|
789
1032
|
def parse_ws_order(self, order, market=None):
|
790
1033
|
#
|
791
|
-
#
|
1034
|
+
# spot
|
1035
|
+
#
|
1036
|
+
# {
|
1037
|
+
# "order_id": 12750,
|
1038
|
+
# "market": "BTCUSDT",
|
1039
|
+
# "margin_market": "BTCUSDT",
|
1040
|
+
# "type": "limit",
|
1041
|
+
# "side": "buy",
|
1042
|
+
# "price": "5999.00",
|
1043
|
+
# "amount": "1.50000000",
|
1044
|
+
# "unfill_amount": "1.50000000",
|
1045
|
+
# "fill_value": "1.50000000",
|
1046
|
+
# "taker_fee_rate": "0.0001",
|
1047
|
+
# "maker_fee_rate": "0.0001",
|
1048
|
+
# "base_ccy_fee": "0.0001",
|
1049
|
+
# "quote_ccy_fee": "0.0001",
|
1050
|
+
# "discount_ccy_fee": "0.0001",
|
1051
|
+
# "last_fill_amount": "0",
|
1052
|
+
# "last_fill_price": "0",
|
1053
|
+
# "client_id": "buy1_1234",
|
1054
|
+
# "created_at": 1689152421692,
|
1055
|
+
# "updated_at": 1689152421692,
|
1056
|
+
# }
|
792
1057
|
#
|
793
|
-
#
|
794
|
-
# "id": 77782469357,
|
795
|
-
# "type": 1,
|
796
|
-
# "side": 2,
|
797
|
-
# "user": 1849116,
|
798
|
-
# "account": 0,
|
799
|
-
# "option": 2,
|
800
|
-
# "ctime": 1653961043.048967,
|
801
|
-
# "mtime": 1653961043.048967,
|
802
|
-
# "market": "BTCUSDT",
|
803
|
-
# "source": "web",
|
804
|
-
# "client_id": '',
|
805
|
-
# "price": "1.00",
|
806
|
-
# "amount": "1.00000000",
|
807
|
-
# "taker_fee": "0.0020",
|
808
|
-
# "maker_fee": "0.0020",
|
809
|
-
# "left": "1.00000000",
|
810
|
-
# "deal_stock": "0",
|
811
|
-
# "deal_money": "0",
|
812
|
-
# "money_fee": "0",
|
813
|
-
# "stock_fee": "0",
|
814
|
-
# "asset_fee": "0",
|
815
|
-
# "fee_discount": "1",
|
816
|
-
# "last_deal_amount": "0",
|
817
|
-
# "last_deal_price": "0",
|
818
|
-
# "last_deal_time": 0,
|
819
|
-
# "last_deal_id": 0,
|
820
|
-
# "last_role": 0,
|
821
|
-
# "fee_asset": null,
|
822
|
-
# "stop_id": 0
|
823
|
-
# }
|
1058
|
+
# spot stop
|
824
1059
|
#
|
825
|
-
#
|
1060
|
+
# {
|
1061
|
+
# "stop_id": 102067022299,
|
1062
|
+
# "market": "BTCUSDT",
|
1063
|
+
# "margin_market": "BTCUSDT",
|
1064
|
+
# "type": "limit",
|
1065
|
+
# "side": "buy",
|
1066
|
+
# "price": "20000.00",
|
1067
|
+
# "amount": "0.10000000",
|
1068
|
+
# "trigger_price": "20000.00",
|
1069
|
+
# "trigger_direction": "lower",
|
1070
|
+
# "taker_fee_rate": "0.0016",
|
1071
|
+
# "maker_fee_rate": "0.0016",
|
1072
|
+
# "status": "active_success",
|
1073
|
+
# "client_id": "",
|
1074
|
+
# "created_at": 1689152996689,
|
1075
|
+
# "updated_at": 1689152996689,
|
1076
|
+
# }
|
1077
|
+
#
|
1078
|
+
# swap
|
1079
|
+
#
|
1080
|
+
# {
|
1081
|
+
# "order_id": 98388656341,
|
1082
|
+
# "stop_id": 0,
|
1083
|
+
# "market": "BTCUSDT",
|
1084
|
+
# "side": "buy",
|
1085
|
+
# "type": "limit",
|
1086
|
+
# "amount": "0.0010",
|
1087
|
+
# "price": "50000.00",
|
1088
|
+
# "unfilled_amount": "0.0010",
|
1089
|
+
# "filled_amount": "0",
|
1090
|
+
# "filled_value": "0",
|
1091
|
+
# "fee": "0",
|
1092
|
+
# "fee_ccy": "USDT",
|
1093
|
+
# "taker_fee_rate": "0.00046",
|
1094
|
+
# "maker_fee_rate": "0.00000000000000000000",
|
1095
|
+
# "client_id": "",
|
1096
|
+
# "last_filled_amount": "0.0010",
|
1097
|
+
# "last_filled_price": "30721.35",
|
1098
|
+
# "created_at": 1689145715129,
|
1099
|
+
# "updated_at": 1689145715129
|
1100
|
+
# }
|
1101
|
+
#
|
1102
|
+
# swap stop
|
1103
|
+
#
|
1104
|
+
# {
|
1105
|
+
# "stop_id": 98389557871,
|
1106
|
+
# "market": "BTCUSDT",
|
1107
|
+
# "side": "sell",
|
1108
|
+
# "type": "limit",
|
1109
|
+
# "price": "20000.00",
|
1110
|
+
# "amount": "0.0100",
|
1111
|
+
# "trigger_price": "20000.00",
|
1112
|
+
# "trigger_direction": "higer",
|
1113
|
+
# "trigger_price_type": "index_price",
|
1114
|
+
# "taker_fee_rate": "0.00046",
|
1115
|
+
# "maker_fee_rate": "0.00026",
|
1116
|
+
# "client_id": "",
|
1117
|
+
# "created_at": 1689146382674,
|
1118
|
+
# "updated_at": 1689146382674
|
1119
|
+
# }
|
826
1120
|
#
|
827
|
-
|
828
|
-
# "order_id": 23423462821,
|
829
|
-
# "position_id": 0,
|
830
|
-
# "stop_id": 0,
|
831
|
-
# "market": "BTCUSDT",
|
832
|
-
# "type": 1,
|
833
|
-
# "side": 2,
|
834
|
-
# "target": 0,
|
835
|
-
# "effect_type": 1,
|
836
|
-
# "user_id": 1849116,
|
837
|
-
# "create_time": 1653961509.25049,
|
838
|
-
# "update_time": 1653961509.25049,
|
839
|
-
# "source": "web",
|
840
|
-
# "price": "1.00",
|
841
|
-
# "amount": "1.0000",
|
842
|
-
# "taker_fee": "0.00050",
|
843
|
-
# "maker_fee": "0.00030",
|
844
|
-
# "left": "1.0000",
|
845
|
-
# "deal_stock": "0.00000000000000000000",
|
846
|
-
# "deal_fee": "0.00000000000000000000",
|
847
|
-
# "deal_profit": "0.00000000000000000000",
|
848
|
-
# "last_deal_amount": "0.00000000000000000000",
|
849
|
-
# "last_deal_price": "0.00000000000000000000",
|
850
|
-
# "last_deal_time": 0,
|
851
|
-
# "last_deal_id": 0,
|
852
|
-
# "last_deal_type": 0,
|
853
|
-
# "last_deal_role": 0,
|
854
|
-
# "client_id": '',
|
855
|
-
# "fee_asset": '',
|
856
|
-
# "fee_discount": "0.00000000000000000000",
|
857
|
-
# "deal_asset_fee": "0.00000000000000000000",
|
858
|
-
# "leverage": "3",
|
859
|
-
# "position_type": 2
|
860
|
-
# }
|
861
|
-
#
|
862
|
-
# order.update_stop
|
863
|
-
#
|
864
|
-
# {
|
865
|
-
# "id": 78006745870,
|
866
|
-
# "type": 1,
|
867
|
-
# "side": 2,
|
868
|
-
# "user": 1849116,
|
869
|
-
# "account": 1,
|
870
|
-
# "option": 70,
|
871
|
-
# "direction": 1,
|
872
|
-
# "ctime": 1654171725.131976,
|
873
|
-
# "mtime": 1654171725.131976,
|
874
|
-
# "market": "BTCUSDT",
|
875
|
-
# "source": "web",
|
876
|
-
# "client_id": '',
|
877
|
-
# "stop_price": "1.00",
|
878
|
-
# "price": "1.00",
|
879
|
-
# "amount": "1.00000000",
|
880
|
-
# "taker_fee": "0.0020",
|
881
|
-
# "maker_fee": "0.0020",
|
882
|
-
# "fee_discount": "1",
|
883
|
-
# "fee_asset": null,
|
884
|
-
# "status": 0
|
885
|
-
# }
|
886
|
-
#
|
887
|
-
timestamp = self.safe_timestamp_2(order, 'update_time', 'mtime')
|
1121
|
+
timestamp = self.safe_integer(order, 'created_at')
|
888
1122
|
marketId = self.safe_string(order, 'market')
|
889
|
-
typeCode = self.safe_string(order, 'type')
|
890
|
-
type = self.safe_string({
|
891
|
-
'1': 'limit',
|
892
|
-
'2': 'market',
|
893
|
-
}, typeCode)
|
894
|
-
sideCode = self.safe_string(order, 'side')
|
895
|
-
side = self.safe_string({
|
896
|
-
'1': 'sell',
|
897
|
-
'2': 'buy',
|
898
|
-
}, sideCode)
|
899
|
-
remaining = self.safe_string(order, 'left')
|
900
|
-
amount = self.safe_string(order, 'amount')
|
901
1123
|
status = self.safe_string(order, 'status')
|
902
|
-
|
1124
|
+
isSpot = ('margin_market' in order)
|
1125
|
+
defaultType = 'spot' if isSpot else 'swap'
|
903
1126
|
market = self.safe_market(marketId, market, None, defaultType)
|
904
|
-
cost = self.safe_string(order, 'deal_money')
|
905
|
-
filled = self.safe_string(order, 'deal_stock')
|
906
|
-
average = None
|
907
|
-
if market['swap']:
|
908
|
-
leverage = self.safe_string(order, 'leverage')
|
909
|
-
cost = Precise.string_div(filled, leverage)
|
910
|
-
average = Precise.string_div(filled, amount)
|
911
|
-
filled = None
|
912
1127
|
fee = None
|
913
|
-
feeCost = self.omit_zero(self.
|
1128
|
+
feeCost = self.omit_zero(self.safe_string_2(order, 'fee', 'quote_ccy_fee'))
|
914
1129
|
if feeCost is not None:
|
915
|
-
feeCurrencyId = self.safe_string(order, '
|
1130
|
+
feeCurrencyId = self.safe_string(order, 'fee_ccy', market['quote'])
|
916
1131
|
fee = {
|
917
1132
|
'currency': self.safe_currency_code(feeCurrencyId),
|
918
1133
|
'cost': feeCost,
|
919
1134
|
}
|
920
1135
|
return self.safe_order({
|
921
1136
|
'info': order,
|
922
|
-
'id': self.safe_string_2(order, 'order_id', '
|
1137
|
+
'id': self.safe_string_2(order, 'order_id', 'stop_id'),
|
923
1138
|
'clientOrderId': self.safe_string(order, 'client_id'),
|
924
1139
|
'datetime': self.iso8601(timestamp),
|
925
1140
|
'timestamp': timestamp,
|
926
|
-
'lastTradeTimestamp': self.
|
1141
|
+
'lastTradeTimestamp': self.safe_integer(order, 'updated_at'),
|
927
1142
|
'symbol': market['symbol'],
|
928
|
-
'type': type,
|
1143
|
+
'type': self.safe_string(order, 'type'),
|
929
1144
|
'timeInForce': None,
|
930
1145
|
'postOnly': None,
|
931
|
-
'side': side,
|
1146
|
+
'side': self.safe_string(order, 'side'),
|
932
1147
|
'price': self.safe_string(order, 'price'),
|
933
|
-
'stopPrice': self.safe_string(order, '
|
934
|
-
'triggerPrice': self.safe_string(order, '
|
935
|
-
'amount': amount,
|
936
|
-
'filled':
|
937
|
-
'remaining':
|
938
|
-
'cost':
|
939
|
-
'average':
|
1148
|
+
'stopPrice': self.safe_string(order, 'trigger_price'),
|
1149
|
+
'triggerPrice': self.safe_string(order, 'trigger_price'),
|
1150
|
+
'amount': self.safe_string(order, 'amount'),
|
1151
|
+
'filled': self.safe_string_2(order, 'filled_amount', 'fill_value'),
|
1152
|
+
'remaining': self.safe_string_2(order, 'unfilled_amount', 'unfill_amount'),
|
1153
|
+
'cost': None,
|
1154
|
+
'average': None,
|
940
1155
|
'status': self.parse_ws_order_status(status),
|
941
1156
|
'fee': fee,
|
942
1157
|
'trades': None,
|
943
1158
|
}, market)
|
944
1159
|
|
945
1160
|
def parse_ws_order_status(self, status):
|
946
|
-
statuses = {
|
947
|
-
'
|
948
|
-
'
|
1161
|
+
statuses: dict = {
|
1162
|
+
'active_success': 'open',
|
1163
|
+
'active_fail': 'canceled',
|
1164
|
+
'cancel': 'canceled',
|
949
1165
|
}
|
950
1166
|
return self.safe_string(statuses, status, status)
|
951
1167
|
|
1168
|
+
async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
|
1169
|
+
"""
|
1170
|
+
watches best bid & ask for symbols
|
1171
|
+
|
1172
|
+
https://docs.coinex.com/api/v2/spot/market/ws/market-bbo
|
1173
|
+
https://docs.coinex.com/api/v2/futures/market/ws/market-bbo
|
1174
|
+
|
1175
|
+
:param str[] [symbols]: unified symbol of the market to fetch the ticker for
|
1176
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1177
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
1178
|
+
"""
|
1179
|
+
await self.load_markets()
|
1180
|
+
marketIds = self.market_ids(symbols)
|
1181
|
+
messageHashes = []
|
1182
|
+
market = None
|
1183
|
+
symbolsDefined = (symbols is not None)
|
1184
|
+
if symbolsDefined:
|
1185
|
+
for i in range(0, len(symbols)):
|
1186
|
+
symbol = symbols[i]
|
1187
|
+
market = self.market(symbol)
|
1188
|
+
messageHashes.append('bidsasks:' + market['symbol'])
|
1189
|
+
else:
|
1190
|
+
messageHashes.append('bidsasks')
|
1191
|
+
type = None
|
1192
|
+
type, params = self.handle_market_type_and_params('watchBidsAsks', market, params)
|
1193
|
+
url = self.urls['api']['ws'][type]
|
1194
|
+
subscriptionHashes = ['all@bidsasks']
|
1195
|
+
subscribe: dict = {
|
1196
|
+
'method': 'bbo.subscribe',
|
1197
|
+
'params': {'market_list': marketIds},
|
1198
|
+
'id': self.request_id(),
|
1199
|
+
}
|
1200
|
+
result = await self.watch_multiple(url, messageHashes, self.deep_extend(subscribe, params), subscriptionHashes)
|
1201
|
+
if self.newUpdates:
|
1202
|
+
return result
|
1203
|
+
return self.filter_by_array(self.bidsasks, 'symbol', symbols)
|
1204
|
+
|
1205
|
+
def handle_bid_ask(self, client: Client, message):
|
1206
|
+
#
|
1207
|
+
# {
|
1208
|
+
# "method": "bbo.update",
|
1209
|
+
# "data": {
|
1210
|
+
# "market": "BTCUSDT",
|
1211
|
+
# "updated_at": 1656660154,
|
1212
|
+
# "best_bid_price": "20000",
|
1213
|
+
# "best_bid_size": "0.1",
|
1214
|
+
# "best_ask_price": "20001",
|
1215
|
+
# "best_ask_size": "0.15"
|
1216
|
+
# },
|
1217
|
+
# "id": null
|
1218
|
+
# }
|
1219
|
+
#
|
1220
|
+
data = self.safe_dict(message, 'data', {})
|
1221
|
+
parsedTicker = self.parse_ws_bid_ask(data)
|
1222
|
+
symbol = parsedTicker['symbol']
|
1223
|
+
self.bidsasks[symbol] = parsedTicker
|
1224
|
+
messageHash = 'bidsasks:' + symbol
|
1225
|
+
client.resolve(parsedTicker, messageHash)
|
1226
|
+
|
1227
|
+
def parse_ws_bid_ask(self, ticker, market=None):
|
1228
|
+
#
|
1229
|
+
# {
|
1230
|
+
# "market": "BTCUSDT",
|
1231
|
+
# "updated_at": 1656660154,
|
1232
|
+
# "best_bid_price": "20000",
|
1233
|
+
# "best_bid_size": "0.1",
|
1234
|
+
# "best_ask_price": "20001",
|
1235
|
+
# "best_ask_size": "0.15"
|
1236
|
+
# }
|
1237
|
+
#
|
1238
|
+
defaultType = self.safe_string(self.options, 'defaultType')
|
1239
|
+
marketId = self.safe_string(ticker, 'market')
|
1240
|
+
market = self.safe_market(marketId, market, None, defaultType)
|
1241
|
+
timestamp = self.safe_integer(ticker, 'updated_at')
|
1242
|
+
return self.safe_ticker({
|
1243
|
+
'symbol': self.safe_symbol(marketId, market, None, defaultType),
|
1244
|
+
'timestamp': timestamp,
|
1245
|
+
'datetime': self.iso8601(timestamp),
|
1246
|
+
'ask': self.safe_number(ticker, 'best_ask_price'),
|
1247
|
+
'askVolume': self.safe_number(ticker, 'best_ask_size'),
|
1248
|
+
'bid': self.safe_number(ticker, 'best_bid_price'),
|
1249
|
+
'bidVolume': self.safe_number(ticker, 'best_bid_size'),
|
1250
|
+
'info': ticker,
|
1251
|
+
}, market)
|
1252
|
+
|
952
1253
|
def handle_message(self, client: Client, message):
|
953
|
-
error = self.safe_value(message, 'error')
|
954
|
-
if error is not None:
|
955
|
-
raise ExchangeError(self.id + ' ' + self.json(error))
|
956
1254
|
method = self.safe_string(message, 'method')
|
957
|
-
|
1255
|
+
error = self.safe_string(message, 'message')
|
1256
|
+
if error is not None:
|
1257
|
+
self.handle_errors(None, None, client.url, method, None, self.json(error), message, None, None)
|
1258
|
+
handlers: dict = {
|
958
1259
|
'state.update': self.handle_ticker,
|
959
|
-
'
|
1260
|
+
'balance.update': self.handle_balance,
|
960
1261
|
'deals.update': self.handle_trades,
|
1262
|
+
'user_deals.update': self.handle_my_trades,
|
961
1263
|
'depth.update': self.handle_order_book,
|
962
1264
|
'order.update': self.handle_orders,
|
963
|
-
'
|
964
|
-
'
|
1265
|
+
'stop.update': self.handle_orders,
|
1266
|
+
'bbo.update': self.handle_bid_ask,
|
965
1267
|
}
|
966
1268
|
handler = self.safe_value(handlers, method)
|
967
1269
|
if handler is not None:
|
@@ -969,86 +1271,90 @@ class coinex(ccxt.async_support.coinex):
|
|
969
1271
|
return
|
970
1272
|
self.handle_subscription_status(client, message)
|
971
1273
|
|
1274
|
+
def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
|
1275
|
+
if response is None:
|
1276
|
+
return None
|
1277
|
+
#
|
1278
|
+
# {"id": 1, "code": 20001, "message": "invalid argument"}
|
1279
|
+
# {"id": 2, "code": 21001, "message": "require auth"}
|
1280
|
+
# {"id": 1, "code": 21002, "message": "Signature Incorrect"}
|
1281
|
+
#
|
1282
|
+
message = self.safe_string_lower(response, 'message')
|
1283
|
+
isErrorMessage = (message is not None) and (message != 'ok')
|
1284
|
+
errorCode = self.safe_string(response, 'code')
|
1285
|
+
isErrorCode = (errorCode is not None) and (errorCode != '0')
|
1286
|
+
if isErrorCode or isErrorMessage:
|
1287
|
+
feedback = self.id + ' ' + body
|
1288
|
+
self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
|
1289
|
+
self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
|
1290
|
+
raise ExchangeError(feedback)
|
1291
|
+
return None
|
1292
|
+
|
972
1293
|
def handle_authentication_message(self, client: Client, message):
|
1294
|
+
#
|
1295
|
+
# success
|
973
1296
|
#
|
974
1297
|
# {
|
975
|
-
# "
|
976
|
-
# "
|
977
|
-
#
|
978
|
-
#
|
979
|
-
#
|
1298
|
+
# "id": 1,
|
1299
|
+
# "code": 0,
|
1300
|
+
# "message": "OK"
|
1301
|
+
# }
|
1302
|
+
#
|
1303
|
+
# fail
|
1304
|
+
#
|
1305
|
+
# {
|
1306
|
+
# "id": 1,
|
1307
|
+
# "code": 21002,
|
1308
|
+
# "message": ""
|
980
1309
|
# }
|
981
1310
|
#
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
1311
|
+
status = self.safe_string_lower(message, 'message')
|
1312
|
+
errorCode = self.safe_string(message, 'code')
|
1313
|
+
messageHash = 'authenticated'
|
1314
|
+
if (status == 'ok') or (errorCode == '0'):
|
1315
|
+
future = self.safe_value(client.futures, messageHash)
|
1316
|
+
future.resolve(True)
|
1317
|
+
else:
|
1318
|
+
error = AuthenticationError(self.json(message))
|
1319
|
+
client.reject(error, messageHash)
|
1320
|
+
if messageHash in client.subscriptions:
|
1321
|
+
del client.subscriptions[messageHash]
|
987
1322
|
|
988
1323
|
def handle_subscription_status(self, client: Client, message):
|
989
1324
|
id = self.safe_integer(message, 'id')
|
990
1325
|
subscription = self.safe_value(client.subscriptions, id)
|
991
1326
|
if subscription is not None:
|
992
1327
|
futureIndex = self.safe_string(subscription, 'future')
|
993
|
-
if futureIndex == 'ohlcv':
|
994
|
-
self.handle_ohlcv(client, message)
|
995
|
-
return
|
996
1328
|
future = self.safe_value(client.futures, futureIndex)
|
997
1329
|
if future is not None:
|
998
1330
|
future.resolve(True)
|
999
1331
|
del client.subscriptions[id]
|
1000
1332
|
|
1001
|
-
async def authenticate(self,
|
1002
|
-
type = None
|
1003
|
-
type, params = self.handle_market_type_and_params('authenticate', None, params)
|
1333
|
+
async def authenticate(self, type: str):
|
1004
1334
|
url = self.urls['api']['ws'][type]
|
1005
1335
|
client = self.client(url)
|
1006
1336
|
time = self.milliseconds()
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
requestId = self.request_id()
|
1013
|
-
subscribe = {
|
1014
|
-
'id': requestId,
|
1015
|
-
'future': 'authenticated:spot',
|
1016
|
-
}
|
1017
|
-
signData = 'access_id=' + self.apiKey + '&tonce=' + self.number_to_string(time) + '&secret_key=' + self.secret
|
1018
|
-
hash = self.hash(self.encode(signData), 'md5')
|
1019
|
-
request = {
|
1020
|
-
'method': 'server.sign',
|
1021
|
-
'params': [
|
1022
|
-
self.apiKey,
|
1023
|
-
hash.upper(),
|
1024
|
-
time,
|
1025
|
-
],
|
1026
|
-
'id': requestId,
|
1027
|
-
}
|
1028
|
-
future = self.watch(url, messageHash, request, requestId, subscribe)
|
1029
|
-
client.subscriptions[messageHash] = future
|
1030
|
-
return await future
|
1031
|
-
else:
|
1032
|
-
messageHash = 'authenticated:swap'
|
1033
|
-
future = self.safe_value(client.subscriptions, messageHash)
|
1034
|
-
if future is not None:
|
1035
|
-
return await future
|
1036
|
-
requestId = self.request_id()
|
1037
|
-
subscribe = {
|
1038
|
-
'id': requestId,
|
1039
|
-
'future': 'authenticated:swap',
|
1040
|
-
}
|
1041
|
-
signData = 'access_id=' + self.apiKey + '×tamp=' + self.number_to_string(time) + '&secret_key=' + self.secret
|
1042
|
-
hash = self.hash(self.encode(signData), 'sha256', 'hex')
|
1043
|
-
request = {
|
1044
|
-
'method': 'server.sign',
|
1045
|
-
'params': [
|
1046
|
-
self.apiKey,
|
1047
|
-
hash.lower(),
|
1048
|
-
time,
|
1049
|
-
],
|
1050
|
-
'id': requestId,
|
1051
|
-
}
|
1052
|
-
future = self.watch(url, messageHash, request, requestId, subscribe)
|
1053
|
-
client.subscriptions[messageHash] = future
|
1337
|
+
timestamp = str(time)
|
1338
|
+
messageHash = 'authenticated'
|
1339
|
+
future = client.future(messageHash)
|
1340
|
+
authenticated = self.safe_value(client.subscriptions, messageHash)
|
1341
|
+
if authenticated is not None:
|
1054
1342
|
return await future
|
1343
|
+
requestId = self.request_id()
|
1344
|
+
subscribe: dict = {
|
1345
|
+
'id': requestId,
|
1346
|
+
'future': messageHash,
|
1347
|
+
}
|
1348
|
+
hmac = self.hmac(self.encode(timestamp), self.encode(self.secret), hashlib.sha256, 'hex')
|
1349
|
+
request: dict = {
|
1350
|
+
'id': requestId,
|
1351
|
+
'method': 'server.sign',
|
1352
|
+
'params': {
|
1353
|
+
'access_id': self.apiKey,
|
1354
|
+
'signed_str': hmac.lower(),
|
1355
|
+
'timestamp': time,
|
1356
|
+
},
|
1357
|
+
}
|
1358
|
+
self.watch(url, messageHash, request, requestId, subscribe)
|
1359
|
+
client.subscriptions[messageHash] = True
|
1360
|
+
return await future
|