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/hyperliquid.py
CHANGED
@@ -5,10 +5,13 @@
|
|
5
5
|
|
6
6
|
from ccxt.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.hyperliquid import ImplicitAPI
|
8
|
-
|
8
|
+
import math
|
9
|
+
from ccxt.base.types import Balances, Currencies, Currency, Int, LedgerEntry, MarginModification, Market, Num, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, Transaction, TransferEntry
|
9
10
|
from typing import List
|
10
11
|
from ccxt.base.errors import ExchangeError
|
11
12
|
from ccxt.base.errors import ArgumentsRequired
|
13
|
+
from ccxt.base.errors import BadRequest
|
14
|
+
from ccxt.base.errors import InsufficientFunds
|
12
15
|
from ccxt.base.errors import InvalidOrder
|
13
16
|
from ccxt.base.errors import OrderNotFound
|
14
17
|
from ccxt.base.errors import NotSupported
|
@@ -28,11 +31,12 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
28
31
|
'countries': [],
|
29
32
|
'version': 'v1',
|
30
33
|
'rateLimit': 50, # 1200 requests per minute, 20 request per second
|
31
|
-
'certified':
|
34
|
+
'certified': True,
|
32
35
|
'pro': True,
|
36
|
+
'dex': True,
|
33
37
|
'has': {
|
34
38
|
'CORS': None,
|
35
|
-
'spot':
|
39
|
+
'spot': True,
|
36
40
|
'margin': False,
|
37
41
|
'swap': True,
|
38
42
|
'future': True,
|
@@ -41,8 +45,10 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
41
45
|
'borrowCrossMargin': False,
|
42
46
|
'borrowIsolatedMargin': False,
|
43
47
|
'cancelAllOrders': False,
|
48
|
+
'cancelAllOrdersAfter': True,
|
44
49
|
'cancelOrder': True,
|
45
50
|
'cancelOrders': True,
|
51
|
+
'cancelOrdersForSymbols': True,
|
46
52
|
'closeAllPositions': False,
|
47
53
|
'closePosition': False,
|
48
54
|
'createMarketBuyOrderWithCost': False,
|
@@ -50,31 +56,34 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
50
56
|
'createMarketSellOrderWithCost': False,
|
51
57
|
'createOrder': True,
|
52
58
|
'createOrders': True,
|
53
|
-
'createReduceOnlyOrder':
|
59
|
+
'createReduceOnlyOrder': True,
|
60
|
+
'createStopOrder': True,
|
61
|
+
'createTriggerOrder': True,
|
54
62
|
'editOrder': True,
|
55
63
|
'fetchAccounts': False,
|
56
64
|
'fetchBalance': True,
|
57
65
|
'fetchBorrowInterest': False,
|
58
66
|
'fetchBorrowRateHistories': False,
|
59
67
|
'fetchBorrowRateHistory': False,
|
60
|
-
'
|
68
|
+
'fetchCanceledAndClosedOrders': True,
|
69
|
+
'fetchCanceledOrders': True,
|
61
70
|
'fetchClosedOrders': True,
|
62
71
|
'fetchCrossBorrowRate': False,
|
63
72
|
'fetchCrossBorrowRates': False,
|
64
73
|
'fetchCurrencies': True,
|
65
74
|
'fetchDepositAddress': False,
|
66
75
|
'fetchDepositAddresses': False,
|
67
|
-
'fetchDeposits':
|
76
|
+
'fetchDeposits': True,
|
68
77
|
'fetchDepositWithdrawFee': 'emulated',
|
69
78
|
'fetchDepositWithdrawFees': False,
|
70
79
|
'fetchFundingHistory': False,
|
71
80
|
'fetchFundingRate': False,
|
72
81
|
'fetchFundingRateHistory': True,
|
73
|
-
'fetchFundingRates':
|
82
|
+
'fetchFundingRates': True,
|
74
83
|
'fetchIndexOHLCV': False,
|
75
84
|
'fetchIsolatedBorrowRate': False,
|
76
85
|
'fetchIsolatedBorrowRates': False,
|
77
|
-
'fetchLedger':
|
86
|
+
'fetchLedger': True,
|
78
87
|
'fetchLeverage': False,
|
79
88
|
'fetchLeverageTiers': False,
|
80
89
|
'fetchLiquidations': False,
|
@@ -85,31 +94,33 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
85
94
|
'fetchMyLiquidations': False,
|
86
95
|
'fetchMyTrades': True,
|
87
96
|
'fetchOHLCV': True,
|
88
|
-
'fetchOpenInterest':
|
97
|
+
'fetchOpenInterest': True,
|
89
98
|
'fetchOpenInterestHistory': False,
|
99
|
+
'fetchOpenInterests': True,
|
90
100
|
'fetchOpenOrders': True,
|
91
101
|
'fetchOrder': True,
|
92
102
|
'fetchOrderBook': True,
|
93
|
-
'fetchOrders':
|
103
|
+
'fetchOrders': True,
|
94
104
|
'fetchOrderTrades': False,
|
95
105
|
'fetchPosition': True,
|
96
106
|
'fetchPositionMode': False,
|
97
107
|
'fetchPositions': True,
|
98
108
|
'fetchPositionsRisk': False,
|
99
109
|
'fetchPremiumIndexOHLCV': False,
|
100
|
-
'fetchTicker':
|
101
|
-
'fetchTickers':
|
110
|
+
'fetchTicker': 'emulated',
|
111
|
+
'fetchTickers': True,
|
102
112
|
'fetchTime': False,
|
103
113
|
'fetchTrades': True,
|
104
|
-
'fetchTradingFee':
|
114
|
+
'fetchTradingFee': True,
|
105
115
|
'fetchTradingFees': False,
|
106
116
|
'fetchTransfer': False,
|
107
117
|
'fetchTransfers': False,
|
108
118
|
'fetchWithdrawal': False,
|
109
|
-
'fetchWithdrawals':
|
119
|
+
'fetchWithdrawals': True,
|
110
120
|
'reduceMargin': True,
|
111
121
|
'repayCrossMargin': False,
|
112
122
|
'repayIsolatedMargin': False,
|
123
|
+
'sandbox': True,
|
113
124
|
'setLeverage': True,
|
114
125
|
'setMarginMode': True,
|
115
126
|
'setPositionMode': False,
|
@@ -125,12 +136,12 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
125
136
|
'1h': '1h',
|
126
137
|
'2h': '2h',
|
127
138
|
'4h': '4h',
|
128
|
-
'
|
139
|
+
'8h': '8h',
|
129
140
|
'12h': '12h',
|
130
141
|
'1d': '1d',
|
131
142
|
'3d': '3d',
|
132
143
|
'1w': '1w',
|
133
|
-
'1M': '
|
144
|
+
'1M': '1M',
|
134
145
|
},
|
135
146
|
'hostname': 'hyperliquid.xyz',
|
136
147
|
'urls': {
|
@@ -151,7 +162,17 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
151
162
|
'api': {
|
152
163
|
'public': {
|
153
164
|
'post': {
|
154
|
-
'info':
|
165
|
+
'info': {
|
166
|
+
'cost': 20,
|
167
|
+
'byType': {
|
168
|
+
'l2Book': 2,
|
169
|
+
'allMids': 2,
|
170
|
+
'clearinghouseState': 2,
|
171
|
+
'orderStatus': 2,
|
172
|
+
'spotClearinghouseState': 2,
|
173
|
+
'exchangeStatus': 2,
|
174
|
+
},
|
175
|
+
},
|
155
176
|
},
|
156
177
|
},
|
157
178
|
'private': {
|
@@ -165,6 +186,10 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
165
186
|
'taker': self.parse_number('0.00035'),
|
166
187
|
'maker': self.parse_number('0.0001'),
|
167
188
|
},
|
189
|
+
'spot': {
|
190
|
+
'taker': self.parse_number('0.00035'),
|
191
|
+
'maker': self.parse_number('0.0001'),
|
192
|
+
},
|
168
193
|
},
|
169
194
|
'requiredCredentials': {
|
170
195
|
'apiKey': False,
|
@@ -186,30 +211,131 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
186
211
|
'No liquidity available for market order.': InvalidOrder,
|
187
212
|
'Order was never placed, already canceled, or filled.': OrderNotFound,
|
188
213
|
'User or API Wallet ': InvalidOrder,
|
214
|
+
'Order has invalid size': InvalidOrder,
|
215
|
+
'Order price cannot be more than 80% away from the reference price': InvalidOrder,
|
216
|
+
'Order has zero size.': InvalidOrder,
|
217
|
+
'Insufficient spot balance asset': InsufficientFunds,
|
189
218
|
},
|
190
219
|
},
|
191
220
|
'precisionMode': TICK_SIZE,
|
192
221
|
'commonCurrencies': {
|
193
222
|
},
|
194
223
|
'options': {
|
224
|
+
'defaultType': 'swap',
|
195
225
|
'sandboxMode': False,
|
196
226
|
'defaultSlippage': 0.05,
|
197
227
|
'zeroAddress': '0x0000000000000000000000000000000000000000',
|
198
228
|
},
|
229
|
+
'features': {
|
230
|
+
'default': {
|
231
|
+
'sandbox': True,
|
232
|
+
'createOrder': {
|
233
|
+
'marginMode': False,
|
234
|
+
'triggerPrice': False,
|
235
|
+
'triggerPriceType': None,
|
236
|
+
'triggerDirection': False,
|
237
|
+
'stopLossPrice': False,
|
238
|
+
'takeProfitPrice': False,
|
239
|
+
'attachedStopLossTakeProfit': None,
|
240
|
+
'timeInForce': {
|
241
|
+
'IOC': True,
|
242
|
+
'FOK': False,
|
243
|
+
'PO': True,
|
244
|
+
'GTD': False,
|
245
|
+
},
|
246
|
+
'hedged': False,
|
247
|
+
'trailing': False,
|
248
|
+
'leverage': False,
|
249
|
+
'marketBuyByCost': False,
|
250
|
+
'marketBuyRequiresPrice': False,
|
251
|
+
'selfTradePrevention': False,
|
252
|
+
'iceberg': False,
|
253
|
+
},
|
254
|
+
'createOrders': {
|
255
|
+
'max': 1000,
|
256
|
+
},
|
257
|
+
'fetchMyTrades': {
|
258
|
+
'marginMode': False,
|
259
|
+
'limit': 2000,
|
260
|
+
'daysBack': None,
|
261
|
+
'untilDays': None,
|
262
|
+
},
|
263
|
+
'fetchOrder': {
|
264
|
+
'marginMode': False,
|
265
|
+
'trigger': False,
|
266
|
+
'trailing': False,
|
267
|
+
},
|
268
|
+
'fetchOpenOrders': {
|
269
|
+
'marginMode': False,
|
270
|
+
'limit': 2000,
|
271
|
+
'trigger': False,
|
272
|
+
'trailing': False,
|
273
|
+
},
|
274
|
+
'fetchOrders': {
|
275
|
+
'marginMode': False,
|
276
|
+
'limit': 2000,
|
277
|
+
'daysBack': None,
|
278
|
+
'untilDays': None,
|
279
|
+
'trigger': False,
|
280
|
+
'trailing': False,
|
281
|
+
},
|
282
|
+
'fetchClosedOrders': {
|
283
|
+
'marginMode': False,
|
284
|
+
'limit': 2000,
|
285
|
+
'daysBack': None,
|
286
|
+
'daysBackCanceled': None,
|
287
|
+
'untilDays': None,
|
288
|
+
'trigger': False,
|
289
|
+
'trailing': False,
|
290
|
+
},
|
291
|
+
'fetchOHLCV': {
|
292
|
+
'limit': 5000,
|
293
|
+
},
|
294
|
+
},
|
295
|
+
'spot': {
|
296
|
+
'extends': 'default',
|
297
|
+
},
|
298
|
+
'forPerps': {
|
299
|
+
'extends': 'default',
|
300
|
+
'createOrder': {
|
301
|
+
'stopLossPrice': True,
|
302
|
+
'takeProfitPrice': True,
|
303
|
+
'attachedStopLossTakeProfit': None, # todo, in two orders
|
304
|
+
},
|
305
|
+
},
|
306
|
+
'swap': {
|
307
|
+
'linear': {
|
308
|
+
'extends': 'forPerps',
|
309
|
+
},
|
310
|
+
'inverse': {
|
311
|
+
'extends': 'forPerps',
|
312
|
+
},
|
313
|
+
},
|
314
|
+
'future': {
|
315
|
+
'linear': {
|
316
|
+
'extends': 'forPerps',
|
317
|
+
},
|
318
|
+
'inverse': {
|
319
|
+
'extends': 'forPerps',
|
320
|
+
},
|
321
|
+
},
|
322
|
+
},
|
199
323
|
})
|
200
324
|
|
201
325
|
def set_sandbox_mode(self, enabled):
|
202
326
|
super(hyperliquid, self).set_sandbox_mode(enabled)
|
203
327
|
self.options['sandboxMode'] = enabled
|
204
328
|
|
205
|
-
def fetch_currencies(self, params={}):
|
329
|
+
def fetch_currencies(self, params={}) -> Currencies:
|
206
330
|
"""
|
207
331
|
fetches all available currencies on an exchange
|
208
|
-
|
332
|
+
|
333
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/perpetuals#retrieve-perpetuals-metadata
|
334
|
+
|
209
335
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
210
336
|
:returns dict: an associative dictionary of currencies
|
211
337
|
"""
|
212
|
-
request = {
|
338
|
+
request: dict = {
|
213
339
|
'type': 'meta',
|
214
340
|
}
|
215
341
|
response = self.publicPostInfo(self.extend(request, params))
|
@@ -228,7 +354,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
228
354
|
# ]
|
229
355
|
#
|
230
356
|
meta = self.safe_list(response, 'universe', [])
|
231
|
-
result = {}
|
357
|
+
result: dict = {}
|
232
358
|
for i in range(0, len(meta)):
|
233
359
|
data = self.safe_dict(meta, i, {})
|
234
360
|
id = i
|
@@ -245,19 +371,48 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
245
371
|
'withdraw': None,
|
246
372
|
'networks': None,
|
247
373
|
'fee': None,
|
248
|
-
|
249
|
-
|
374
|
+
'limits': {
|
375
|
+
'amount': {
|
376
|
+
'min': None,
|
377
|
+
'max': None,
|
378
|
+
},
|
379
|
+
'withdraw': {
|
380
|
+
'min': None,
|
381
|
+
'max': None,
|
382
|
+
},
|
383
|
+
},
|
250
384
|
}
|
251
385
|
return result
|
252
386
|
|
253
|
-
def fetch_markets(self, params={}):
|
387
|
+
def fetch_markets(self, params={}) -> List[Market]:
|
254
388
|
"""
|
255
389
|
retrieves data on all markets for hyperliquid
|
256
|
-
|
390
|
+
|
391
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/perpetuals#retrieve-perpetuals-asset-contexts-includes-mark-price-current-funding-open-interest-etc
|
392
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/spot#retrieve-spot-asset-contexts
|
393
|
+
|
394
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
395
|
+
:returns dict[]: an array of objects representing market data
|
396
|
+
"""
|
397
|
+
rawPromises = [
|
398
|
+
self.fetch_swap_markets(params),
|
399
|
+
self.fetch_spot_markets(params),
|
400
|
+
]
|
401
|
+
promises = rawPromises
|
402
|
+
swapMarkets = promises[0]
|
403
|
+
spotMarkets = promises[1]
|
404
|
+
return self.array_concat(swapMarkets, spotMarkets)
|
405
|
+
|
406
|
+
def fetch_swap_markets(self, params={}) -> List[Market]:
|
407
|
+
"""
|
408
|
+
retrieves data on all swap markets for hyperliquid
|
409
|
+
|
410
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/perpetuals#retrieve-perpetuals-asset-contexts-includes-mark-price-current-funding-open-interest-etc
|
411
|
+
|
257
412
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
258
413
|
:returns dict[]: an array of objects representing market data
|
259
414
|
"""
|
260
|
-
request = {
|
415
|
+
request: dict = {
|
261
416
|
'type': 'metaAndAssetCtxs',
|
262
417
|
}
|
263
418
|
response = self.publicPostInfo(self.extend(request, params))
|
@@ -291,20 +446,213 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
291
446
|
# ]
|
292
447
|
# ]
|
293
448
|
#
|
449
|
+
#
|
294
450
|
meta = self.safe_dict(response, 0, {})
|
295
|
-
|
296
|
-
assetCtxs = self.
|
451
|
+
universe = self.safe_list(meta, 'universe', [])
|
452
|
+
assetCtxs = self.safe_list(response, 1, [])
|
297
453
|
result = []
|
298
|
-
for i in range(0, len(
|
454
|
+
for i in range(0, len(universe)):
|
299
455
|
data = self.extend(
|
300
|
-
self.safe_dict(
|
456
|
+
self.safe_dict(universe, i, {}),
|
301
457
|
self.safe_dict(assetCtxs, i, {})
|
302
458
|
)
|
303
459
|
data['baseId'] = i
|
304
460
|
result.append(data)
|
305
461
|
return self.parse_markets(result)
|
306
462
|
|
307
|
-
def
|
463
|
+
def calculate_price_precision(self, price: float, amountPrecision: float, maxDecimals: float):
|
464
|
+
"""
|
465
|
+
Helper function to calculate the Hyperliquid DECIMAL_PLACES price precision
|
466
|
+
:param float price: the price to use in the calculation
|
467
|
+
:param int amountPrecision: the amountPrecision to use in the calculation
|
468
|
+
:param int maxDecimals: the maxDecimals to use in the calculation
|
469
|
+
:returns int: The calculated price precision
|
470
|
+
"""
|
471
|
+
pricePrecision = 0
|
472
|
+
priceStr = self.number_to_string(price)
|
473
|
+
if priceStr is None:
|
474
|
+
return 0
|
475
|
+
priceSplitted = priceStr.split('.')
|
476
|
+
if Precise.string_eq(priceStr, '0'):
|
477
|
+
# Significant digits is always hasattr(self, 5) case
|
478
|
+
significantDigits = 5
|
479
|
+
# Integer digits is always hasattr(self, 0) case(0 doesn't count)
|
480
|
+
integerDigits = 0
|
481
|
+
# Calculate the price precision
|
482
|
+
pricePrecision = min(maxDecimals - amountPrecision, significantDigits - integerDigits)
|
483
|
+
elif Precise.string_gt(priceStr, '0') and Precise.string_lt(priceStr, '1'):
|
484
|
+
# Significant digits, always hasattr(self, 5) case
|
485
|
+
significantDigits = 5
|
486
|
+
# Get the part after the decimal separator
|
487
|
+
decimalPart = self.safe_string(priceSplitted, 1, '')
|
488
|
+
# Count the number of leading zeros in the decimal part
|
489
|
+
leadingZeros = 0
|
490
|
+
while((leadingZeros <= len(decimalPart)) and (decimalPart[leadingZeros] == '0')):
|
491
|
+
leadingZeros = leadingZeros + 1
|
492
|
+
# Calculate price precision based on leading zeros and significant digits
|
493
|
+
pricePrecision = leadingZeros + significantDigits
|
494
|
+
# Calculate the price precision based on maxDecimals - szDecimals and the calculated price precision from the previous step
|
495
|
+
pricePrecision = min(maxDecimals - amountPrecision, pricePrecision)
|
496
|
+
else:
|
497
|
+
# Count the numbers before the decimal separator
|
498
|
+
integerPart = self.safe_string(priceSplitted, 0, '')
|
499
|
+
# Get significant digits, take the max() of 5 and the integer digits count
|
500
|
+
significantDigits = max(5, len(integerPart))
|
501
|
+
# Calculate price precision based on maxDecimals - szDecimals and significantDigits - len(integerPart)
|
502
|
+
pricePrecision = min(maxDecimals - amountPrecision, significantDigits - len(integerPart))
|
503
|
+
return self.parse_to_int(pricePrecision)
|
504
|
+
|
505
|
+
def fetch_spot_markets(self, params={}) -> List[Market]:
|
506
|
+
"""
|
507
|
+
retrieves data on all spot markets for hyperliquid
|
508
|
+
|
509
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/spot#retrieve-spot-asset-contexts
|
510
|
+
|
511
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
512
|
+
:returns dict[]: an array of objects representing market data
|
513
|
+
"""
|
514
|
+
request: dict = {
|
515
|
+
'type': 'spotMetaAndAssetCtxs',
|
516
|
+
}
|
517
|
+
response = self.publicPostInfo(self.extend(request, params))
|
518
|
+
#
|
519
|
+
# [
|
520
|
+
# {
|
521
|
+
# "tokens": [
|
522
|
+
# {
|
523
|
+
# "name": "USDC",
|
524
|
+
# "szDecimals": 8,
|
525
|
+
# "weiDecimals" 8,
|
526
|
+
# "index": 0,
|
527
|
+
# "tokenId": "0x6d1e7cde53ba9467b783cb7c530ce054",
|
528
|
+
# "isCanonical": True,
|
529
|
+
# "evmContract":null,
|
530
|
+
# "fullName":null
|
531
|
+
# },
|
532
|
+
# {
|
533
|
+
# "name": "PURR",
|
534
|
+
# "szDecimals": 0,
|
535
|
+
# "weiDecimals": 5,
|
536
|
+
# "index": 1,
|
537
|
+
# "tokenId": "0xc1fb593aeffbeb02f85e0308e9956a90",
|
538
|
+
# "isCanonical": True,
|
539
|
+
# "evmContract":null,
|
540
|
+
# "fullName":null
|
541
|
+
# }
|
542
|
+
# ],
|
543
|
+
# "universe": [
|
544
|
+
# {
|
545
|
+
# "name": "PURR/USDC",
|
546
|
+
# "tokens": [1, 0],
|
547
|
+
# "index": 0,
|
548
|
+
# "isCanonical": True
|
549
|
+
# }
|
550
|
+
# ]
|
551
|
+
# },
|
552
|
+
# [
|
553
|
+
# {
|
554
|
+
# "dayNtlVlm":"8906.0",
|
555
|
+
# "markPx":"0.14",
|
556
|
+
# "midPx":"0.209265",
|
557
|
+
# "prevDayPx":"0.20432"
|
558
|
+
# }
|
559
|
+
# ]
|
560
|
+
# ]
|
561
|
+
#
|
562
|
+
first = self.safe_dict(response, 0, {})
|
563
|
+
second = self.safe_list(response, 1, [])
|
564
|
+
meta = self.safe_list(first, 'universe', [])
|
565
|
+
tokens = self.safe_list(first, 'tokens', [])
|
566
|
+
markets = []
|
567
|
+
for i in range(0, len(meta)):
|
568
|
+
market = self.safe_dict(meta, i, {})
|
569
|
+
index = self.safe_integer(market, 'index')
|
570
|
+
extraData = self.safe_dict(second, index, {})
|
571
|
+
marketName = self.safe_string(market, 'name')
|
572
|
+
# if marketName.find('/') < 0:
|
573
|
+
# # there are some weird spot markets in testnet, eg @2
|
574
|
+
# continue
|
575
|
+
# }
|
576
|
+
# marketParts = marketName.split('/')
|
577
|
+
# baseName = self.safe_string(marketParts, 0)
|
578
|
+
# quoteId = self.safe_string(marketParts, 1)
|
579
|
+
fees = self.safe_dict(self.fees, 'spot', {})
|
580
|
+
taker = self.safe_number(fees, 'taker')
|
581
|
+
maker = self.safe_number(fees, 'maker')
|
582
|
+
tokensPos = self.safe_list(market, 'tokens', [])
|
583
|
+
baseTokenPos = self.safe_integer(tokensPos, 0)
|
584
|
+
quoteTokenPos = self.safe_integer(tokensPos, 1)
|
585
|
+
baseTokenInfo = self.safe_dict(tokens, baseTokenPos, {})
|
586
|
+
quoteTokenInfo = self.safe_dict(tokens, quoteTokenPos, {})
|
587
|
+
baseName = self.safe_string(baseTokenInfo, 'name')
|
588
|
+
quoteId = self.safe_string(quoteTokenInfo, 'name')
|
589
|
+
base = self.safe_currency_code(baseName)
|
590
|
+
quote = self.safe_currency_code(quoteId)
|
591
|
+
symbol = base + '/' + quote
|
592
|
+
innerBaseTokenInfo = self.safe_dict(baseTokenInfo, 'spec', baseTokenInfo)
|
593
|
+
# innerQuoteTokenInfo = self.safe_dict(quoteTokenInfo, 'spec', quoteTokenInfo)
|
594
|
+
amountPrecisionStr = self.safe_string(innerBaseTokenInfo, 'szDecimals')
|
595
|
+
amountPrecision = int(amountPrecisionStr)
|
596
|
+
price = self.safe_number(extraData, 'midPx')
|
597
|
+
pricePrecision = self.calculate_price_precision(price, amountPrecision, 8)
|
598
|
+
pricePrecisionStr = self.number_to_string(pricePrecision)
|
599
|
+
# quotePrecision = self.parse_number(self.parse_precision(self.safe_string(innerQuoteTokenInfo, 'szDecimals')))
|
600
|
+
baseId = self.number_to_string(index + 10000)
|
601
|
+
markets.append(self.safe_market_structure({
|
602
|
+
'id': marketName,
|
603
|
+
'symbol': symbol,
|
604
|
+
'base': base,
|
605
|
+
'quote': quote,
|
606
|
+
'settle': None,
|
607
|
+
'baseId': baseId,
|
608
|
+
'quoteId': quoteId,
|
609
|
+
'settleId': None,
|
610
|
+
'type': 'spot',
|
611
|
+
'spot': True,
|
612
|
+
'subType': None,
|
613
|
+
'margin': None,
|
614
|
+
'swap': False,
|
615
|
+
'future': False,
|
616
|
+
'option': False,
|
617
|
+
'active': True,
|
618
|
+
'contract': False,
|
619
|
+
'linear': None,
|
620
|
+
'inverse': None,
|
621
|
+
'taker': taker,
|
622
|
+
'maker': maker,
|
623
|
+
'contractSize': None,
|
624
|
+
'expiry': None,
|
625
|
+
'expiryDatetime': None,
|
626
|
+
'strike': None,
|
627
|
+
'optionType': None,
|
628
|
+
'precision': {
|
629
|
+
'amount': self.parse_number(self.parse_precision(amountPrecisionStr)),
|
630
|
+
'price': self.parse_number(self.parse_precision(pricePrecisionStr)),
|
631
|
+
},
|
632
|
+
'limits': {
|
633
|
+
'leverage': {
|
634
|
+
'min': None,
|
635
|
+
'max': None,
|
636
|
+
},
|
637
|
+
'amount': {
|
638
|
+
'min': None,
|
639
|
+
'max': None,
|
640
|
+
},
|
641
|
+
'price': {
|
642
|
+
'min': None,
|
643
|
+
'max': None,
|
644
|
+
},
|
645
|
+
'cost': {
|
646
|
+
'min': self.parse_number('10'),
|
647
|
+
'max': None,
|
648
|
+
},
|
649
|
+
},
|
650
|
+
'created': None,
|
651
|
+
'info': self.extend(extraData, market),
|
652
|
+
}))
|
653
|
+
return markets
|
654
|
+
|
655
|
+
def parse_market(self, market: dict) -> Market:
|
308
656
|
#
|
309
657
|
# {
|
310
658
|
# "maxLeverage": "50",
|
@@ -340,7 +688,16 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
340
688
|
fees = self.safe_dict(self.fees, 'swap', {})
|
341
689
|
taker = self.safe_number(fees, 'taker')
|
342
690
|
maker = self.safe_number(fees, 'maker')
|
343
|
-
|
691
|
+
amountPrecisionStr = self.safe_string(market, 'szDecimals')
|
692
|
+
amountPrecision = int(amountPrecisionStr)
|
693
|
+
price = self.safe_number(market, 'markPx', 0)
|
694
|
+
pricePrecision = self.calculate_price_precision(price, amountPrecision, 6)
|
695
|
+
pricePrecisionStr = self.number_to_string(pricePrecision)
|
696
|
+
isDelisted = self.safe_bool(market, 'isDelisted')
|
697
|
+
active = True
|
698
|
+
if isDelisted is not None:
|
699
|
+
active = not isDelisted
|
700
|
+
return self.safe_market_structure({
|
344
701
|
'id': baseId,
|
345
702
|
'symbol': symbol,
|
346
703
|
'base': base,
|
@@ -355,7 +712,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
355
712
|
'swap': swap,
|
356
713
|
'future': False,
|
357
714
|
'option': False,
|
358
|
-
'active':
|
715
|
+
'active': active,
|
359
716
|
'contract': contract,
|
360
717
|
'linear': True,
|
361
718
|
'inverse': False,
|
@@ -367,13 +724,13 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
367
724
|
'strike': None,
|
368
725
|
'optionType': None,
|
369
726
|
'precision': {
|
370
|
-
'amount': self.parse_number(self.parse_precision(
|
371
|
-
'price':
|
727
|
+
'amount': self.parse_number(self.parse_precision(amountPrecisionStr)),
|
728
|
+
'price': self.parse_number(self.parse_precision(pricePrecisionStr)),
|
372
729
|
},
|
373
730
|
'limits': {
|
374
731
|
'leverage': {
|
375
732
|
'min': None,
|
376
|
-
'max':
|
733
|
+
'max': self.safe_integer(market, 'maxLeverage'),
|
377
734
|
},
|
378
735
|
'amount': {
|
379
736
|
'min': None,
|
@@ -384,26 +741,34 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
384
741
|
'max': None,
|
385
742
|
},
|
386
743
|
'cost': {
|
387
|
-
'min':
|
744
|
+
'min': self.parse_number('10'),
|
388
745
|
'max': None,
|
389
746
|
},
|
390
747
|
},
|
391
748
|
'created': None,
|
392
749
|
'info': market,
|
393
|
-
}
|
750
|
+
})
|
394
751
|
|
395
752
|
def fetch_balance(self, params={}) -> Balances:
|
396
753
|
"""
|
397
754
|
query for balance and get the amount of funds available for trading or funds locked in orders
|
398
|
-
|
755
|
+
|
756
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/spot#retrieve-a-users-token-balances
|
757
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/perpetuals#retrieve-users-perpetuals-account-summary
|
758
|
+
|
399
759
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
400
760
|
:param str [params.user]: user address, will default to self.walletAddress if not provided
|
761
|
+
:param str [params.type]: wallet type, ['spot', 'swap'], defaults to swap
|
401
762
|
:returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
|
402
763
|
"""
|
403
764
|
userAddress = None
|
404
765
|
userAddress, params = self.handle_public_address('fetchBalance', params)
|
405
|
-
|
406
|
-
|
766
|
+
type = None
|
767
|
+
type, params = self.handle_market_type_and_params('fetchBalance', None, params)
|
768
|
+
isSpot = (type == 'spot')
|
769
|
+
reqType = 'spotClearinghouseState' if (isSpot) else 'clearinghouseState'
|
770
|
+
request: dict = {
|
771
|
+
'type': reqType,
|
407
772
|
'user': userAddress,
|
408
773
|
}
|
409
774
|
response = self.publicPostInfo(self.extend(request, params))
|
@@ -426,13 +791,41 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
426
791
|
# "time": "1704261007014",
|
427
792
|
# "withdrawable": "100.0"
|
428
793
|
# }
|
794
|
+
# spot
|
795
|
+
#
|
796
|
+
# {
|
797
|
+
# "balances":[
|
798
|
+
# {
|
799
|
+
# "coin":"USDC",
|
800
|
+
# "hold":"0.0",
|
801
|
+
# "total":"1481.844"
|
802
|
+
# },
|
803
|
+
# {
|
804
|
+
# "coin":"PURR",
|
805
|
+
# "hold":"0.0",
|
806
|
+
# "total":"999.65004"
|
807
|
+
# }
|
808
|
+
# }
|
429
809
|
#
|
810
|
+
balances = self.safe_list(response, 'balances')
|
811
|
+
if balances is not None:
|
812
|
+
spotBalances: dict = {'info': response}
|
813
|
+
for i in range(0, len(balances)):
|
814
|
+
balance = balances[i]
|
815
|
+
code = self.safe_currency_code(self.safe_string(balance, 'coin'))
|
816
|
+
account = self.account()
|
817
|
+
total = self.safe_string(balance, 'total')
|
818
|
+
used = self.safe_string(balance, 'hold')
|
819
|
+
account['total'] = total
|
820
|
+
account['used'] = used
|
821
|
+
spotBalances[code] = account
|
822
|
+
return self.safe_balance(spotBalances)
|
430
823
|
data = self.safe_dict(response, 'marginSummary', {})
|
431
|
-
result = {
|
824
|
+
result: dict = {
|
432
825
|
'info': response,
|
433
826
|
'USDC': {
|
434
|
-
'total': self.
|
435
|
-
'
|
827
|
+
'total': self.safe_number(data, 'accountValue'),
|
828
|
+
'free': self.safe_number(response, 'withdrawable'),
|
436
829
|
},
|
437
830
|
}
|
438
831
|
timestamp = self.safe_integer(response, 'time')
|
@@ -443,7 +836,9 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
443
836
|
def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
444
837
|
"""
|
445
838
|
fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
446
|
-
|
839
|
+
|
840
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#l2-book-snapshot
|
841
|
+
|
447
842
|
:param str symbol: unified symbol of the market to fetch the order book for
|
448
843
|
:param int [limit]: the maximum amount of order book entries to return
|
449
844
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -451,9 +846,9 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
451
846
|
"""
|
452
847
|
self.load_markets()
|
453
848
|
market = self.market(symbol)
|
454
|
-
request = {
|
849
|
+
request: dict = {
|
455
850
|
'type': 'l2Book',
|
456
|
-
'coin': market['base'],
|
851
|
+
'coin': market['base'] if market['swap'] else market['id'],
|
457
852
|
}
|
458
853
|
response = self.publicPostInfo(self.extend(request, params))
|
459
854
|
#
|
@@ -479,17 +874,188 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
479
874
|
# }
|
480
875
|
#
|
481
876
|
data = self.safe_list(response, 'levels', [])
|
482
|
-
result = {
|
877
|
+
result: dict = {
|
483
878
|
'bids': self.safe_list(data, 0, []),
|
484
879
|
'asks': self.safe_list(data, 1, []),
|
485
880
|
}
|
486
881
|
timestamp = self.safe_integer(response, 'time')
|
487
882
|
return self.parse_order_book(result, market['symbol'], timestamp, 'bids', 'asks', 'px', 'sz')
|
488
883
|
|
884
|
+
def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
885
|
+
"""
|
886
|
+
fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
|
887
|
+
|
888
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/perpetuals#retrieve-perpetuals-asset-contexts-includes-mark-price-current-funding-open-interest-etc
|
889
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/spot#retrieve-spot-asset-contexts
|
890
|
+
|
891
|
+
:param str[] [symbols]: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
|
892
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
893
|
+
:param str [params.type]: 'spot' or 'swap', by default fetches both
|
894
|
+
:returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
|
895
|
+
"""
|
896
|
+
self.load_markets()
|
897
|
+
symbols = self.market_symbols(symbols)
|
898
|
+
# at self stage, to get tickers data, we use fetchMarkets endpoints
|
899
|
+
response = []
|
900
|
+
type = self.safe_string(params, 'type')
|
901
|
+
params = self.omit(params, 'type')
|
902
|
+
if type == 'spot':
|
903
|
+
response = self.fetch_spot_markets(params)
|
904
|
+
elif type == 'swap':
|
905
|
+
response = self.fetch_swap_markets(params)
|
906
|
+
else:
|
907
|
+
response = self.fetch_markets(params)
|
908
|
+
# same response "fetchMarkets"
|
909
|
+
result: dict = {}
|
910
|
+
for i in range(0, len(response)):
|
911
|
+
market = response[i]
|
912
|
+
info = market['info']
|
913
|
+
ticker = self.parse_ticker(info, market)
|
914
|
+
symbol = self.safe_string(ticker, 'symbol')
|
915
|
+
result[symbol] = ticker
|
916
|
+
return self.filter_by_array_tickers(result, 'symbol', symbols)
|
917
|
+
|
918
|
+
def fetch_funding_rates(self, symbols: Strings = None, params={}) -> FundingRates:
|
919
|
+
"""
|
920
|
+
retrieves data on all swap markets for hyperliquid
|
921
|
+
|
922
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/perpetuals#retrieve-perpetuals-asset-contexts-includes-mark-price-current-funding-open-interest-etc
|
923
|
+
|
924
|
+
:param str[] [symbols]: list of unified market symbols
|
925
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
926
|
+
:returns dict[]: an array of objects representing market data
|
927
|
+
"""
|
928
|
+
request: dict = {
|
929
|
+
'type': 'metaAndAssetCtxs',
|
930
|
+
}
|
931
|
+
response = self.publicPostInfo(self.extend(request, params))
|
932
|
+
#
|
933
|
+
# [
|
934
|
+
# {
|
935
|
+
# "universe": [
|
936
|
+
# {
|
937
|
+
# "maxLeverage": 50,
|
938
|
+
# "name": "SOL",
|
939
|
+
# "onlyIsolated": False,
|
940
|
+
# "szDecimals": 2
|
941
|
+
# }
|
942
|
+
# ]
|
943
|
+
# },
|
944
|
+
# [
|
945
|
+
# {
|
946
|
+
# "dayNtlVlm": "9450588.2273",
|
947
|
+
# "funding": "0.0000198",
|
948
|
+
# "impactPxs": [
|
949
|
+
# "108.04",
|
950
|
+
# "108.06"
|
951
|
+
# ],
|
952
|
+
# "markPx": "108.04",
|
953
|
+
# "midPx": "108.05",
|
954
|
+
# "openInterest": "10764.48",
|
955
|
+
# "oraclePx": "107.99",
|
956
|
+
# "premium": "0.00055561",
|
957
|
+
# "prevDayPx": "111.81"
|
958
|
+
# }
|
959
|
+
# ]
|
960
|
+
# ]
|
961
|
+
#
|
962
|
+
#
|
963
|
+
meta = self.safe_dict(response, 0, {})
|
964
|
+
universe = self.safe_list(meta, 'universe', [])
|
965
|
+
assetCtxs = self.safe_list(response, 1, [])
|
966
|
+
result = []
|
967
|
+
for i in range(0, len(universe)):
|
968
|
+
data = self.extend(
|
969
|
+
self.safe_dict(universe, i, {}),
|
970
|
+
self.safe_dict(assetCtxs, i, {})
|
971
|
+
)
|
972
|
+
result.append(data)
|
973
|
+
return self.parse_funding_rates(result, symbols)
|
974
|
+
|
975
|
+
def parse_funding_rate(self, info, market: Market = None) -> FundingRate:
|
976
|
+
#
|
977
|
+
# {
|
978
|
+
# "maxLeverage": "50",
|
979
|
+
# "name": "ETH",
|
980
|
+
# "onlyIsolated": False,
|
981
|
+
# "szDecimals": "4",
|
982
|
+
# "dayNtlVlm": "1709813.11535",
|
983
|
+
# "funding": "0.00004807",
|
984
|
+
# "impactPxs": [
|
985
|
+
# "2369.3",
|
986
|
+
# "2369.6"
|
987
|
+
# ],
|
988
|
+
# "markPx": "2369.6",
|
989
|
+
# "midPx": "2369.45",
|
990
|
+
# "openInterest": "1815.4712",
|
991
|
+
# "oraclePx": "2367.3",
|
992
|
+
# "premium": "0.00090821",
|
993
|
+
# "prevDayPx": "2381.5"
|
994
|
+
# }
|
995
|
+
#
|
996
|
+
base = self.safe_string(info, 'name')
|
997
|
+
marketId = self.coin_to_market_id(base)
|
998
|
+
symbol = self.safe_symbol(marketId, market)
|
999
|
+
funding = self.safe_number(info, 'funding')
|
1000
|
+
markPx = self.safe_number(info, 'markPx')
|
1001
|
+
oraclePx = self.safe_number(info, 'oraclePx')
|
1002
|
+
fundingTimestamp = (int(math.floor(self.milliseconds()) / 60 / 60 / 1000) + 1) * 60 * 60 * 1000
|
1003
|
+
return {
|
1004
|
+
'info': info,
|
1005
|
+
'symbol': symbol,
|
1006
|
+
'markPrice': markPx,
|
1007
|
+
'indexPrice': oraclePx,
|
1008
|
+
'interestRate': None,
|
1009
|
+
'estimatedSettlePrice': None,
|
1010
|
+
'timestamp': None,
|
1011
|
+
'datetime': None,
|
1012
|
+
'fundingRate': funding,
|
1013
|
+
'fundingTimestamp': fundingTimestamp,
|
1014
|
+
'fundingDatetime': self.iso8601(fundingTimestamp),
|
1015
|
+
'nextFundingRate': None,
|
1016
|
+
'nextFundingTimestamp': None,
|
1017
|
+
'nextFundingDatetime': None,
|
1018
|
+
'previousFundingRate': None,
|
1019
|
+
'previousFundingTimestamp': None,
|
1020
|
+
'previousFundingDatetime': None,
|
1021
|
+
'interval': '1h',
|
1022
|
+
}
|
1023
|
+
|
1024
|
+
def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
|
1025
|
+
#
|
1026
|
+
# {
|
1027
|
+
# "prevDayPx": "3400.5",
|
1028
|
+
# "dayNtlVlm": "511297257.47936022",
|
1029
|
+
# "markPx": "3464.7",
|
1030
|
+
# "midPx": "3465.05",
|
1031
|
+
# "oraclePx": "3460.1", # only in swap
|
1032
|
+
# "openInterest": "64638.1108", # only in swap
|
1033
|
+
# "premium": "0.00141614", # only in swap
|
1034
|
+
# "funding": "0.00008727", # only in swap
|
1035
|
+
# "impactPxs": ["3465.0", "3465.1"], # only in swap
|
1036
|
+
# "coin": "PURR", # only in spot
|
1037
|
+
# "circulatingSupply": "998949190.03400207", # only in spot
|
1038
|
+
# },
|
1039
|
+
#
|
1040
|
+
bidAsk = self.safe_list(ticker, 'impactPxs')
|
1041
|
+
return self.safe_ticker({
|
1042
|
+
'symbol': market['symbol'],
|
1043
|
+
'timestamp': None,
|
1044
|
+
'datetime': None,
|
1045
|
+
'previousClose': self.safe_number(ticker, 'prevDayPx'),
|
1046
|
+
'close': self.safe_number(ticker, 'midPx'),
|
1047
|
+
'bid': self.safe_number(bidAsk, 0),
|
1048
|
+
'ask': self.safe_number(bidAsk, 1),
|
1049
|
+
'quoteVolume': self.safe_number(ticker, 'dayNtlVlm'),
|
1050
|
+
'info': ticker,
|
1051
|
+
}, market)
|
1052
|
+
|
489
1053
|
def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
490
1054
|
"""
|
491
1055
|
fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
492
|
-
|
1056
|
+
|
1057
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#candle-snapshot
|
1058
|
+
|
493
1059
|
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
494
1060
|
:param str timeframe: the length of time each candle represents, support '1m', '15m', '1h', '1d'
|
495
1061
|
:param int [since]: timestamp in ms of the earliest candle to fetch
|
@@ -501,16 +1067,22 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
501
1067
|
self.load_markets()
|
502
1068
|
market = self.market(symbol)
|
503
1069
|
until = self.safe_integer(params, 'until', self.milliseconds())
|
1070
|
+
useTail = since is None
|
1071
|
+
originalSince = since
|
504
1072
|
if since is None:
|
505
|
-
|
506
|
-
|
507
|
-
|
1073
|
+
if limit is not None:
|
1074
|
+
# optimization if limit is provided
|
1075
|
+
timeframeInMilliseconds = self.parse_timeframe(timeframe) * 1000
|
1076
|
+
since = self.sum(until, timeframeInMilliseconds * limit * -1)
|
1077
|
+
useTail = False
|
1078
|
+
else:
|
1079
|
+
since = 0
|
508
1080
|
params = self.omit(params, ['until'])
|
509
|
-
request = {
|
1081
|
+
request: dict = {
|
510
1082
|
'type': 'candleSnapshot',
|
511
1083
|
'req': {
|
512
|
-
'coin': market['base'],
|
513
|
-
'interval': timeframe,
|
1084
|
+
'coin': market['base'] if market['swap'] else market['id'],
|
1085
|
+
'interval': self.safe_string(self.timeframes, timeframe, timeframe),
|
514
1086
|
'startTime': since,
|
515
1087
|
'endTime': until,
|
516
1088
|
},
|
@@ -532,7 +1104,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
532
1104
|
# }
|
533
1105
|
# ]
|
534
1106
|
#
|
535
|
-
return self.parse_ohlcvs(response, market, timeframe,
|
1107
|
+
return self.parse_ohlcvs(response, market, timeframe, originalSince, limit, useTail)
|
536
1108
|
|
537
1109
|
def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
|
538
1110
|
#
|
@@ -550,7 +1122,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
550
1122
|
# }
|
551
1123
|
#
|
552
1124
|
return [
|
553
|
-
self.safe_integer(ohlcv, '
|
1125
|
+
self.safe_integer(ohlcv, 't'),
|
554
1126
|
self.safe_number(ohlcv, 'o'),
|
555
1127
|
self.safe_number(ohlcv, 'h'),
|
556
1128
|
self.safe_number(ohlcv, 'l'),
|
@@ -561,8 +1133,10 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
561
1133
|
def fetch_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
562
1134
|
"""
|
563
1135
|
get the list of most recent trades for a particular symbol
|
564
|
-
|
565
|
-
|
1136
|
+
|
1137
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-fills
|
1138
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-fills-by-time
|
1139
|
+
|
566
1140
|
:param str symbol: unified market symbol
|
567
1141
|
:param int [since]: the earliest time in ms to fetch trades for
|
568
1142
|
:param int [limit]: the maximum number of trades structures to retrieve
|
@@ -576,7 +1150,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
576
1150
|
userAddress, params = self.handle_public_address('fetchTrades', params)
|
577
1151
|
self.load_markets()
|
578
1152
|
market = self.safe_market(symbol)
|
579
|
-
request = {
|
1153
|
+
request: dict = {
|
580
1154
|
'user': userAddress,
|
581
1155
|
}
|
582
1156
|
if since is not None:
|
@@ -612,13 +1186,18 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
612
1186
|
return self.parse_trades(response, market, since, limit)
|
613
1187
|
|
614
1188
|
def amount_to_precision(self, symbol, amount):
|
615
|
-
|
1189
|
+
market = self.market(symbol)
|
1190
|
+
return self.decimal_to_precision(amount, ROUND, market['precision']['amount'], self.precisionMode, self.paddingMode)
|
616
1191
|
|
617
1192
|
def price_to_precision(self, symbol: str, price) -> str:
|
618
1193
|
market = self.market(symbol)
|
619
|
-
|
620
|
-
|
621
|
-
|
1194
|
+
priceStr = self.number_to_string(price)
|
1195
|
+
integerPart = priceStr.split('.')[0]
|
1196
|
+
significantDigits = max(5, len(integerPart))
|
1197
|
+
result = self.decimal_to_precision(price, ROUND, significantDigits, SIGNIFICANT_DIGITS, self.paddingMode)
|
1198
|
+
maxDecimals = 8 if market['spot'] else 6
|
1199
|
+
subtractedValue = maxDecimals - self.precision_from_string(self.safe_string(market['precision'], 'amount'))
|
1200
|
+
return self.decimal_to_precision(result, ROUND, subtractedValue, DECIMAL_PLACES, self.paddingMode)
|
622
1201
|
|
623
1202
|
def hash_message(self, message):
|
624
1203
|
return '0x' + self.hash(message, 'keccak', 'hex')
|
@@ -657,7 +1236,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
657
1236
|
hash = self.action_hash(action, vaultAdress, nonce)
|
658
1237
|
isTestnet = self.safe_bool(self.options, 'sandboxMode', False)
|
659
1238
|
phantomAgent = self.construct_phantom_agent(hash, isTestnet)
|
660
|
-
# data = {
|
1239
|
+
# data: Dict = {
|
661
1240
|
# 'domain': {
|
662
1241
|
# 'chainId': 1337,
|
663
1242
|
# 'name': 'Exchange',
|
@@ -681,13 +1260,13 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
681
1260
|
# }
|
682
1261
|
zeroAddress = self.safe_string(self.options, 'zeroAddress')
|
683
1262
|
chainId = 1337 # check self out
|
684
|
-
domain = {
|
1263
|
+
domain: dict = {
|
685
1264
|
'chainId': chainId,
|
686
1265
|
'name': 'Exchange',
|
687
1266
|
'verifyingContract': zeroAddress,
|
688
1267
|
'version': '1',
|
689
1268
|
}
|
690
|
-
messageTypes = {
|
1269
|
+
messageTypes: dict = {
|
691
1270
|
'Agent': [
|
692
1271
|
{'name': 'source', 'type': 'string'},
|
693
1272
|
{'name': 'connectionId', 'type': 'bytes32'},
|
@@ -697,11 +1276,12 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
697
1276
|
signature = self.sign_message(msg, self.privateKey)
|
698
1277
|
return signature
|
699
1278
|
|
700
|
-
def
|
1279
|
+
def sign_user_signed_action(self, messageTypes, message):
|
701
1280
|
zeroAddress = self.safe_string(self.options, 'zeroAddress')
|
702
|
-
|
1281
|
+
chainId = 421614 # check self out
|
1282
|
+
domain: dict = {
|
703
1283
|
'chainId': chainId,
|
704
|
-
'name': '
|
1284
|
+
'name': 'HyperliquidSignTransaction',
|
705
1285
|
'verifyingContract': zeroAddress,
|
706
1286
|
'version': '1',
|
707
1287
|
}
|
@@ -709,72 +1289,108 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
709
1289
|
signature = self.sign_message(msg, self.privateKey)
|
710
1290
|
return signature
|
711
1291
|
|
712
|
-
def
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
'UsdTransferSignPayload': [
|
1292
|
+
def build_usd_send_sig(self, message):
|
1293
|
+
messageTypes: dict = {
|
1294
|
+
'HyperliquidTransaction:UsdSend': [
|
1295
|
+
{'name': 'hyperliquidChain', 'type': 'string'},
|
717
1296
|
{'name': 'destination', 'type': 'string'},
|
718
1297
|
{'name': 'amount', 'type': 'string'},
|
719
1298
|
{'name': 'time', 'type': 'uint64'},
|
720
1299
|
],
|
721
1300
|
}
|
722
|
-
return self.
|
1301
|
+
return self.sign_user_signed_action(messageTypes, message)
|
1302
|
+
|
1303
|
+
def build_usd_class_send_sig(self, message):
|
1304
|
+
messageTypes: dict = {
|
1305
|
+
'HyperliquidTransaction:UsdClassTransfer': [
|
1306
|
+
{'name': 'hyperliquidChain', 'type': 'string'},
|
1307
|
+
{'name': 'amount', 'type': 'string'},
|
1308
|
+
{'name': 'toPerp', 'type': 'bool'},
|
1309
|
+
{'name': 'nonce', 'type': 'uint64'},
|
1310
|
+
],
|
1311
|
+
}
|
1312
|
+
return self.sign_user_signed_action(messageTypes, message)
|
723
1313
|
|
724
1314
|
def build_withdraw_sig(self, message):
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
'WithdrawFromBridge2SignPayload': [
|
1315
|
+
messageTypes: dict = {
|
1316
|
+
'HyperliquidTransaction:Withdraw': [
|
1317
|
+
{'name': 'hyperliquidChain', 'type': 'string'},
|
729
1318
|
{'name': 'destination', 'type': 'string'},
|
730
|
-
{'name': '
|
1319
|
+
{'name': 'amount', 'type': 'string'},
|
731
1320
|
{'name': 'time', 'type': 'uint64'},
|
732
1321
|
],
|
733
1322
|
}
|
734
|
-
return self.
|
1323
|
+
return self.sign_user_signed_action(messageTypes, message)
|
735
1324
|
|
736
1325
|
def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
737
1326
|
"""
|
738
1327
|
create a trade order
|
739
|
-
|
1328
|
+
|
1329
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#place-an-order
|
1330
|
+
|
740
1331
|
:param str symbol: unified symbol of the market to create an order in
|
741
1332
|
:param str type: 'market' or 'limit'
|
742
1333
|
:param str side: 'buy' or 'sell'
|
743
1334
|
:param float amount: how much of currency you want to trade in units of base currency
|
744
|
-
:param float [price]: the price at which the order is to be
|
1335
|
+
:param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
|
745
1336
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
746
1337
|
:param str [params.timeInForce]: 'Gtc', 'Ioc', 'Alo'
|
747
1338
|
:param bool [params.postOnly]: True or False whether the order is post-only
|
748
1339
|
:param bool [params.reduceOnly]: True or False whether the order is reduce-only
|
749
1340
|
:param float [params.triggerPrice]: The price at which a trigger order is triggered at
|
750
|
-
:param str [params.clientOrderId]: client order id,
|
1341
|
+
:param str [params.clientOrderId]: client order id,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
|
751
1342
|
:param str [params.slippage]: the slippage for market order
|
1343
|
+
:param str [params.vaultAddress]: the vault address for order
|
752
1344
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
753
1345
|
"""
|
754
1346
|
self.load_markets()
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
'symbol': symbol,
|
759
|
-
'type': type,
|
760
|
-
'side': side,
|
761
|
-
'amount': amount,
|
762
|
-
'price': price,
|
763
|
-
'params': params,
|
764
|
-
}
|
765
|
-
response = self.create_orders([order], params)
|
766
|
-
first = self.safe_dict(response, 0)
|
767
|
-
return first
|
1347
|
+
order, globalParams = self.parse_create_order_args(symbol, type, side, amount, price, params)
|
1348
|
+
orders = self.create_orders([order], globalParams)
|
1349
|
+
return orders[0]
|
768
1350
|
|
769
1351
|
def create_orders(self, orders: List[OrderRequest], params={}):
|
770
1352
|
"""
|
771
1353
|
create a list of trade orders
|
772
|
-
|
1354
|
+
|
1355
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#place-an-order
|
1356
|
+
|
773
1357
|
:param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
|
1358
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
774
1359
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
775
1360
|
"""
|
776
|
-
self.check_required_credentials()
|
777
1361
|
self.load_markets()
|
1362
|
+
request = self.create_orders_request(orders, params)
|
1363
|
+
response = self.privatePostExchange(request)
|
1364
|
+
#
|
1365
|
+
# {
|
1366
|
+
# "status": "ok",
|
1367
|
+
# "response": {
|
1368
|
+
# "type": "order",
|
1369
|
+
# "data": {
|
1370
|
+
# "statuses": [
|
1371
|
+
# {
|
1372
|
+
# "resting": {
|
1373
|
+
# "oid": 5063830287
|
1374
|
+
# }
|
1375
|
+
# }
|
1376
|
+
# ]
|
1377
|
+
# }
|
1378
|
+
# }
|
1379
|
+
# }
|
1380
|
+
#
|
1381
|
+
responseObj = self.safe_dict(response, 'response', {})
|
1382
|
+
data = self.safe_dict(responseObj, 'data', {})
|
1383
|
+
statuses = self.safe_list(data, 'statuses', [])
|
1384
|
+
return self.parse_orders(statuses, None)
|
1385
|
+
|
1386
|
+
def create_orders_request(self, orders, params={}) -> dict:
|
1387
|
+
"""
|
1388
|
+
create a list of trade orders
|
1389
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#place-an-order
|
1390
|
+
:param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
|
1391
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1392
|
+
"""
|
1393
|
+
self.check_required_credentials()
|
778
1394
|
defaultSlippage = self.safe_string(self.options, 'defaultSlippage')
|
779
1395
|
defaultSlippage = self.safe_string(params, 'slippage', defaultSlippage)
|
780
1396
|
hasClientOrderId = False
|
@@ -791,7 +1407,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
791
1407
|
clientOrderId = self.safe_string_2(orderParams, 'clientOrderId', 'client_id')
|
792
1408
|
if clientOrderId is None:
|
793
1409
|
raise ArgumentsRequired(self.id + ' createOrders() all orders must have clientOrderId if at least one has a clientOrderId')
|
794
|
-
params = self.omit(params, ['slippage', 'clientOrderId', 'client_id', 'slippage', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice'])
|
1410
|
+
params = self.omit(params, ['slippage', 'clientOrderId', 'client_id', 'slippage', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'timeInForce'])
|
795
1411
|
nonce = self.milliseconds()
|
796
1412
|
orderReq = []
|
797
1413
|
for i in range(0, len(orders)):
|
@@ -806,7 +1422,6 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
806
1422
|
amount = self.safe_string(rawOrder, 'amount')
|
807
1423
|
price = self.safe_string(rawOrder, 'price')
|
808
1424
|
orderParams = self.safe_dict(rawOrder, 'params', {})
|
809
|
-
orderParams = self.extend(params, orderParams)
|
810
1425
|
clientOrderId = self.safe_string_2(orderParams, 'clientOrderId', 'client_id')
|
811
1426
|
slippage = self.safe_string(orderParams, 'slippage', defaultSlippage)
|
812
1427
|
defaultTimeInForce = 'ioc' if (isMarket) else 'gtc'
|
@@ -829,7 +1444,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
829
1444
|
px = self.price_to_precision(symbol, price)
|
830
1445
|
sz = self.amount_to_precision(symbol, amount)
|
831
1446
|
reduceOnly = self.safe_bool(orderParams, 'reduceOnly', False)
|
832
|
-
orderType = {}
|
1447
|
+
orderType: dict = {}
|
833
1448
|
if isTrigger:
|
834
1449
|
isTp = False
|
835
1450
|
if takeProfitPrice is not None:
|
@@ -846,7 +1461,8 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
846
1461
|
orderType['limit'] = {
|
847
1462
|
'tif': timeInForce,
|
848
1463
|
}
|
849
|
-
|
1464
|
+
orderParams = self.omit(orderParams, ['clientOrderId', 'slippage', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'timeInForce', 'client_id', 'reduceOnly', 'postOnly'])
|
1465
|
+
orderObj: dict = {
|
850
1466
|
'a': self.parse_to_int(market['baseId']),
|
851
1467
|
'b': isBuy,
|
852
1468
|
'p': px,
|
@@ -858,8 +1474,8 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
858
1474
|
if clientOrderId is not None:
|
859
1475
|
orderObj['c'] = clientOrderId
|
860
1476
|
orderReq.append(orderObj)
|
861
|
-
vaultAddress = self.safe_string(params, 'vaultAddress')
|
862
|
-
orderAction = {
|
1477
|
+
vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
|
1478
|
+
orderAction: dict = {
|
863
1479
|
'type': 'order',
|
864
1480
|
'orders': orderReq,
|
865
1481
|
'grouping': 'na',
|
@@ -868,57 +1484,46 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
868
1484
|
if vaultAddress is None:
|
869
1485
|
orderAction['brokerCode'] = 1
|
870
1486
|
signature = self.sign_l1_action(orderAction, nonce, vaultAddress)
|
871
|
-
request = {
|
1487
|
+
request: dict = {
|
872
1488
|
'action': orderAction,
|
873
1489
|
'nonce': nonce,
|
874
1490
|
'signature': signature,
|
875
1491
|
# 'vaultAddress': vaultAddress,
|
876
1492
|
}
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
# "response": {
|
882
|
-
# "type": "order",
|
883
|
-
# "data": {
|
884
|
-
# "statuses": [
|
885
|
-
# {
|
886
|
-
# "resting": {
|
887
|
-
# "oid": 5063830287
|
888
|
-
# }
|
889
|
-
# }
|
890
|
-
# ]
|
891
|
-
# }
|
892
|
-
# }
|
893
|
-
# }
|
894
|
-
#
|
895
|
-
responseObj = self.safe_dict(response, 'response', {})
|
896
|
-
data = self.safe_dict(responseObj, 'data', {})
|
897
|
-
statuses = self.safe_list(data, 'statuses', [])
|
898
|
-
return self.parse_orders(statuses, None)
|
1493
|
+
if vaultAddress is not None:
|
1494
|
+
params = self.omit(params, 'vaultAddress')
|
1495
|
+
request['vaultAddress'] = vaultAddress
|
1496
|
+
return request
|
899
1497
|
|
900
1498
|
def cancel_order(self, id: str, symbol: Str = None, params={}):
|
901
1499
|
"""
|
902
1500
|
cancels an open order
|
903
|
-
|
904
|
-
|
1501
|
+
|
1502
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s
|
1503
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s-by-cloid
|
1504
|
+
|
905
1505
|
:param str id: order id
|
906
1506
|
:param str symbol: unified symbol of the market the order was made in
|
907
1507
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
908
|
-
:param str [params.clientOrderId]: client order id(
|
1508
|
+
:param str [params.clientOrderId]: client order id,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
|
1509
|
+
:param str [params.vaultAddress]: the vault address for order
|
909
1510
|
:returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
910
1511
|
"""
|
911
|
-
|
1512
|
+
orders = self.cancel_orders([id], symbol, params)
|
1513
|
+
return self.safe_dict(orders, 0)
|
912
1514
|
|
913
1515
|
def cancel_orders(self, ids: List[str], symbol: Str = None, params={}):
|
914
1516
|
"""
|
915
1517
|
cancel multiple orders
|
916
|
-
|
917
|
-
|
1518
|
+
|
1519
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s
|
1520
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s-by-cloid
|
1521
|
+
|
918
1522
|
:param str[] ids: order ids
|
919
1523
|
:param str [symbol]: unified market symbol
|
920
1524
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
921
|
-
:param string|str[] [params.clientOrderId]: client order ids(
|
1525
|
+
:param string|str[] [params.clientOrderId]: client order ids,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
|
1526
|
+
:param str [params.vaultAddress]: the vault address
|
922
1527
|
:returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
923
1528
|
"""
|
924
1529
|
self.check_required_credentials()
|
@@ -929,12 +1534,12 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
929
1534
|
clientOrderId = self.safe_value_2(params, 'clientOrderId', 'client_id')
|
930
1535
|
params = self.omit(params, ['clientOrderId', 'client_id'])
|
931
1536
|
nonce = self.milliseconds()
|
932
|
-
request = {
|
1537
|
+
request: dict = {
|
933
1538
|
'nonce': nonce,
|
934
1539
|
# 'vaultAddress': vaultAddress,
|
935
1540
|
}
|
936
1541
|
cancelReq = []
|
937
|
-
cancelAction = {
|
1542
|
+
cancelAction: dict = {
|
938
1543
|
'type': '',
|
939
1544
|
'cancels': [],
|
940
1545
|
}
|
@@ -956,11 +1561,92 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
956
1561
|
'o': self.parse_to_numeric(ids[i]),
|
957
1562
|
})
|
958
1563
|
cancelAction['cancels'] = cancelReq
|
959
|
-
vaultAddress = self.safe_string(params, 'vaultAddress')
|
1564
|
+
vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
|
960
1565
|
signature = self.sign_l1_action(cancelAction, nonce, vaultAddress)
|
961
1566
|
request['action'] = cancelAction
|
962
1567
|
request['signature'] = signature
|
963
|
-
|
1568
|
+
if vaultAddress is not None:
|
1569
|
+
params = self.omit(params, 'vaultAddress')
|
1570
|
+
request['vaultAddress'] = vaultAddress
|
1571
|
+
response = self.privatePostExchange(request)
|
1572
|
+
#
|
1573
|
+
# {
|
1574
|
+
# "status":"ok",
|
1575
|
+
# "response":{
|
1576
|
+
# "type":"cancel",
|
1577
|
+
# "data":{
|
1578
|
+
# "statuses":[
|
1579
|
+
# "success"
|
1580
|
+
# ]
|
1581
|
+
# }
|
1582
|
+
# }
|
1583
|
+
# }
|
1584
|
+
#
|
1585
|
+
innerResponse = self.safe_dict(response, 'response')
|
1586
|
+
data = self.safe_dict(innerResponse, 'data')
|
1587
|
+
statuses = self.safe_list(data, 'statuses')
|
1588
|
+
orders = []
|
1589
|
+
for i in range(0, len(statuses)):
|
1590
|
+
status = statuses[i]
|
1591
|
+
orders.append(self.safe_order({
|
1592
|
+
'info': status,
|
1593
|
+
'status': status,
|
1594
|
+
}))
|
1595
|
+
return orders
|
1596
|
+
|
1597
|
+
def cancel_orders_for_symbols(self, orders: List[CancellationRequest], params={}):
|
1598
|
+
"""
|
1599
|
+
cancel multiple orders for multiple symbols
|
1600
|
+
|
1601
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s
|
1602
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s-by-cloid
|
1603
|
+
|
1604
|
+
:param CancellationRequest[] orders: each order should contain the parameters required by cancelOrder namely id and symbol, example [{"id": "a", "symbol": "BTC/USDT"}, {"id": "b", "symbol": "ETH/USDT"}]
|
1605
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1606
|
+
:param str [params.vaultAddress]: the vault address
|
1607
|
+
:returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1608
|
+
"""
|
1609
|
+
self.check_required_credentials()
|
1610
|
+
self.load_markets()
|
1611
|
+
nonce = self.milliseconds()
|
1612
|
+
request: dict = {
|
1613
|
+
'nonce': nonce,
|
1614
|
+
# 'vaultAddress': vaultAddress,
|
1615
|
+
}
|
1616
|
+
cancelReq = []
|
1617
|
+
cancelAction: dict = {
|
1618
|
+
'type': '',
|
1619
|
+
'cancels': [],
|
1620
|
+
}
|
1621
|
+
cancelByCloid = False
|
1622
|
+
for i in range(0, len(orders)):
|
1623
|
+
order = orders[i]
|
1624
|
+
clientOrderId = self.safe_string(order, 'clientOrderId')
|
1625
|
+
if clientOrderId is not None:
|
1626
|
+
cancelByCloid = True
|
1627
|
+
id = self.safe_string(order, 'id')
|
1628
|
+
symbol = self.safe_string(order, 'symbol')
|
1629
|
+
if symbol is None:
|
1630
|
+
raise ArgumentsRequired(self.id + ' cancelOrdersForSymbols() requires a symbol argument in each order')
|
1631
|
+
if id is not None and cancelByCloid:
|
1632
|
+
raise BadRequest(self.id + ' cancelOrdersForSymbols() all orders must have either id or clientOrderId')
|
1633
|
+
assetKey = 'asset' if cancelByCloid else 'a'
|
1634
|
+
idKey = 'cloid' if cancelByCloid else 'o'
|
1635
|
+
market = self.market(symbol)
|
1636
|
+
cancelObj: dict = {}
|
1637
|
+
cancelObj[assetKey] = self.parse_to_numeric(market['baseId'])
|
1638
|
+
cancelObj[idKey] = clientOrderId if cancelByCloid else self.parse_to_numeric(id)
|
1639
|
+
cancelReq.append(cancelObj)
|
1640
|
+
cancelAction['type'] = 'cancelByCloid' if cancelByCloid else 'cancel'
|
1641
|
+
cancelAction['cancels'] = cancelReq
|
1642
|
+
vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
|
1643
|
+
signature = self.sign_l1_action(cancelAction, nonce, vaultAddress)
|
1644
|
+
request['action'] = cancelAction
|
1645
|
+
request['signature'] = signature
|
1646
|
+
if vaultAddress is not None:
|
1647
|
+
params = self.omit(params, 'vaultAddress')
|
1648
|
+
request['vaultAddress'] = vaultAddress
|
1649
|
+
response = self.privatePostExchange(request)
|
964
1650
|
#
|
965
1651
|
# {
|
966
1652
|
# "status":"ok",
|
@@ -976,29 +1662,46 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
976
1662
|
#
|
977
1663
|
return response
|
978
1664
|
|
979
|
-
def
|
1665
|
+
def cancel_all_orders_after(self, timeout: Int, params={}):
|
980
1666
|
"""
|
981
|
-
|
982
|
-
:
|
983
|
-
:see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-multiple-orders
|
984
|
-
:param str id: cancel order id
|
985
|
-
:param str symbol: unified symbol of the market to create an order in
|
986
|
-
:param str type: 'market' or 'limit'
|
987
|
-
:param str side: 'buy' or 'sell'
|
988
|
-
:param float amount: how much of currency you want to trade in units of base currency
|
989
|
-
:param float [price]: the price at which the order is to be fullfilled, in units of the base currency, ignored in market orders
|
1667
|
+
dead man's switch, cancel all orders after the given timeout
|
1668
|
+
:param number timeout: time in milliseconds, 0 represents cancel the timer
|
990
1669
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
991
|
-
:param str [params.
|
992
|
-
:
|
993
|
-
:param bool [params.reduceOnly]: True or False whether the order is reduce-only
|
994
|
-
:param float [params.triggerPrice]: The price at which a trigger order is triggered at
|
995
|
-
:param str [params.clientOrderId]: client order id,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
|
996
|
-
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1670
|
+
:param str [params.vaultAddress]: the vault address
|
1671
|
+
:returns dict: the api result
|
997
1672
|
"""
|
1673
|
+
self.check_required_credentials()
|
1674
|
+
self.load_markets()
|
1675
|
+
params = self.omit(params, ['clientOrderId', 'client_id'])
|
1676
|
+
nonce = self.milliseconds()
|
1677
|
+
request: dict = {
|
1678
|
+
'nonce': nonce,
|
1679
|
+
# 'vaultAddress': vaultAddress,
|
1680
|
+
}
|
1681
|
+
cancelAction: dict = {
|
1682
|
+
'type': 'scheduleCancel',
|
1683
|
+
'time': nonce + timeout,
|
1684
|
+
}
|
1685
|
+
vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
|
1686
|
+
signature = self.sign_l1_action(cancelAction, nonce, vaultAddress)
|
1687
|
+
request['action'] = cancelAction
|
1688
|
+
request['signature'] = signature
|
1689
|
+
if vaultAddress is not None:
|
1690
|
+
params = self.omit(params, 'vaultAddress')
|
1691
|
+
request['vaultAddress'] = vaultAddress
|
1692
|
+
response = self.privatePostExchange(request)
|
1693
|
+
#
|
1694
|
+
# {
|
1695
|
+
# "status":"err",
|
1696
|
+
# "response":"Cannot set scheduled cancel time until enough volume traded. Required: $1000000. Traded: $373.47205."
|
1697
|
+
# }
|
1698
|
+
#
|
1699
|
+
return response
|
1700
|
+
|
1701
|
+
def edit_order_request(self, id: str, symbol: str, type: str, side: str, amount: Num = None, price: Num = None, params={}):
|
998
1702
|
self.check_required_credentials()
|
999
1703
|
if id is None:
|
1000
1704
|
raise ArgumentsRequired(self.id + ' editOrder() requires an id argument')
|
1001
|
-
self.load_markets()
|
1002
1705
|
market = self.market(symbol)
|
1003
1706
|
type = type.upper()
|
1004
1707
|
isMarket = (type == 'MARKET')
|
@@ -1025,7 +1728,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1025
1728
|
px = self.price_to_precision(symbol, str(price))
|
1026
1729
|
sz = self.amount_to_precision(symbol, amount)
|
1027
1730
|
reduceOnly = self.safe_bool(params, 'reduceOnly', False)
|
1028
|
-
orderType = {}
|
1731
|
+
orderType: dict = {}
|
1029
1732
|
if isTrigger:
|
1030
1733
|
isTp = False
|
1031
1734
|
if takeProfitPrice is not None:
|
@@ -1045,7 +1748,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1045
1748
|
if triggerPrice is None:
|
1046
1749
|
triggerPrice = '0'
|
1047
1750
|
nonce = self.milliseconds()
|
1048
|
-
orderReq = {
|
1751
|
+
orderReq: dict = {
|
1049
1752
|
'a': self.parse_to_int(market['baseId']),
|
1050
1753
|
'b': isBuy,
|
1051
1754
|
'p': px,
|
@@ -1056,23 +1759,53 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1056
1759
|
}
|
1057
1760
|
if clientOrderId is not None:
|
1058
1761
|
orderReq['c'] = clientOrderId
|
1059
|
-
modifyReq = {
|
1762
|
+
modifyReq: dict = {
|
1060
1763
|
'oid': self.parse_to_int(id),
|
1061
1764
|
'order': orderReq,
|
1062
1765
|
}
|
1063
|
-
modifyAction = {
|
1766
|
+
modifyAction: dict = {
|
1064
1767
|
'type': 'batchModify',
|
1065
1768
|
'modifies': [modifyReq],
|
1066
1769
|
}
|
1067
|
-
vaultAddress = self.safe_string(params, 'vaultAddress')
|
1770
|
+
vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
|
1068
1771
|
signature = self.sign_l1_action(modifyAction, nonce, vaultAddress)
|
1069
|
-
request = {
|
1772
|
+
request: dict = {
|
1070
1773
|
'action': modifyAction,
|
1071
1774
|
'nonce': nonce,
|
1072
1775
|
'signature': signature,
|
1073
1776
|
# 'vaultAddress': vaultAddress,
|
1074
1777
|
}
|
1075
|
-
|
1778
|
+
if vaultAddress is not None:
|
1779
|
+
params = self.omit(params, 'vaultAddress')
|
1780
|
+
request['vaultAddress'] = vaultAddress
|
1781
|
+
return request
|
1782
|
+
|
1783
|
+
def edit_order(self, id: str, symbol: str, type: str, side: str, amount: Num = None, price: Num = None, params={}):
|
1784
|
+
"""
|
1785
|
+
edit a trade order
|
1786
|
+
|
1787
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-an-order
|
1788
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-multiple-orders
|
1789
|
+
|
1790
|
+
:param str id: cancel order id
|
1791
|
+
:param str symbol: unified symbol of the market to create an order in
|
1792
|
+
:param str type: 'market' or 'limit'
|
1793
|
+
:param str side: 'buy' or 'sell'
|
1794
|
+
:param float amount: how much of currency you want to trade in units of base currency
|
1795
|
+
:param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
|
1796
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1797
|
+
:param str [params.timeInForce]: 'Gtc', 'Ioc', 'Alo'
|
1798
|
+
:param bool [params.postOnly]: True or False whether the order is post-only
|
1799
|
+
:param bool [params.reduceOnly]: True or False whether the order is reduce-only
|
1800
|
+
:param float [params.triggerPrice]: The price at which a trigger order is triggered at
|
1801
|
+
:param str [params.clientOrderId]: client order id,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
|
1802
|
+
:param str [params.vaultAddress]: the vault address for order
|
1803
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1804
|
+
"""
|
1805
|
+
self.load_markets()
|
1806
|
+
market = self.market(symbol)
|
1807
|
+
request = self.edit_order_request(id, symbol, type, side, amount, price, params)
|
1808
|
+
response = self.privatePostExchange(request)
|
1076
1809
|
#
|
1077
1810
|
# {
|
1078
1811
|
# "status": "ok",
|
@@ -1117,7 +1850,9 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1117
1850
|
def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1118
1851
|
"""
|
1119
1852
|
fetches historical funding rate prices
|
1120
|
-
|
1853
|
+
|
1854
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/perpetuals#retrieve-historical-funding-rates
|
1855
|
+
|
1121
1856
|
:param str symbol: unified symbol of the market to fetch the funding rate history for
|
1122
1857
|
:param int [since]: timestamp in ms of the earliest funding rate to fetch
|
1123
1858
|
:param int [limit]: the maximum amount of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>` to fetch
|
@@ -1126,15 +1861,18 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1126
1861
|
:returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
|
1127
1862
|
"""
|
1128
1863
|
self.load_markets()
|
1864
|
+
if symbol is None:
|
1865
|
+
raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
|
1129
1866
|
market = self.market(symbol)
|
1130
|
-
request = {
|
1867
|
+
request: dict = {
|
1131
1868
|
'type': 'fundingHistory',
|
1132
1869
|
'coin': market['base'],
|
1133
1870
|
}
|
1134
1871
|
if since is not None:
|
1135
1872
|
request['startTime'] = since
|
1136
1873
|
else:
|
1137
|
-
|
1874
|
+
maxLimit = 500 if (limit is None) else limit
|
1875
|
+
request['startTime'] = self.milliseconds() - maxLimit * 60 * 60 * 1000
|
1138
1876
|
until = self.safe_integer(params, 'until')
|
1139
1877
|
params = self.omit(params, 'until')
|
1140
1878
|
if until is not None:
|
@@ -1167,20 +1905,25 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1167
1905
|
def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
1168
1906
|
"""
|
1169
1907
|
fetch all unfilled currently open orders
|
1170
|
-
|
1908
|
+
|
1909
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-open-orders
|
1910
|
+
|
1171
1911
|
:param str symbol: unified market symbol
|
1172
1912
|
:param int [since]: the earliest time in ms to fetch open orders for
|
1173
1913
|
:param int [limit]: the maximum number of open orders structures to retrieve
|
1174
1914
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1175
1915
|
:param str [params.user]: user address, will default to self.walletAddress if not provided
|
1916
|
+
:param str [params.method]: 'openOrders' or 'frontendOpenOrders' default is 'frontendOpenOrders'
|
1176
1917
|
:returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1177
1918
|
"""
|
1178
1919
|
userAddress = None
|
1179
1920
|
userAddress, params = self.handle_public_address('fetchOpenOrders', params)
|
1921
|
+
method = None
|
1922
|
+
method, params = self.handle_option_and_params(params, 'fetchOpenOrders', 'method', 'frontendOpenOrders')
|
1180
1923
|
self.load_markets()
|
1181
1924
|
market = self.safe_market(symbol)
|
1182
|
-
request = {
|
1183
|
-
'type':
|
1925
|
+
request: dict = {
|
1926
|
+
'type': method,
|
1184
1927
|
'user': userAddress,
|
1185
1928
|
}
|
1186
1929
|
response = self.publicPostInfo(self.extend(request, params))
|
@@ -1197,7 +1940,14 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1197
1940
|
# }
|
1198
1941
|
# ]
|
1199
1942
|
#
|
1200
|
-
|
1943
|
+
orderWithStatus = []
|
1944
|
+
for i in range(0, len(response)):
|
1945
|
+
order = response[i]
|
1946
|
+
extendOrder = {}
|
1947
|
+
if self.safe_string(order, 'status') is None:
|
1948
|
+
extendOrder['ccxtStatus'] = 'open'
|
1949
|
+
orderWithStatus.append(self.extend(order, extendOrder))
|
1950
|
+
return self.parse_orders(orderWithStatus, market, since, limit)
|
1201
1951
|
|
1202
1952
|
def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
1203
1953
|
"""
|
@@ -1209,11 +1959,56 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1209
1959
|
:param str [params.user]: user address, will default to self.walletAddress if not provided
|
1210
1960
|
:returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1211
1961
|
"""
|
1962
|
+
self.load_markets()
|
1963
|
+
orders = self.fetch_orders(symbol, None, None, params) # don't filter here because we don't want to catch open orders
|
1964
|
+
closedOrders = self.filter_by_array(orders, 'status', ['closed'], False)
|
1965
|
+
return self.filter_by_symbol_since_limit(closedOrders, symbol, since, limit)
|
1966
|
+
|
1967
|
+
def fetch_canceled_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
1968
|
+
"""
|
1969
|
+
fetch all canceled orders
|
1970
|
+
:param str symbol: unified market symbol
|
1971
|
+
:param int [since]: the earliest time in ms to fetch open orders for
|
1972
|
+
:param int [limit]: the maximum number of open orders structures to retrieve
|
1973
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1974
|
+
:param str [params.user]: user address, will default to self.walletAddress if not provided
|
1975
|
+
:returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1976
|
+
"""
|
1977
|
+
self.load_markets()
|
1978
|
+
orders = self.fetch_orders(symbol, None, None, params) # don't filter here because we don't want to catch open orders
|
1979
|
+
closedOrders = self.filter_by_array(orders, 'status', ['canceled'], False)
|
1980
|
+
return self.filter_by_symbol_since_limit(closedOrders, symbol, since, limit)
|
1981
|
+
|
1982
|
+
def fetch_canceled_and_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
1983
|
+
"""
|
1984
|
+
fetch all closed and canceled orders
|
1985
|
+
:param str symbol: unified market symbol
|
1986
|
+
:param int [since]: the earliest time in ms to fetch open orders for
|
1987
|
+
:param int [limit]: the maximum number of open orders structures to retrieve
|
1988
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1989
|
+
:param str [params.user]: user address, will default to self.walletAddress if not provided
|
1990
|
+
:returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1991
|
+
"""
|
1992
|
+
self.load_markets()
|
1993
|
+
orders = self.fetch_orders(symbol, None, None, params) # don't filter here because we don't want to catch open orders
|
1994
|
+
closedOrders = self.filter_by_array(orders, 'status', ['canceled', 'closed', 'rejected'], False)
|
1995
|
+
return self.filter_by_symbol_since_limit(closedOrders, symbol, since, limit)
|
1996
|
+
|
1997
|
+
def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
1998
|
+
"""
|
1999
|
+
fetch all orders
|
2000
|
+
:param str symbol: unified market symbol
|
2001
|
+
:param int [since]: the earliest time in ms to fetch open orders for
|
2002
|
+
:param int [limit]: the maximum number of open orders structures to retrieve
|
2003
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2004
|
+
:param str [params.user]: user address, will default to self.walletAddress if not provided
|
2005
|
+
:returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
2006
|
+
"""
|
1212
2007
|
userAddress = None
|
1213
|
-
userAddress, params = self.handle_public_address('
|
2008
|
+
userAddress, params = self.handle_public_address('fetchOrders', params)
|
1214
2009
|
self.load_markets()
|
1215
2010
|
market = self.safe_market(symbol)
|
1216
|
-
request = {
|
2011
|
+
request: dict = {
|
1217
2012
|
'type': 'historicalOrders',
|
1218
2013
|
'user': userAddress,
|
1219
2014
|
}
|
@@ -1236,7 +2031,10 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1236
2031
|
def fetch_order(self, id: str, symbol: Str = None, params={}):
|
1237
2032
|
"""
|
1238
2033
|
fetches information on an order made by the user
|
1239
|
-
|
2034
|
+
|
2035
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#query-order-status-by-oid-or-cloid
|
2036
|
+
|
2037
|
+
:param str id: order id
|
1240
2038
|
:param str symbol: unified symbol of the market the order was made in
|
1241
2039
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1242
2040
|
:param str [params.user]: user address, will default to self.walletAddress if not provided
|
@@ -1246,9 +2044,10 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1246
2044
|
userAddress, params = self.handle_public_address('fetchOrder', params)
|
1247
2045
|
self.load_markets()
|
1248
2046
|
market = self.safe_market(symbol)
|
1249
|
-
|
2047
|
+
isClientOrderId = len(id) >= 34
|
2048
|
+
request: dict = {
|
1250
2049
|
'type': 'orderStatus',
|
1251
|
-
'oid': self.parse_to_numeric(id),
|
2050
|
+
'oid': id if isClientOrderId else self.parse_to_numeric(id),
|
1252
2051
|
'user': userAddress,
|
1253
2052
|
}
|
1254
2053
|
response = self.publicPostInfo(self.extend(request, params))
|
@@ -1282,7 +2081,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1282
2081
|
data = self.safe_dict(response, 'order')
|
1283
2082
|
return self.parse_order(data, market)
|
1284
2083
|
|
1285
|
-
def parse_order(self, order, market: Market = None) -> Order:
|
2084
|
+
def parse_order(self, order: dict, market: Market = None) -> Order:
|
1286
2085
|
#
|
1287
2086
|
# fetchOpenOrders
|
1288
2087
|
#
|
@@ -1354,6 +2153,25 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1354
2153
|
# "oid":6195281425
|
1355
2154
|
# }
|
1356
2155
|
# }
|
2156
|
+
# frontendOrder
|
2157
|
+
# {
|
2158
|
+
# "children": [],
|
2159
|
+
# "cloid": null,
|
2160
|
+
# "coin": "BLUR",
|
2161
|
+
# "isPositionTpsl": False,
|
2162
|
+
# "isTrigger": True,
|
2163
|
+
# "limitPx": "0.5",
|
2164
|
+
# "oid": 8670487141,
|
2165
|
+
# "orderType": "Stop Limit",
|
2166
|
+
# "origSz": "20.0",
|
2167
|
+
# "reduceOnly": False,
|
2168
|
+
# "side": "B",
|
2169
|
+
# "sz": "20.0",
|
2170
|
+
# "tif": null,
|
2171
|
+
# "timestamp": 1715523663687,
|
2172
|
+
# "triggerCondition": "Price above 0.6",
|
2173
|
+
# "triggerPx": "0.6"
|
2174
|
+
# }
|
1357
2175
|
#
|
1358
2176
|
entry = self.safe_dict_n(order, ['order', 'resting', 'filled'])
|
1359
2177
|
if entry is None:
|
@@ -1361,17 +2179,20 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1361
2179
|
coin = self.safe_string(entry, 'coin')
|
1362
2180
|
marketId = None
|
1363
2181
|
if coin is not None:
|
1364
|
-
marketId = coin
|
2182
|
+
marketId = self.coin_to_market_id(coin)
|
1365
2183
|
if self.safe_string(entry, 'id') is None:
|
1366
2184
|
market = self.safe_market(marketId, None)
|
1367
2185
|
else:
|
1368
2186
|
market = self.safe_market(marketId, market)
|
1369
2187
|
symbol = market['symbol']
|
1370
|
-
timestamp = self.
|
1371
|
-
status = self.
|
2188
|
+
timestamp = self.safe_integer(entry, 'timestamp')
|
2189
|
+
status = self.safe_string_2(order, 'status', 'ccxtStatus')
|
2190
|
+
order = self.omit(order, ['ccxtStatus'])
|
1372
2191
|
side = self.safe_string(entry, 'side')
|
1373
2192
|
if side is not None:
|
1374
2193
|
side = 'sell' if (side == 'A') else 'buy'
|
2194
|
+
totalAmount = self.safe_string_2(entry, 'origSz', 'totalSz')
|
2195
|
+
remaining = self.safe_string(entry, 'sz')
|
1375
2196
|
return self.safe_order({
|
1376
2197
|
'info': order,
|
1377
2198
|
'id': self.safe_string(entry, 'oid'),
|
@@ -1379,34 +2200,38 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1379
2200
|
'timestamp': timestamp,
|
1380
2201
|
'datetime': self.iso8601(timestamp),
|
1381
2202
|
'lastTradeTimestamp': None,
|
1382
|
-
'lastUpdateTimestamp':
|
2203
|
+
'lastUpdateTimestamp': self.safe_integer(order, 'statusTimestamp'),
|
1383
2204
|
'symbol': symbol,
|
1384
|
-
'type': self.safe_string_lower(entry, 'orderType'),
|
2205
|
+
'type': self.parse_order_type(self.safe_string_lower(entry, 'orderType')),
|
1385
2206
|
'timeInForce': self.safe_string_upper(entry, 'tif'),
|
1386
2207
|
'postOnly': None,
|
1387
2208
|
'reduceOnly': self.safe_bool(entry, 'reduceOnly'),
|
1388
2209
|
'side': side,
|
1389
|
-
'price': self.
|
2210
|
+
'price': self.safe_string(entry, 'limitPx'),
|
1390
2211
|
'triggerPrice': self.safe_number(entry, 'triggerPx') if self.safe_bool(entry, 'isTrigger') else None,
|
1391
|
-
'amount':
|
2212
|
+
'amount': totalAmount,
|
1392
2213
|
'cost': None,
|
1393
|
-
'average': self.
|
1394
|
-
'filled':
|
1395
|
-
'remaining':
|
2214
|
+
'average': self.safe_string(entry, 'avgPx'),
|
2215
|
+
'filled': Precise.string_sub(totalAmount, remaining),
|
2216
|
+
'remaining': remaining,
|
1396
2217
|
'status': self.parse_order_status(status),
|
1397
2218
|
'fee': None,
|
1398
2219
|
'trades': None,
|
1399
2220
|
}, market)
|
1400
2221
|
|
1401
|
-
def parse_order_status(self, status):
|
1402
|
-
statuses = {
|
2222
|
+
def parse_order_status(self, status: Str):
|
2223
|
+
statuses: dict = {
|
1403
2224
|
'triggered': 'open',
|
1404
2225
|
'filled': 'closed',
|
2226
|
+
'open': 'open',
|
2227
|
+
'canceled': 'canceled',
|
2228
|
+
'rejected': 'rejected',
|
2229
|
+
'marginCanceled': 'canceled',
|
1405
2230
|
}
|
1406
2231
|
return self.safe_string(statuses, status, status)
|
1407
2232
|
|
1408
2233
|
def parse_order_type(self, status):
|
1409
|
-
statuses = {
|
2234
|
+
statuses: dict = {
|
1410
2235
|
'stop limit': 'limit',
|
1411
2236
|
'stop market': 'market',
|
1412
2237
|
}
|
@@ -1415,8 +2240,10 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1415
2240
|
def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1416
2241
|
"""
|
1417
2242
|
fetch all trades made by the user
|
1418
|
-
|
1419
|
-
|
2243
|
+
|
2244
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-fills
|
2245
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-fills-by-time
|
2246
|
+
|
1420
2247
|
:param str symbol: unified market symbol
|
1421
2248
|
:param int [since]: the earliest time in ms to fetch trades for
|
1422
2249
|
:param int [limit]: the maximum number of trades structures to retrieve
|
@@ -1428,7 +2255,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1428
2255
|
userAddress, params = self.handle_public_address('fetchMyTrades', params)
|
1429
2256
|
self.load_markets()
|
1430
2257
|
market = self.safe_market(symbol)
|
1431
|
-
request = {
|
2258
|
+
request: dict = {
|
1432
2259
|
'user': userAddress,
|
1433
2260
|
}
|
1434
2261
|
if since is not None:
|
@@ -1449,6 +2276,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1449
2276
|
# "crossed": True,
|
1450
2277
|
# "dir": "Close Long",
|
1451
2278
|
# "fee": "0.050062",
|
2279
|
+
# "feeToken": "USDC",
|
1452
2280
|
# "hash": "0x09d77c96791e98b5775a04092584ab010d009445119c71e4005c0d634ea322bc",
|
1453
2281
|
# "liquidationMarkPx": null,
|
1454
2282
|
# "oid": 3929354691,
|
@@ -1463,7 +2291,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1463
2291
|
#
|
1464
2292
|
return self.parse_trades(response, market, since, limit)
|
1465
2293
|
|
1466
|
-
def parse_trade(self, trade, market: Market = None) -> Trade:
|
2294
|
+
def parse_trade(self, trade: dict, market: Market = None) -> Trade:
|
1467
2295
|
#
|
1468
2296
|
# {
|
1469
2297
|
# "closedPnl": "0.19343",
|
@@ -1486,7 +2314,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1486
2314
|
price = self.safe_string(trade, 'px')
|
1487
2315
|
amount = self.safe_string(trade, 'sz')
|
1488
2316
|
coin = self.safe_string(trade, 'coin')
|
1489
|
-
marketId = coin
|
2317
|
+
marketId = self.coin_to_market_id(coin)
|
1490
2318
|
market = self.safe_market(marketId, None)
|
1491
2319
|
symbol = market['symbol']
|
1492
2320
|
id = self.safe_string(trade, 'tid')
|
@@ -1507,13 +2335,19 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1507
2335
|
'price': price,
|
1508
2336
|
'amount': amount,
|
1509
2337
|
'cost': None,
|
1510
|
-
'fee': {
|
2338
|
+
'fee': {
|
2339
|
+
'cost': fee,
|
2340
|
+
'currency': self.safe_string(trade, 'feeToken'),
|
2341
|
+
'rate': None,
|
2342
|
+
},
|
1511
2343
|
}, market)
|
1512
2344
|
|
1513
2345
|
def fetch_position(self, symbol: str, params={}):
|
1514
2346
|
"""
|
1515
2347
|
fetch data on an open position
|
1516
|
-
|
2348
|
+
|
2349
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/perpetuals#retrieve-users-perpetuals-account-summary
|
2350
|
+
|
1517
2351
|
:param str symbol: unified market symbol of the market the position is held in
|
1518
2352
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1519
2353
|
:param str [params.user]: user address, will default to self.walletAddress if not provided
|
@@ -1525,7 +2359,9 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1525
2359
|
def fetch_positions(self, symbols: Strings = None, params={}):
|
1526
2360
|
"""
|
1527
2361
|
fetch all open positions
|
1528
|
-
|
2362
|
+
|
2363
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/perpetuals#retrieve-users-perpetuals-account-summary
|
2364
|
+
|
1529
2365
|
:param str[] [symbols]: list of unified market symbols
|
1530
2366
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1531
2367
|
:param str [params.user]: user address, will default to self.walletAddress if not provided
|
@@ -1535,7 +2371,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1535
2371
|
userAddress = None
|
1536
2372
|
userAddress, params = self.handle_public_address('fetchPositions', params)
|
1537
2373
|
symbols = self.market_symbols(symbols)
|
1538
|
-
request = {
|
2374
|
+
request: dict = {
|
1539
2375
|
'type': 'clearinghouseState',
|
1540
2376
|
'user': userAddress,
|
1541
2377
|
}
|
@@ -1591,7 +2427,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1591
2427
|
result.append(self.parse_position(data[i], None))
|
1592
2428
|
return self.filter_by_array_positions(result, 'symbol', symbols, False)
|
1593
2429
|
|
1594
|
-
def parse_position(self, position, market: Market = None):
|
2430
|
+
def parse_position(self, position: dict, market: Market = None):
|
1595
2431
|
#
|
1596
2432
|
# {
|
1597
2433
|
# "position": {
|
@@ -1620,18 +2456,22 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1620
2456
|
#
|
1621
2457
|
entry = self.safe_dict(position, 'position', {})
|
1622
2458
|
coin = self.safe_string(entry, 'coin')
|
1623
|
-
marketId = coin
|
2459
|
+
marketId = self.coin_to_market_id(coin)
|
1624
2460
|
market = self.safe_market(marketId, None)
|
1625
2461
|
symbol = market['symbol']
|
1626
2462
|
leverage = self.safe_dict(entry, 'leverage', {})
|
1627
|
-
|
1628
|
-
|
2463
|
+
marginMode = self.safe_string(leverage, 'type')
|
2464
|
+
isIsolated = (marginMode == 'isolated')
|
2465
|
+
rawSize = self.safe_string(entry, 'szi')
|
2466
|
+
size = rawSize
|
1629
2467
|
side = None
|
1630
|
-
if
|
1631
|
-
side = '
|
1632
|
-
|
1633
|
-
|
1634
|
-
|
2468
|
+
if size is not None:
|
2469
|
+
side = 'long' if Precise.string_gt(rawSize, '0') else 'short'
|
2470
|
+
size = Precise.string_abs(size)
|
2471
|
+
rawUnrealizedPnl = self.safe_string(entry, 'unrealizedPnl')
|
2472
|
+
absRawUnrealizedPnl = Precise.string_abs(rawUnrealizedPnl)
|
2473
|
+
initialMargin = self.safe_string(entry, 'marginUsed')
|
2474
|
+
percentage = Precise.string_mul(Precise.string_div(absRawUnrealizedPnl, initialMargin), '100')
|
1635
2475
|
return self.safe_position({
|
1636
2476
|
'info': position,
|
1637
2477
|
'id': None,
|
@@ -1641,21 +2481,21 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1641
2481
|
'isolated': isIsolated,
|
1642
2482
|
'hedged': None,
|
1643
2483
|
'side': side,
|
1644
|
-
'contracts': self.parse_number(
|
2484
|
+
'contracts': self.parse_number(size),
|
1645
2485
|
'contractSize': None,
|
1646
2486
|
'entryPrice': self.safe_number(entry, 'entryPx'),
|
1647
2487
|
'markPrice': None,
|
1648
2488
|
'notional': self.safe_number(entry, 'positionValue'),
|
1649
2489
|
'leverage': self.safe_number(leverage, 'value'),
|
1650
|
-
'collateral':
|
1651
|
-
'initialMargin': initialMargin,
|
2490
|
+
'collateral': self.safe_number(entry, 'marginUsed'),
|
2491
|
+
'initialMargin': self.parse_number(initialMargin),
|
1652
2492
|
'maintenanceMargin': None,
|
1653
2493
|
'initialMarginPercentage': None,
|
1654
2494
|
'maintenanceMarginPercentage': None,
|
1655
|
-
'unrealizedPnl':
|
2495
|
+
'unrealizedPnl': self.parse_number(rawUnrealizedPnl),
|
1656
2496
|
'liquidationPrice': self.safe_number(entry, 'liquidationPx'),
|
1657
|
-
'marginMode':
|
1658
|
-
'percentage': percentage,
|
2497
|
+
'marginMode': marginMode,
|
2498
|
+
'percentage': self.parse_number(percentage),
|
1659
2499
|
})
|
1660
2500
|
|
1661
2501
|
def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
|
@@ -1675,24 +2515,30 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1675
2515
|
if leverage is None:
|
1676
2516
|
raise ArgumentsRequired(self.id + ' setMarginMode() requires a leverage parameter')
|
1677
2517
|
asset = self.parse_to_int(market['baseId'])
|
1678
|
-
isCross = (marginMode == '
|
2518
|
+
isCross = (marginMode == 'cross')
|
1679
2519
|
nonce = self.milliseconds()
|
1680
2520
|
params = self.omit(params, ['leverage'])
|
1681
|
-
updateAction = {
|
2521
|
+
updateAction: dict = {
|
1682
2522
|
'type': 'updateLeverage',
|
1683
2523
|
'asset': asset,
|
1684
2524
|
'isCross': isCross,
|
1685
2525
|
'leverage': leverage,
|
1686
2526
|
}
|
1687
2527
|
vaultAddress = self.safe_string(params, 'vaultAddress')
|
2528
|
+
if vaultAddress is not None:
|
2529
|
+
params = self.omit(params, 'vaultAddress')
|
2530
|
+
if vaultAddress.startswith('0x'):
|
2531
|
+
vaultAddress = vaultAddress.replace('0x', '')
|
1688
2532
|
signature = self.sign_l1_action(updateAction, nonce, vaultAddress)
|
1689
|
-
request = {
|
2533
|
+
request: dict = {
|
1690
2534
|
'action': updateAction,
|
1691
2535
|
'nonce': nonce,
|
1692
2536
|
'signature': signature,
|
1693
2537
|
# 'vaultAddress': vaultAddress,
|
1694
2538
|
}
|
1695
|
-
|
2539
|
+
if vaultAddress is not None:
|
2540
|
+
request['vaultAddress'] = vaultAddress
|
2541
|
+
response = self.privatePostExchange(request)
|
1696
2542
|
#
|
1697
2543
|
# {
|
1698
2544
|
# 'response': {
|
@@ -1721,21 +2567,24 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1721
2567
|
asset = self.parse_to_int(market['baseId'])
|
1722
2568
|
nonce = self.milliseconds()
|
1723
2569
|
params = self.omit(params, 'marginMode')
|
1724
|
-
updateAction = {
|
2570
|
+
updateAction: dict = {
|
1725
2571
|
'type': 'updateLeverage',
|
1726
2572
|
'asset': asset,
|
1727
2573
|
'isCross': isCross,
|
1728
2574
|
'leverage': leverage,
|
1729
2575
|
}
|
1730
|
-
vaultAddress = self.safe_string(params, 'vaultAddress')
|
2576
|
+
vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
|
1731
2577
|
signature = self.sign_l1_action(updateAction, nonce, vaultAddress)
|
1732
|
-
request = {
|
2578
|
+
request: dict = {
|
1733
2579
|
'action': updateAction,
|
1734
2580
|
'nonce': nonce,
|
1735
2581
|
'signature': signature,
|
1736
2582
|
# 'vaultAddress': vaultAddress,
|
1737
2583
|
}
|
1738
|
-
|
2584
|
+
if vaultAddress is not None:
|
2585
|
+
params = self.omit(params, 'vaultAddress')
|
2586
|
+
request['vaultAddress'] = vaultAddress
|
2587
|
+
response = self.privatePostExchange(request)
|
1739
2588
|
#
|
1740
2589
|
# {
|
1741
2590
|
# 'response': {
|
@@ -1746,10 +2595,12 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1746
2595
|
#
|
1747
2596
|
return response
|
1748
2597
|
|
1749
|
-
def add_margin(self, symbol: str, amount, params={}):
|
2598
|
+
def add_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
|
1750
2599
|
"""
|
1751
2600
|
add margin
|
1752
|
-
|
2601
|
+
|
2602
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#update-isolated-margin
|
2603
|
+
|
1753
2604
|
:param str symbol: unified market symbol
|
1754
2605
|
:param float amount: amount of margin to add
|
1755
2606
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -1757,9 +2608,11 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1757
2608
|
"""
|
1758
2609
|
return self.modify_margin_helper(symbol, amount, 'add', params)
|
1759
2610
|
|
1760
|
-
def reduce_margin(self, symbol: str, amount, params={}):
|
2611
|
+
def reduce_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
|
1761
2612
|
"""
|
1762
|
-
|
2613
|
+
|
2614
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#update-isolated-margin
|
2615
|
+
|
1763
2616
|
remove margin from a position
|
1764
2617
|
:param str symbol: unified market symbol
|
1765
2618
|
:param float amount: the amount of margin to remove
|
@@ -1768,7 +2621,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1768
2621
|
"""
|
1769
2622
|
return self.modify_margin_helper(symbol, amount, 'reduce', params)
|
1770
2623
|
|
1771
|
-
def modify_margin_helper(self, symbol: str, amount, type, params={}):
|
2624
|
+
def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
|
1772
2625
|
self.load_markets()
|
1773
2626
|
market = self.market(symbol)
|
1774
2627
|
asset = self.parse_to_int(market['baseId'])
|
@@ -1776,21 +2629,24 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1776
2629
|
if type == 'reduce':
|
1777
2630
|
sz = -sz
|
1778
2631
|
nonce = self.milliseconds()
|
1779
|
-
updateAction = {
|
2632
|
+
updateAction: dict = {
|
1780
2633
|
'type': 'updateIsolatedMargin',
|
1781
2634
|
'asset': asset,
|
1782
2635
|
'isBuy': True,
|
1783
2636
|
'ntli': sz,
|
1784
2637
|
}
|
1785
|
-
vaultAddress = self.safe_string(params, 'vaultAddress')
|
2638
|
+
vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
|
1786
2639
|
signature = self.sign_l1_action(updateAction, nonce, vaultAddress)
|
1787
|
-
request = {
|
2640
|
+
request: dict = {
|
1788
2641
|
'action': updateAction,
|
1789
2642
|
'nonce': nonce,
|
1790
2643
|
'signature': signature,
|
1791
2644
|
# 'vaultAddress': vaultAddress,
|
1792
2645
|
}
|
1793
|
-
|
2646
|
+
if vaultAddress is not None:
|
2647
|
+
params = self.omit(params, 'vaultAddress')
|
2648
|
+
request['vaultAddress'] = vaultAddress
|
2649
|
+
response = self.privatePostExchange(request)
|
1794
2650
|
#
|
1795
2651
|
# {
|
1796
2652
|
# 'response': {
|
@@ -1799,58 +2655,121 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1799
2655
|
# 'status': 'ok'
|
1800
2656
|
# }
|
1801
2657
|
#
|
1802
|
-
return response
|
1803
|
-
|
1804
|
-
|
1805
|
-
|
2658
|
+
return self.extend(self.parse_margin_modification(response, market), {
|
2659
|
+
'code': self.safe_string(response, 'status'),
|
2660
|
+
})
|
2661
|
+
|
2662
|
+
def parse_margin_modification(self, data: dict, market: Market = None) -> MarginModification:
|
2663
|
+
#
|
2664
|
+
# {
|
2665
|
+
# 'type': 'default'
|
2666
|
+
# }
|
2667
|
+
#
|
2668
|
+
return {
|
2669
|
+
'info': data,
|
2670
|
+
'symbol': self.safe_symbol(None, market),
|
2671
|
+
'type': None,
|
2672
|
+
'marginMode': 'isolated',
|
2673
|
+
'amount': None,
|
2674
|
+
'total': None,
|
2675
|
+
'code': self.safe_string(market, 'settle'),
|
2676
|
+
'status': None,
|
2677
|
+
'timestamp': None,
|
2678
|
+
'datetime': None,
|
2679
|
+
}
|
1806
2680
|
|
1807
2681
|
def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
|
1808
2682
|
"""
|
1809
2683
|
transfer currency internally between wallets on the same account
|
1810
|
-
|
2684
|
+
|
2685
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#l1-usdc-transfer
|
2686
|
+
|
1811
2687
|
:param str code: unified currency code
|
1812
2688
|
:param float amount: amount to transfer
|
1813
|
-
:param str fromAccount: account to transfer from
|
1814
|
-
:param str toAccount: account to transfer to
|
2689
|
+
:param str fromAccount: account to transfer from *spot, swap*
|
2690
|
+
:param str toAccount: account to transfer to *swap, spot or address*
|
1815
2691
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2692
|
+
:param str [params.vaultAddress]: the vault address for order
|
1816
2693
|
:returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
|
1817
2694
|
"""
|
1818
2695
|
self.check_required_credentials()
|
1819
2696
|
self.load_markets()
|
2697
|
+
isSandboxMode = self.safe_bool(self.options, 'sandboxMode')
|
2698
|
+
nonce = self.milliseconds()
|
2699
|
+
if self.in_array(fromAccount, ['spot', 'swap', 'perp']):
|
2700
|
+
# handle swap <> spot account transfer
|
2701
|
+
if not self.in_array(toAccount, ['spot', 'swap', 'perp']):
|
2702
|
+
raise NotSupported(self.id + 'transfer() only support spot <> swap transfer')
|
2703
|
+
strAmount = self.number_to_string(amount)
|
2704
|
+
vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
|
2705
|
+
params = self.omit(params, 'vaultAddress')
|
2706
|
+
if vaultAddress is not None:
|
2707
|
+
strAmount = strAmount + ' subaccount:' + vaultAddress
|
2708
|
+
toPerp = (toAccount == 'perp') or (toAccount == 'swap')
|
2709
|
+
transferPayload: dict = {
|
2710
|
+
'hyperliquidChain': 'Testnet' if isSandboxMode else 'Mainnet',
|
2711
|
+
'amount': strAmount,
|
2712
|
+
'toPerp': toPerp,
|
2713
|
+
'nonce': nonce,
|
2714
|
+
}
|
2715
|
+
transferSig = self.build_usd_class_send_sig(transferPayload)
|
2716
|
+
transferRequest: dict = {
|
2717
|
+
'action': {
|
2718
|
+
'hyperliquidChain': transferPayload['hyperliquidChain'],
|
2719
|
+
'signatureChainId': '0x66eee',
|
2720
|
+
'type': 'usdClassTransfer',
|
2721
|
+
'amount': strAmount,
|
2722
|
+
'toPerp': toPerp,
|
2723
|
+
'nonce': nonce,
|
2724
|
+
},
|
2725
|
+
'nonce': nonce,
|
2726
|
+
'signature': transferSig,
|
2727
|
+
}
|
2728
|
+
if vaultAddress is not None:
|
2729
|
+
transferRequest['vaultAddress'] = vaultAddress
|
2730
|
+
transferResponse = self.privatePostExchange(transferRequest)
|
2731
|
+
return transferResponse
|
2732
|
+
# handle sub-account/different account transfer
|
1820
2733
|
self.check_address(toAccount)
|
1821
2734
|
if code is not None:
|
1822
2735
|
code = code.upper()
|
1823
2736
|
if code != 'USDC':
|
1824
|
-
raise NotSupported(self.id + '
|
1825
|
-
|
1826
|
-
|
1827
|
-
payload = {
|
2737
|
+
raise NotSupported(self.id + 'transfer() only support USDC')
|
2738
|
+
payload: dict = {
|
2739
|
+
'hyperliquidChain': 'Testnet' if isSandboxMode else 'Mainnet',
|
1828
2740
|
'destination': toAccount,
|
1829
|
-
'amount':
|
2741
|
+
'amount': self.number_to_string(amount),
|
1830
2742
|
'time': nonce,
|
1831
2743
|
}
|
1832
|
-
sig = self.
|
1833
|
-
request = {
|
2744
|
+
sig = self.build_usd_send_sig(payload)
|
2745
|
+
request: dict = {
|
1834
2746
|
'action': {
|
1835
|
-
'
|
1836
|
-
'
|
1837
|
-
'
|
2747
|
+
'hyperliquidChain': payload['hyperliquidChain'],
|
2748
|
+
'signatureChainId': '0x66eee', # check self out
|
2749
|
+
'destination': toAccount,
|
2750
|
+
'amount': str(amount),
|
2751
|
+
'time': nonce,
|
2752
|
+
'type': 'usdSend',
|
1838
2753
|
},
|
1839
2754
|
'nonce': nonce,
|
1840
2755
|
'signature': sig,
|
1841
2756
|
}
|
1842
|
-
response = self.privatePostExchange(
|
2757
|
+
response = self.privatePostExchange(request)
|
1843
2758
|
return response
|
1844
2759
|
|
1845
|
-
def withdraw(self, code: str, amount, address, tag=None, params={}):
|
2760
|
+
def withdraw(self, code: str, amount: float, address: str, tag=None, params={}) -> Transaction:
|
1846
2761
|
"""
|
1847
2762
|
make a withdrawal(only support USDC)
|
1848
|
-
|
2763
|
+
|
2764
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#initiate-a-withdrawal-request
|
2765
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#deposit-or-withdraw-from-a-vault
|
2766
|
+
|
1849
2767
|
:param str code: unified currency code
|
1850
2768
|
:param float amount: the amount to withdraw
|
1851
2769
|
:param str address: the address to withdraw to
|
1852
2770
|
:param str tag:
|
1853
2771
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2772
|
+
:param str [params.vaultAddress]: vault address withdraw from
|
1854
2773
|
:returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
|
1855
2774
|
"""
|
1856
2775
|
self.check_required_credentials()
|
@@ -1860,38 +2779,457 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1860
2779
|
code = code.upper()
|
1861
2780
|
if code != 'USDC':
|
1862
2781
|
raise NotSupported(self.id + 'withdraw() only support USDC')
|
1863
|
-
|
2782
|
+
vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
|
2783
|
+
params = self.omit(params, 'vaultAddress')
|
1864
2784
|
nonce = self.milliseconds()
|
1865
|
-
|
1866
|
-
|
1867
|
-
|
1868
|
-
|
1869
|
-
|
1870
|
-
|
1871
|
-
|
1872
|
-
|
1873
|
-
|
1874
|
-
|
1875
|
-
|
1876
|
-
|
2785
|
+
action: dict = {}
|
2786
|
+
sig = None
|
2787
|
+
if vaultAddress is not None:
|
2788
|
+
action = {
|
2789
|
+
'type': 'vaultTransfer',
|
2790
|
+
'vaultAddress': '0x' + vaultAddress,
|
2791
|
+
'isDeposit': False,
|
2792
|
+
'usd': amount,
|
2793
|
+
}
|
2794
|
+
sig = self.sign_l1_action(action, nonce)
|
2795
|
+
else:
|
2796
|
+
isSandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
|
2797
|
+
payload: dict = {
|
2798
|
+
'hyperliquidChain': 'Testnet' if isSandboxMode else 'Mainnet',
|
2799
|
+
'destination': address,
|
2800
|
+
'amount': str(amount),
|
2801
|
+
'time': nonce,
|
2802
|
+
}
|
2803
|
+
sig = self.build_withdraw_sig(payload)
|
2804
|
+
action = {
|
2805
|
+
'hyperliquidChain': payload['hyperliquidChain'],
|
2806
|
+
'signatureChainId': '0x66eee', # check self out
|
2807
|
+
'destination': address,
|
2808
|
+
'amount': str(amount),
|
2809
|
+
'time': nonce,
|
2810
|
+
'type': 'withdraw3',
|
2811
|
+
}
|
2812
|
+
request: dict = {
|
2813
|
+
'action': action,
|
1877
2814
|
'nonce': nonce,
|
1878
2815
|
'signature': sig,
|
1879
2816
|
}
|
1880
|
-
response = self.privatePostExchange(
|
1881
|
-
return response
|
2817
|
+
response = self.privatePostExchange(request)
|
2818
|
+
return self.parse_transaction(response)
|
2819
|
+
|
2820
|
+
def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
|
2821
|
+
#
|
2822
|
+
# {status: 'ok', response: {type: 'default'}}
|
2823
|
+
#
|
2824
|
+
# fetchDeposits / fetchWithdrawals
|
2825
|
+
# {
|
2826
|
+
# "time":1724762307531,
|
2827
|
+
# "hash":"0x620a234a7e0eb7930575040f59482a01050058b0802163b4767bfd9033e77781",
|
2828
|
+
# "delta":{
|
2829
|
+
# "type":"accountClassTransfer",
|
2830
|
+
# "usdc":"50.0",
|
2831
|
+
# "toPerp":false
|
2832
|
+
# }
|
2833
|
+
# }
|
2834
|
+
#
|
2835
|
+
timestamp = self.safe_integer(transaction, 'time')
|
2836
|
+
delta = self.safe_dict(transaction, 'delta', {})
|
2837
|
+
fee = None
|
2838
|
+
feeCost = self.safe_integer(delta, 'fee')
|
2839
|
+
if feeCost is not None:
|
2840
|
+
fee = {
|
2841
|
+
'currency': 'USDC',
|
2842
|
+
'cost': feeCost,
|
2843
|
+
}
|
2844
|
+
internal = None
|
2845
|
+
type = self.safe_string(delta, 'type')
|
2846
|
+
if type is not None:
|
2847
|
+
internal = (type == 'internalTransfer')
|
2848
|
+
return {
|
2849
|
+
'info': transaction,
|
2850
|
+
'id': None,
|
2851
|
+
'txid': self.safe_string(transaction, 'hash'),
|
2852
|
+
'timestamp': timestamp,
|
2853
|
+
'datetime': self.iso8601(timestamp),
|
2854
|
+
'network': None,
|
2855
|
+
'address': None,
|
2856
|
+
'addressTo': self.safe_string(delta, 'destination'),
|
2857
|
+
'addressFrom': self.safe_string(delta, 'user'),
|
2858
|
+
'tag': None,
|
2859
|
+
'tagTo': None,
|
2860
|
+
'tagFrom': None,
|
2861
|
+
'type': None,
|
2862
|
+
'amount': self.safe_integer(delta, 'usdc'),
|
2863
|
+
'currency': None,
|
2864
|
+
'status': self.safe_string(transaction, 'status'),
|
2865
|
+
'updated': None,
|
2866
|
+
'comment': None,
|
2867
|
+
'internal': internal,
|
2868
|
+
'fee': fee,
|
2869
|
+
}
|
2870
|
+
|
2871
|
+
def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
|
2872
|
+
"""
|
2873
|
+
fetch the trading fees for a market
|
2874
|
+
:param str symbol: unified market symbol
|
2875
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2876
|
+
:param str [params.user]: user address, will default to self.walletAddress if not provided
|
2877
|
+
:returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
|
2878
|
+
"""
|
2879
|
+
self.load_markets()
|
2880
|
+
userAddress = None
|
2881
|
+
userAddress, params = self.handle_public_address('fetchTradingFee', params)
|
2882
|
+
market = self.market(symbol)
|
2883
|
+
request: dict = {
|
2884
|
+
'type': 'userFees',
|
2885
|
+
'user': userAddress,
|
2886
|
+
}
|
2887
|
+
response = self.publicPostInfo(self.extend(request, params))
|
2888
|
+
#
|
2889
|
+
# {
|
2890
|
+
# "dailyUserVlm": [
|
2891
|
+
# {
|
2892
|
+
# "date": "2024-07-08",
|
2893
|
+
# "userCross": "0.0",
|
2894
|
+
# "userAdd": "0.0",
|
2895
|
+
# "exchange": "90597185.23639999"
|
2896
|
+
# }
|
2897
|
+
# ],
|
2898
|
+
# "feeSchedule": {
|
2899
|
+
# "cross": "0.00035",
|
2900
|
+
# "add": "0.0001",
|
2901
|
+
# "tiers": {
|
2902
|
+
# "vip": [
|
2903
|
+
# {
|
2904
|
+
# "ntlCutoff": "5000000.0",
|
2905
|
+
# "cross": "0.0003",
|
2906
|
+
# "add": "0.00005"
|
2907
|
+
# }
|
2908
|
+
# ],
|
2909
|
+
# "mm": [
|
2910
|
+
# {
|
2911
|
+
# "makerFractionCutoff": "0.005",
|
2912
|
+
# "add": "-0.00001"
|
2913
|
+
# }
|
2914
|
+
# ]
|
2915
|
+
# },
|
2916
|
+
# "referralDiscount": "0.04"
|
2917
|
+
# },
|
2918
|
+
# "userCrossRate": "0.00035",
|
2919
|
+
# "userAddRate": "0.0001",
|
2920
|
+
# "activeReferralDiscount": "0.0"
|
2921
|
+
# }
|
2922
|
+
#
|
2923
|
+
data: dict = {
|
2924
|
+
'userCrossRate': self.safe_string(response, 'userCrossRate'),
|
2925
|
+
'userAddRate': self.safe_string(response, 'userAddRate'),
|
2926
|
+
}
|
2927
|
+
return self.parse_trading_fee(data, market)
|
2928
|
+
|
2929
|
+
def parse_trading_fee(self, fee: dict, market: Market = None) -> TradingFeeInterface:
|
2930
|
+
#
|
2931
|
+
# {
|
2932
|
+
# "dailyUserVlm": [
|
2933
|
+
# {
|
2934
|
+
# "date": "2024-07-08",
|
2935
|
+
# "userCross": "0.0",
|
2936
|
+
# "userAdd": "0.0",
|
2937
|
+
# "exchange": "90597185.23639999"
|
2938
|
+
# }
|
2939
|
+
# ],
|
2940
|
+
# "feeSchedule": {
|
2941
|
+
# "cross": "0.00035",
|
2942
|
+
# "add": "0.0001",
|
2943
|
+
# "tiers": {
|
2944
|
+
# "vip": [
|
2945
|
+
# {
|
2946
|
+
# "ntlCutoff": "5000000.0",
|
2947
|
+
# "cross": "0.0003",
|
2948
|
+
# "add": "0.00005"
|
2949
|
+
# }
|
2950
|
+
# ],
|
2951
|
+
# "mm": [
|
2952
|
+
# {
|
2953
|
+
# "makerFractionCutoff": "0.005",
|
2954
|
+
# "add": "-0.00001"
|
2955
|
+
# }
|
2956
|
+
# ]
|
2957
|
+
# },
|
2958
|
+
# "referralDiscount": "0.04"
|
2959
|
+
# },
|
2960
|
+
# "userCrossRate": "0.00035",
|
2961
|
+
# "userAddRate": "0.0001",
|
2962
|
+
# "activeReferralDiscount": "0.0"
|
2963
|
+
# }
|
2964
|
+
#
|
2965
|
+
symbol = self.safe_symbol(None, market)
|
2966
|
+
return {
|
2967
|
+
'info': fee,
|
2968
|
+
'symbol': symbol,
|
2969
|
+
'maker': self.safe_number(fee, 'userAddRate'),
|
2970
|
+
'taker': self.safe_number(fee, 'userCrossRate'),
|
2971
|
+
'percentage': None,
|
2972
|
+
'tierBased': None,
|
2973
|
+
}
|
2974
|
+
|
2975
|
+
def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LedgerEntry]:
|
2976
|
+
"""
|
2977
|
+
fetch the history of changes, actions done by the user or operations that altered the balance of the user
|
2978
|
+
:param str [code]: unified currency code
|
2979
|
+
:param int [since]: timestamp in ms of the earliest ledger entry
|
2980
|
+
:param int [limit]: max number of ledger entries to return
|
2981
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2982
|
+
:param int [params.until]: timestamp in ms of the latest ledger entry
|
2983
|
+
:returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger>`
|
2984
|
+
"""
|
2985
|
+
self.load_markets()
|
2986
|
+
userAddress = None
|
2987
|
+
userAddress, params = self.handle_public_address('fetchLedger', params)
|
2988
|
+
request: dict = {
|
2989
|
+
'type': 'userNonFundingLedgerUpdates',
|
2990
|
+
'user': userAddress,
|
2991
|
+
}
|
2992
|
+
if since is not None:
|
2993
|
+
request['startTime'] = since
|
2994
|
+
until = self.safe_integer(params, 'until')
|
2995
|
+
if until is not None:
|
2996
|
+
request['endTime'] = until
|
2997
|
+
params = self.omit(params, ['until'])
|
2998
|
+
response = self.publicPostInfo(self.extend(request, params))
|
2999
|
+
#
|
3000
|
+
# [
|
3001
|
+
# {
|
3002
|
+
# "time":1724762307531,
|
3003
|
+
# "hash":"0x620a234a7e0eb7930575040f59482a01050058b0802163b4767bfd9033e77781",
|
3004
|
+
# "delta":{
|
3005
|
+
# "type":"accountClassTransfer",
|
3006
|
+
# "usdc":"50.0",
|
3007
|
+
# "toPerp":false
|
3008
|
+
# }
|
3009
|
+
# }
|
3010
|
+
# ]
|
3011
|
+
#
|
3012
|
+
return self.parse_ledger(response, None, since, limit)
|
3013
|
+
|
3014
|
+
def parse_ledger_entry(self, item: dict, currency: Currency = None) -> LedgerEntry:
|
3015
|
+
#
|
3016
|
+
# {
|
3017
|
+
# "time":1724762307531,
|
3018
|
+
# "hash":"0x620a234a7e0eb7930575040f59482a01050058b0802163b4767bfd9033e77781",
|
3019
|
+
# "delta":{
|
3020
|
+
# "type":"accountClassTransfer",
|
3021
|
+
# "usdc":"50.0",
|
3022
|
+
# "toPerp":false
|
3023
|
+
# }
|
3024
|
+
# }
|
3025
|
+
#
|
3026
|
+
timestamp = self.safe_integer(item, 'time')
|
3027
|
+
delta = self.safe_dict(item, 'delta', {})
|
3028
|
+
fee = None
|
3029
|
+
feeCost = self.safe_integer(delta, 'fee')
|
3030
|
+
if feeCost is not None:
|
3031
|
+
fee = {
|
3032
|
+
'currency': 'USDC',
|
3033
|
+
'cost': feeCost,
|
3034
|
+
}
|
3035
|
+
type = self.safe_string(delta, 'type')
|
3036
|
+
amount = self.safe_string(delta, 'usdc')
|
3037
|
+
return self.safe_ledger_entry({
|
3038
|
+
'info': item,
|
3039
|
+
'id': self.safe_string(item, 'hash'),
|
3040
|
+
'direction': None,
|
3041
|
+
'account': None,
|
3042
|
+
'referenceAccount': self.safe_string(delta, 'user'),
|
3043
|
+
'referenceId': self.safe_string(item, 'hash'),
|
3044
|
+
'type': self.parse_ledger_entry_type(type),
|
3045
|
+
'currency': None,
|
3046
|
+
'amount': self.parse_number(amount),
|
3047
|
+
'timestamp': timestamp,
|
3048
|
+
'datetime': self.iso8601(timestamp),
|
3049
|
+
'before': None,
|
3050
|
+
'after': None,
|
3051
|
+
'status': None,
|
3052
|
+
'fee': fee,
|
3053
|
+
}, currency)
|
3054
|
+
|
3055
|
+
def parse_ledger_entry_type(self, type):
|
3056
|
+
ledgerType: dict = {
|
3057
|
+
'internalTransfer': 'transfer',
|
3058
|
+
'accountClassTransfer': 'transfer',
|
3059
|
+
}
|
3060
|
+
return self.safe_string(ledgerType, type, type)
|
3061
|
+
|
3062
|
+
def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
|
3063
|
+
"""
|
3064
|
+
fetch all deposits made to an account
|
3065
|
+
:param str code: unified currency code
|
3066
|
+
:param int [since]: the earliest time in ms to fetch deposits for
|
3067
|
+
:param int [limit]: the maximum number of deposits structures to retrieve
|
3068
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
3069
|
+
:param int [params.until]: the latest time in ms to fetch withdrawals for
|
3070
|
+
:returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
|
3071
|
+
"""
|
3072
|
+
self.load_markets()
|
3073
|
+
userAddress = None
|
3074
|
+
userAddress, params = self.handle_public_address('fetchDepositsWithdrawals', params)
|
3075
|
+
request: dict = {
|
3076
|
+
'type': 'userNonFundingLedgerUpdates',
|
3077
|
+
'user': userAddress,
|
3078
|
+
}
|
3079
|
+
if since is not None:
|
3080
|
+
request['startTime'] = since
|
3081
|
+
until = self.safe_integer(params, 'until')
|
3082
|
+
if until is not None:
|
3083
|
+
request['endTime'] = until
|
3084
|
+
params = self.omit(params, ['until'])
|
3085
|
+
response = self.publicPostInfo(self.extend(request, params))
|
3086
|
+
#
|
3087
|
+
# [
|
3088
|
+
# {
|
3089
|
+
# "time":1724762307531,
|
3090
|
+
# "hash":"0x620a234a7e0eb7930575040f59482a01050058b0802163b4767bfd9033e77781",
|
3091
|
+
# "delta":{
|
3092
|
+
# "type":"accountClassTransfer",
|
3093
|
+
# "usdc":"50.0",
|
3094
|
+
# "toPerp":false
|
3095
|
+
# }
|
3096
|
+
# }
|
3097
|
+
# ]
|
3098
|
+
#
|
3099
|
+
records = self.extract_type_from_delta(response)
|
3100
|
+
deposits = self.filter_by_array(records, 'type', ['deposit'], False)
|
3101
|
+
return self.parse_transactions(deposits, None, since, limit)
|
3102
|
+
|
3103
|
+
def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
|
3104
|
+
"""
|
3105
|
+
fetch all withdrawals made from an account
|
3106
|
+
:param str code: unified currency code
|
3107
|
+
:param int [since]: the earliest time in ms to fetch withdrawals for
|
3108
|
+
:param int [limit]: the maximum number of withdrawals structures to retrieve
|
3109
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
3110
|
+
:param int [params.until]: the latest time in ms to fetch withdrawals for
|
3111
|
+
:returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
|
3112
|
+
"""
|
3113
|
+
self.load_markets()
|
3114
|
+
userAddress = None
|
3115
|
+
userAddress, params = self.handle_public_address('fetchDepositsWithdrawals', params)
|
3116
|
+
request: dict = {
|
3117
|
+
'type': 'userNonFundingLedgerUpdates',
|
3118
|
+
'user': userAddress,
|
3119
|
+
}
|
3120
|
+
if since is not None:
|
3121
|
+
request['startTime'] = since
|
3122
|
+
until = self.safe_integer(params, 'until')
|
3123
|
+
if until is not None:
|
3124
|
+
request['endTime'] = until
|
3125
|
+
params = self.omit(params, ['until'])
|
3126
|
+
response = self.publicPostInfo(self.extend(request, params))
|
3127
|
+
#
|
3128
|
+
# [
|
3129
|
+
# {
|
3130
|
+
# "time":1724762307531,
|
3131
|
+
# "hash":"0x620a234a7e0eb7930575040f59482a01050058b0802163b4767bfd9033e77781",
|
3132
|
+
# "delta":{
|
3133
|
+
# "type":"accountClassTransfer",
|
3134
|
+
# "usdc":"50.0",
|
3135
|
+
# "toPerp":false
|
3136
|
+
# }
|
3137
|
+
# }
|
3138
|
+
# ]
|
3139
|
+
#
|
3140
|
+
records = self.extract_type_from_delta(response)
|
3141
|
+
withdrawals = self.filter_by_array(records, 'type', ['withdraw'], False)
|
3142
|
+
return self.parse_transactions(withdrawals, None, since, limit)
|
3143
|
+
|
3144
|
+
def fetch_open_interests(self, symbols: Strings = None, params={}):
|
3145
|
+
"""
|
3146
|
+
Retrieves the open interest for a list of symbols
|
3147
|
+
:param str[] [symbols]: Unified CCXT market symbol
|
3148
|
+
:param dict [params]: exchange specific parameters
|
3149
|
+
:returns dict} an open interest structure{@link https://docs.ccxt.com/#/?id=open-interest-structure:
|
3150
|
+
"""
|
3151
|
+
self.load_markets()
|
3152
|
+
symbols = self.market_symbols(symbols)
|
3153
|
+
swapMarkets = self.fetch_swap_markets()
|
3154
|
+
return self.parse_open_interests(swapMarkets, symbols)
|
3155
|
+
|
3156
|
+
def fetch_open_interest(self, symbol: str, params={}):
|
3157
|
+
"""
|
3158
|
+
retrieves the open interest of a contract trading pair
|
3159
|
+
:param str symbol: unified CCXT market symbol
|
3160
|
+
:param dict [params]: exchange specific parameters
|
3161
|
+
:returns dict: an `open interest structure <https://docs.ccxt.com/#/?id=open-interest-structure>`
|
3162
|
+
"""
|
3163
|
+
symbol = self.symbol(symbol)
|
3164
|
+
self.load_markets()
|
3165
|
+
ois = self.fetch_open_interests([symbol], params)
|
3166
|
+
return ois[symbol]
|
3167
|
+
|
3168
|
+
def parse_open_interest(self, interest, market: Market = None):
|
3169
|
+
#
|
3170
|
+
# {
|
3171
|
+
# szDecimals: '2',
|
3172
|
+
# name: 'HYPE',
|
3173
|
+
# maxLeverage: '3',
|
3174
|
+
# funding: '0.00014735',
|
3175
|
+
# openInterest: '14677900.74',
|
3176
|
+
# prevDayPx: '26.145',
|
3177
|
+
# dayNtlVlm: '299643445.12560016',
|
3178
|
+
# premium: '0.00081613',
|
3179
|
+
# oraclePx: '27.569',
|
3180
|
+
# markPx: '27.63',
|
3181
|
+
# midPx: '27.599',
|
3182
|
+
# impactPxs: ['27.5915', '27.6319'],
|
3183
|
+
# dayBaseVlm: '10790652.83',
|
3184
|
+
# baseId: 159
|
3185
|
+
# }
|
3186
|
+
#
|
3187
|
+
interest = self.safe_dict(interest, 'info', {})
|
3188
|
+
coin = self.safe_string(interest, 'name')
|
3189
|
+
marketId = None
|
3190
|
+
if coin is not None:
|
3191
|
+
marketId = self.coin_to_market_id(coin)
|
3192
|
+
return self.safe_open_interest({
|
3193
|
+
'symbol': self.safe_symbol(marketId),
|
3194
|
+
'openInterestAmount': self.safe_number(interest, 'openInterest'),
|
3195
|
+
'openInterestValue': None,
|
3196
|
+
'timestamp': None,
|
3197
|
+
'datetime': None,
|
3198
|
+
'info': interest,
|
3199
|
+
}, market)
|
3200
|
+
|
3201
|
+
def extract_type_from_delta(self, data=[]):
|
3202
|
+
records = []
|
3203
|
+
for i in range(0, len(data)):
|
3204
|
+
record = data[i]
|
3205
|
+
record['type'] = record['delta']['type']
|
3206
|
+
records.append(record)
|
3207
|
+
return records
|
3208
|
+
|
3209
|
+
def format_vault_address(self, address: Str = None):
|
3210
|
+
if address is None:
|
3211
|
+
return None
|
3212
|
+
if address.startswith('0x'):
|
3213
|
+
return address.replace('0x', '')
|
3214
|
+
return address
|
1882
3215
|
|
1883
3216
|
def handle_public_address(self, methodName: str, params: dict):
|
1884
3217
|
userAux = None
|
1885
3218
|
userAux, params = self.handle_option_and_params(params, methodName, 'user')
|
1886
3219
|
user = userAux
|
1887
3220
|
user, params = self.handle_option_and_params(params, methodName, 'address', userAux)
|
1888
|
-
if user is not None:
|
3221
|
+
if (user is not None) and (user != ''):
|
1889
3222
|
return [user, params]
|
1890
|
-
if self.walletAddress is not None:
|
3223
|
+
if (self.walletAddress is not None) and (self.walletAddress != ''):
|
1891
3224
|
return [self.walletAddress, params]
|
1892
3225
|
raise ArgumentsRequired(self.id + ' ' + methodName + '() requires a user parameter inside \'params\' or the wallet address set')
|
1893
3226
|
|
1894
|
-
def
|
3227
|
+
def coin_to_market_id(self, coin: Str):
|
3228
|
+
if coin.find('/') > -1 or coin.find('@') > -1:
|
3229
|
+
return coin # spot
|
3230
|
+
return coin + '/USDC:USDC'
|
3231
|
+
|
3232
|
+
def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
|
1895
3233
|
if not response:
|
1896
3234
|
return None # fallback to default error handler
|
1897
3235
|
# {"status":"err","response":"User or API Wallet 0xb8a6f8b26223de27c31938d56e470a5b832703a5 does not exist."}
|
@@ -1928,3 +3266,29 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1928
3266
|
}
|
1929
3267
|
body = self.json(params)
|
1930
3268
|
return {'url': url, 'method': method, 'body': body, 'headers': headers}
|
3269
|
+
|
3270
|
+
def calculate_rate_limiter_cost(self, api, method, path, params, config={}):
|
3271
|
+
if ('byType' in config) and ('type' in params):
|
3272
|
+
type = params['type']
|
3273
|
+
byType = config['byType']
|
3274
|
+
if type in byType:
|
3275
|
+
return byType[type]
|
3276
|
+
return self.safe_value(config, 'cost', 1)
|
3277
|
+
|
3278
|
+
def parse_create_order_args(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
3279
|
+
market = self.market(symbol)
|
3280
|
+
vaultAddress = self.safe_string(params, 'vaultAddress')
|
3281
|
+
params = self.omit(params, 'vaultAddress')
|
3282
|
+
symbol = market['symbol']
|
3283
|
+
order = {
|
3284
|
+
'symbol': symbol,
|
3285
|
+
'type': type,
|
3286
|
+
'side': side,
|
3287
|
+
'amount': amount,
|
3288
|
+
'price': price,
|
3289
|
+
'params': params,
|
3290
|
+
}
|
3291
|
+
globalParams = {}
|
3292
|
+
if vaultAddress is not None:
|
3293
|
+
globalParams['vaultAddress'] = vaultAddress
|
3294
|
+
return [order, globalParams]
|