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