ccxt 4.2.59 → 4.2.61
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.
- package/README.md +103 -102
- package/build.sh +2 -2
- package/dist/ccxt.browser.js +11853 -3790
- package/dist/ccxt.browser.min.js +7 -7
- package/dist/cjs/ccxt.js +4 -1
- package/dist/cjs/src/abstract/hyperliquid.js +9 -0
- package/dist/cjs/src/ascendex.js +10 -12
- package/dist/cjs/src/base/Exchange.js +22 -1
- package/dist/cjs/src/base/functions/encode.js +5 -0
- package/dist/cjs/src/base/functions.js +1 -0
- package/dist/cjs/src/bingx.js +38 -0
- package/dist/cjs/src/bitfinex2.js +20 -3
- package/dist/cjs/src/bitget.js +9 -2
- package/dist/cjs/src/bitmart.js +41 -23
- package/dist/cjs/src/blofin.js +59 -1
- package/dist/cjs/src/coinbase.js +108 -103
- package/dist/cjs/src/coinex.js +61 -1
- package/dist/cjs/src/hitbtc.js +1 -1
- package/dist/cjs/src/htx.js +4 -1
- package/dist/cjs/src/hyperliquid.js +2035 -0
- package/dist/cjs/src/kraken.js +50 -41
- package/dist/cjs/src/krakenfutures.js +28 -0
- package/dist/cjs/src/kucoinfutures.js +3 -2
- package/dist/cjs/src/okx.js +1 -1
- package/dist/cjs/src/phemex.js +2 -2
- package/dist/cjs/src/pro/binance.js +16 -3
- package/dist/cjs/src/pro/bingx.js +1 -0
- package/dist/cjs/src/static_dependencies/ethers/abi-coder.js +158 -0
- package/dist/cjs/src/static_dependencies/ethers/address/address.js +144 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/abstract-coder.js +407 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/address.js +45 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/anonymous.js +28 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/array.js +176 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/boolean.js +27 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/bytes.js +52 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/fixed-bytes.js +45 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/null.js +30 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/number.js +60 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/string.js +27 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/tuple.js +68 -0
- package/dist/cjs/src/static_dependencies/ethers/fragments.js +614 -0
- package/dist/cjs/src/static_dependencies/ethers/hash/typed-data.js +492 -0
- package/dist/cjs/src/static_dependencies/ethers/index.js +35 -0
- package/dist/cjs/src/static_dependencies/ethers/interface.js +44 -0
- package/dist/cjs/src/static_dependencies/ethers/typed.js +618 -0
- package/dist/cjs/src/static_dependencies/ethers/utils/base58.js +20 -0
- package/dist/cjs/src/static_dependencies/ethers/utils/data.js +134 -0
- package/dist/cjs/src/static_dependencies/ethers/utils/errors.js +228 -0
- package/dist/cjs/src/static_dependencies/ethers/utils/events.js +13 -0
- package/dist/cjs/src/static_dependencies/ethers/utils/fixednumber.js +29 -0
- package/dist/cjs/src/static_dependencies/ethers/utils/index.js +53 -0
- package/dist/cjs/src/static_dependencies/ethers/utils/maths.js +231 -0
- package/dist/cjs/src/static_dependencies/ethers/utils/properties.js +47 -0
- package/dist/cjs/src/static_dependencies/ethers/utils/utf8.js +218 -0
- package/dist/cjs/src/static_dependencies/messagepack/msgpack.js +292 -0
- package/dist/cjs/src/tokocrypto.js +22 -2
- package/dist/cjs/src/wazirx.js +314 -4
- package/dist/cjs/src/woo.js +157 -77
- package/js/ccxt.d.ts +5 -2
- package/js/ccxt.js +4 -2
- package/js/src/abstract/blofin.d.ts +1 -0
- package/js/src/abstract/coinbase.d.ts +3 -3
- package/js/src/abstract/hyperliquid.d.ts +9 -0
- package/js/src/abstract/hyperliquid.js +11 -0
- package/js/src/abstract/wazirx.d.ts +5 -0
- package/js/src/ascendex.d.ts +2 -2
- package/js/src/ascendex.js +10 -12
- package/js/src/base/Exchange.d.ts +4 -0
- package/js/src/base/Exchange.js +13 -1
- package/js/src/base/functions/encode.d.ts +2 -1
- package/js/src/base/functions/encode.js +5 -1
- package/js/src/bingx.d.ts +3 -1
- package/js/src/bingx.js +38 -0
- package/js/src/bitfinex2.js +20 -3
- package/js/src/bitget.js +9 -2
- package/js/src/bitmart.d.ts +9 -2
- package/js/src/bitmart.js +41 -23
- package/js/src/blofin.d.ts +2 -1
- package/js/src/blofin.js +59 -1
- package/js/src/coinbase.js +108 -103
- package/js/src/coinex.d.ts +3 -1
- package/js/src/coinex.js +61 -1
- package/js/src/hitbtc.js +1 -1
- package/js/src/htx.js +4 -1
- package/js/src/hyperliquid.d.ts +83 -0
- package/js/src/hyperliquid.js +2036 -0
- package/js/src/kraken.js +50 -41
- package/js/src/krakenfutures.d.ts +2 -1
- package/js/src/krakenfutures.js +28 -0
- package/js/src/kucoinfutures.js +3 -2
- package/js/src/okx.js +1 -1
- package/js/src/phemex.js +2 -2
- package/js/src/pro/binance.js +16 -3
- package/js/src/pro/bingx.js +1 -0
- package/js/src/pro/deribit.d.ts +1 -1
- package/js/src/static_dependencies/ethers/abi-coder.d.ts +50 -0
- package/js/src/static_dependencies/ethers/abi-coder.js +148 -0
- package/js/src/static_dependencies/ethers/address/address.d.ts +55 -0
- package/js/src/static_dependencies/ethers/address/address.js +162 -0
- package/js/src/static_dependencies/ethers/address/checks.d.ts +80 -0
- package/js/src/static_dependencies/ethers/address/checks.js +119 -0
- package/js/src/static_dependencies/ethers/address/contract-address.d.ts +47 -0
- package/js/src/static_dependencies/ethers/address/contract-address.js +73 -0
- package/js/src/static_dependencies/ethers/address/index.d.ts +48 -0
- package/js/src/static_dependencies/ethers/address/index.js +24 -0
- package/js/src/static_dependencies/ethers/bytes32.d.ts +14 -0
- package/js/src/static_dependencies/ethers/bytes32.js +45 -0
- package/js/src/static_dependencies/ethers/coders/abstract-coder.d.ts +120 -0
- package/js/src/static_dependencies/ethers/coders/abstract-coder.js +424 -0
- package/js/src/static_dependencies/ethers/coders/address.d.ts +12 -0
- package/js/src/static_dependencies/ethers/coders/address.js +34 -0
- package/js/src/static_dependencies/ethers/coders/anonymous.d.ts +14 -0
- package/js/src/static_dependencies/ethers/coders/anonymous.js +27 -0
- package/js/src/static_dependencies/ethers/coders/array.d.ts +24 -0
- package/js/src/static_dependencies/ethers/coders/array.js +162 -0
- package/js/src/static_dependencies/ethers/coders/boolean.d.ts +12 -0
- package/js/src/static_dependencies/ethers/coders/boolean.js +26 -0
- package/js/src/static_dependencies/ethers/coders/bytes.d.ts +18 -0
- package/js/src/static_dependencies/ethers/coders/bytes.js +39 -0
- package/js/src/static_dependencies/ethers/coders/fixed-bytes.d.ts +14 -0
- package/js/src/static_dependencies/ethers/coders/fixed-bytes.js +32 -0
- package/js/src/static_dependencies/ethers/coders/null.d.ts +11 -0
- package/js/src/static_dependencies/ethers/coders/null.js +29 -0
- package/js/src/static_dependencies/ethers/coders/number.d.ts +15 -0
- package/js/src/static_dependencies/ethers/coders/number.js +48 -0
- package/js/src/static_dependencies/ethers/coders/string.d.ts +12 -0
- package/js/src/static_dependencies/ethers/coders/string.js +26 -0
- package/js/src/static_dependencies/ethers/coders/tuple.d.ts +15 -0
- package/js/src/static_dependencies/ethers/coders/tuple.js +67 -0
- package/js/src/static_dependencies/ethers/fragments.d.ts +458 -0
- package/js/src/static_dependencies/ethers/fragments.js +1252 -0
- package/js/src/static_dependencies/ethers/hash/index.d.ts +10 -0
- package/js/src/static_dependencies/ethers/hash/index.js +15 -0
- package/js/src/static_dependencies/ethers/hash/solidity.d.ts +30 -0
- package/js/src/static_dependencies/ethers/hash/solidity.js +107 -0
- package/js/src/static_dependencies/ethers/hash/typed-data.d.ts +144 -0
- package/js/src/static_dependencies/ethers/hash/typed-data.js +490 -0
- package/js/src/static_dependencies/ethers/index.d.ts +19 -0
- package/js/src/static_dependencies/ethers/index.js +22 -0
- package/js/src/static_dependencies/ethers/interface.d.ts +380 -0
- package/js/src/static_dependencies/ethers/interface.js +990 -0
- package/js/src/static_dependencies/ethers/typed.d.ts +569 -0
- package/js/src/static_dependencies/ethers/typed.js +608 -0
- package/js/src/static_dependencies/ethers/utils/base58.d.ts +22 -0
- package/js/src/static_dependencies/ethers/utils/base58.js +68 -0
- package/js/src/static_dependencies/ethers/utils/base64-browser.d.ts +3 -0
- package/js/src/static_dependencies/ethers/utils/base64-browser.js +24 -0
- package/js/src/static_dependencies/ethers/utils/base64.d.ts +39 -0
- package/js/src/static_dependencies/ethers/utils/base64.js +58 -0
- package/js/src/static_dependencies/ethers/utils/data.d.ts +92 -0
- package/js/src/static_dependencies/ethers/utils/data.js +175 -0
- package/js/src/static_dependencies/ethers/utils/errors.d.ts +509 -0
- package/js/src/static_dependencies/ethers/utils/errors.js +227 -0
- package/js/src/static_dependencies/ethers/utils/events.d.ts +76 -0
- package/js/src/static_dependencies/ethers/utils/events.js +52 -0
- package/js/src/static_dependencies/ethers/utils/fixednumber.d.ts +251 -0
- package/js/src/static_dependencies/ethers/utils/fixednumber.js +529 -0
- package/js/src/static_dependencies/ethers/utils/index.d.ts +30 -0
- package/js/src/static_dependencies/ethers/utils/index.js +38 -0
- package/js/src/static_dependencies/ethers/utils/maths.d.ts +65 -0
- package/js/src/static_dependencies/ethers/utils/maths.js +220 -0
- package/js/src/static_dependencies/ethers/utils/properties.d.ts +22 -0
- package/js/src/static_dependencies/ethers/utils/properties.js +59 -0
- package/js/src/static_dependencies/ethers/utils/rlp-decode.d.ts +5 -0
- package/js/src/static_dependencies/ethers/utils/rlp-decode.js +84 -0
- package/js/src/static_dependencies/ethers/utils/rlp-encode.d.ts +5 -0
- package/js/src/static_dependencies/ethers/utils/rlp-encode.js +54 -0
- package/js/src/static_dependencies/ethers/utils/rlp.d.ts +16 -0
- package/js/src/static_dependencies/ethers/utils/rlp.js +14 -0
- package/js/src/static_dependencies/ethers/utils/units.d.ts +23 -0
- package/js/src/static_dependencies/ethers/utils/units.js +88 -0
- package/js/src/static_dependencies/ethers/utils/utf8.d.ts +95 -0
- package/js/src/static_dependencies/ethers/utils/utf8.js +225 -0
- package/js/src/static_dependencies/ethers/utils/uuid.d.ts +7 -0
- package/js/src/static_dependencies/ethers/utils/uuid.js +35 -0
- package/js/src/static_dependencies/messagepack/msgpack.d.ts +2 -0
- package/js/src/static_dependencies/messagepack/msgpack.js +572 -0
- package/js/src/tokocrypto.js +22 -2
- package/js/src/wazirx.d.ts +12 -1
- package/js/src/wazirx.js +314 -4
- package/js/src/woo.d.ts +8 -0
- package/js/src/woo.js +157 -77
- package/package.json +1 -1
- package/skip-tests.json +60 -16
|
@@ -0,0 +1,2036 @@
|
|
|
1
|
+
// ----------------------------------------------------------------------------
|
|
2
|
+
|
|
3
|
+
// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
|
|
4
|
+
// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
|
|
5
|
+
// EDIT THE CORRESPONDENT .ts FILE INSTEAD
|
|
6
|
+
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
import Exchange from './abstract/hyperliquid.js';
|
|
9
|
+
import { ExchangeError, ArgumentsRequired, NotSupported, InvalidOrder, OrderNotFound } from './base/errors.js';
|
|
10
|
+
import { Precise } from './base/Precise.js';
|
|
11
|
+
import { TICK_SIZE, ROUND } from './base/functions/number.js';
|
|
12
|
+
import { keccak_256 as keccak } from './static_dependencies/noble-hashes/sha3.js';
|
|
13
|
+
import { secp256k1 } from './static_dependencies/noble-curves/secp256k1.js';
|
|
14
|
+
import { ecdsa } from './base/functions/crypto.js';
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
/**
|
|
17
|
+
* @class hyperliquid
|
|
18
|
+
* @augments Exchange
|
|
19
|
+
*/
|
|
20
|
+
export default class hyperliquid extends Exchange {
|
|
21
|
+
describe() {
|
|
22
|
+
return this.deepExtend(super.describe(), {
|
|
23
|
+
'id': 'hyperliquid',
|
|
24
|
+
'name': 'Hyperliquid',
|
|
25
|
+
'countries': [],
|
|
26
|
+
'version': 'v1',
|
|
27
|
+
'rateLimit': 50,
|
|
28
|
+
'certified': false,
|
|
29
|
+
'pro': false,
|
|
30
|
+
'has': {
|
|
31
|
+
'CORS': undefined,
|
|
32
|
+
'spot': false,
|
|
33
|
+
'margin': false,
|
|
34
|
+
'swap': true,
|
|
35
|
+
'future': true,
|
|
36
|
+
'option': false,
|
|
37
|
+
'addMargin': true,
|
|
38
|
+
'borrowCrossMargin': false,
|
|
39
|
+
'borrowIsolatedMargin': false,
|
|
40
|
+
'cancelAllOrders': false,
|
|
41
|
+
'cancelOrder': true,
|
|
42
|
+
'cancelOrders': true,
|
|
43
|
+
'closeAllPositions': false,
|
|
44
|
+
'closePosition': false,
|
|
45
|
+
'createMarketBuyOrderWithCost': false,
|
|
46
|
+
'createMarketOrderWithCost': false,
|
|
47
|
+
'createMarketSellOrderWithCost': false,
|
|
48
|
+
'createOrder': true,
|
|
49
|
+
'createOrders': true,
|
|
50
|
+
'createReduceOnlyOrder': false,
|
|
51
|
+
'editOrder': true,
|
|
52
|
+
'fetchAccounts': false,
|
|
53
|
+
'fetchBalance': true,
|
|
54
|
+
'fetchBorrowInterest': false,
|
|
55
|
+
'fetchBorrowRateHistories': false,
|
|
56
|
+
'fetchBorrowRateHistory': false,
|
|
57
|
+
'fetchCanceledOrders': false,
|
|
58
|
+
'fetchClosedOrders': true,
|
|
59
|
+
'fetchCrossBorrowRate': false,
|
|
60
|
+
'fetchCrossBorrowRates': false,
|
|
61
|
+
'fetchCurrencies': true,
|
|
62
|
+
'fetchDepositAddress': false,
|
|
63
|
+
'fetchDepositAddresses': false,
|
|
64
|
+
'fetchDeposits': false,
|
|
65
|
+
'fetchDepositWithdrawFee': 'emulated',
|
|
66
|
+
'fetchDepositWithdrawFees': false,
|
|
67
|
+
'fetchFundingHistory': false,
|
|
68
|
+
'fetchFundingRate': false,
|
|
69
|
+
'fetchFundingRateHistory': true,
|
|
70
|
+
'fetchFundingRates': false,
|
|
71
|
+
'fetchIndexOHLCV': false,
|
|
72
|
+
'fetchIsolatedBorrowRate': false,
|
|
73
|
+
'fetchIsolatedBorrowRates': false,
|
|
74
|
+
'fetchLedger': false,
|
|
75
|
+
'fetchLeverage': false,
|
|
76
|
+
'fetchLeverageTiers': false,
|
|
77
|
+
'fetchLiquidations': false,
|
|
78
|
+
'fetchMarginMode': undefined,
|
|
79
|
+
'fetchMarketLeverageTiers': false,
|
|
80
|
+
'fetchMarkets': true,
|
|
81
|
+
'fetchMarkOHLCV': false,
|
|
82
|
+
'fetchMyLiquidations': false,
|
|
83
|
+
'fetchMyTrades': true,
|
|
84
|
+
'fetchOHLCV': true,
|
|
85
|
+
'fetchOpenInterest': false,
|
|
86
|
+
'fetchOpenInterestHistory': false,
|
|
87
|
+
'fetchOpenOrders': true,
|
|
88
|
+
'fetchOrder': true,
|
|
89
|
+
'fetchOrderBook': true,
|
|
90
|
+
'fetchOrders': false,
|
|
91
|
+
'fetchOrderTrades': false,
|
|
92
|
+
'fetchPosition': true,
|
|
93
|
+
'fetchPositionMode': false,
|
|
94
|
+
'fetchPositions': true,
|
|
95
|
+
'fetchPositionsRisk': false,
|
|
96
|
+
'fetchPremiumIndexOHLCV': false,
|
|
97
|
+
'fetchTicker': false,
|
|
98
|
+
'fetchTickers': false,
|
|
99
|
+
'fetchTime': false,
|
|
100
|
+
'fetchTrades': true,
|
|
101
|
+
'fetchTradingFee': false,
|
|
102
|
+
'fetchTradingFees': false,
|
|
103
|
+
'fetchTransfer': false,
|
|
104
|
+
'fetchTransfers': false,
|
|
105
|
+
'fetchWithdrawal': false,
|
|
106
|
+
'fetchWithdrawals': false,
|
|
107
|
+
'reduceMargin': true,
|
|
108
|
+
'repayCrossMargin': false,
|
|
109
|
+
'repayIsolatedMargin': false,
|
|
110
|
+
'setLeverage': true,
|
|
111
|
+
'setMarginMode': true,
|
|
112
|
+
'setPositionMode': false,
|
|
113
|
+
'transfer': true,
|
|
114
|
+
'withdraw': true,
|
|
115
|
+
},
|
|
116
|
+
'timeframes': {
|
|
117
|
+
'1m': '1m',
|
|
118
|
+
'3m': '3m',
|
|
119
|
+
'5m': '5m',
|
|
120
|
+
'15m': '15m',
|
|
121
|
+
'30m': '30m',
|
|
122
|
+
'1h': '1h',
|
|
123
|
+
'2h': '2h',
|
|
124
|
+
'4h': '4h',
|
|
125
|
+
'6h': '6h',
|
|
126
|
+
'12h': '12h',
|
|
127
|
+
'1d': '1d',
|
|
128
|
+
'3d': '3d',
|
|
129
|
+
'1w': '1w',
|
|
130
|
+
'1M': '1m',
|
|
131
|
+
},
|
|
132
|
+
'hostname': 'hyperliquid.xyz',
|
|
133
|
+
'urls': {
|
|
134
|
+
'logo': 'https://private-user-images.githubusercontent.com/43336371/310452397-3974aea3-c1a1-40c8-8df1-c2c00c829ca1.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MDk3MTk4OTUsIm5iZiI6MTcwOTcxOTU5NSwicGF0aCI6Ii80MzMzNjM3MS8zMTA0NTIzOTctMzk3NGFlYTMtYzFhMS00MGM4LThkZjEtYzJjMDBjODI5Y2ExLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDAzMDYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwMzA2VDEwMDYzNVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTNhNjk0Yzg4Y2I4MDFhZTViODZmZWI5MWUzNzYxZTExN2JkYjdlZjJkMzM1YjVlNDg5ZmM2MGQ3NDJhYWRhYjkmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.SYtqqL0tfQe6rnqsFNwHRVhKouJTjQEBGX0FPXWGoG8',
|
|
135
|
+
'api': {
|
|
136
|
+
'public': 'https://api.{hostname}',
|
|
137
|
+
'private': 'https://api.{hostname}',
|
|
138
|
+
},
|
|
139
|
+
'test': {
|
|
140
|
+
'public': 'https://api.hyperliquid-testnet.xyz',
|
|
141
|
+
'private': 'https://api.hyperliquid-testnet.xyz',
|
|
142
|
+
},
|
|
143
|
+
'www': 'https://hyperliquid.xyz',
|
|
144
|
+
'doc': 'https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api',
|
|
145
|
+
'fees': 'https://hyperliquid.gitbook.io/hyperliquid-docs/trading/fees',
|
|
146
|
+
'referral': 'https://app.hyperliquid.xyz/',
|
|
147
|
+
},
|
|
148
|
+
'api': {
|
|
149
|
+
'public': {
|
|
150
|
+
'post': {
|
|
151
|
+
'info': 1,
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
'private': {
|
|
155
|
+
'post': {
|
|
156
|
+
'exchange': 1,
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
'fees': {
|
|
161
|
+
'swap': {
|
|
162
|
+
'taker': this.parseNumber('0.00035'),
|
|
163
|
+
'maker': this.parseNumber('0.0001'),
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
'requiredCredentials': {
|
|
167
|
+
'apiKey': false,
|
|
168
|
+
'secret': false,
|
|
169
|
+
'walletAddress': true,
|
|
170
|
+
'privateKey': true,
|
|
171
|
+
},
|
|
172
|
+
'exceptions': {
|
|
173
|
+
'exact': {},
|
|
174
|
+
'broad': {
|
|
175
|
+
'Price must be divisible by tick size.': InvalidOrder,
|
|
176
|
+
'Order must have minimum value of $10': InvalidOrder,
|
|
177
|
+
'Insufficient margin to place order.': InvalidOrder,
|
|
178
|
+
'Reduce only order would increase position.': InvalidOrder,
|
|
179
|
+
'Post only order would have immediately matched,': InvalidOrder,
|
|
180
|
+
'Order could not immediately match against any resting orders.': InvalidOrder,
|
|
181
|
+
'Invalid TP/SL price.': InvalidOrder,
|
|
182
|
+
'No liquidity available for market order.': InvalidOrder,
|
|
183
|
+
'Order was never placed, already canceled, or filled.': OrderNotFound,
|
|
184
|
+
'User or API Wallet ': InvalidOrder,
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
'precisionMode': TICK_SIZE,
|
|
188
|
+
'commonCurrencies': {},
|
|
189
|
+
'options': {
|
|
190
|
+
'sandboxMode': false,
|
|
191
|
+
'defaultSlippage': 0.05,
|
|
192
|
+
'zeroAddress': '0x0000000000000000000000000000000000000000',
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
setSandboxMode(enabled) {
|
|
197
|
+
super.setSandboxMode(enabled);
|
|
198
|
+
this.options['sandboxMode'] = enabled;
|
|
199
|
+
}
|
|
200
|
+
async fetchCurrencies(params = {}) {
|
|
201
|
+
/**
|
|
202
|
+
* @method
|
|
203
|
+
* @name hyperliquid#fetchCurrencies
|
|
204
|
+
* @description fetches all available currencies on an exchange
|
|
205
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-exchange-metadata
|
|
206
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
207
|
+
* @returns {object} an associative dictionary of currencies
|
|
208
|
+
*/
|
|
209
|
+
const request = {
|
|
210
|
+
'type': 'meta',
|
|
211
|
+
};
|
|
212
|
+
const response = await this.publicPostInfo(this.extend(request, params));
|
|
213
|
+
//
|
|
214
|
+
// [
|
|
215
|
+
// {
|
|
216
|
+
// "universe": [
|
|
217
|
+
// {
|
|
218
|
+
// "maxLeverage": 50,
|
|
219
|
+
// "name": "SOL",
|
|
220
|
+
// "onlyIsolated": false,
|
|
221
|
+
// "szDecimals": 2
|
|
222
|
+
// }
|
|
223
|
+
// ]
|
|
224
|
+
// }
|
|
225
|
+
// ]
|
|
226
|
+
//
|
|
227
|
+
const meta = this.safeList(response, 'universe', []);
|
|
228
|
+
const result = {};
|
|
229
|
+
for (let i = 0; i < meta.length; i++) {
|
|
230
|
+
const data = this.safeDict(meta, i, {});
|
|
231
|
+
const id = i;
|
|
232
|
+
const name = this.safeString(data, 'name');
|
|
233
|
+
const code = this.safeCurrencyCode(name);
|
|
234
|
+
result[code] = {
|
|
235
|
+
'id': id,
|
|
236
|
+
'name': name,
|
|
237
|
+
'code': code,
|
|
238
|
+
'precision': undefined,
|
|
239
|
+
'info': data,
|
|
240
|
+
'active': undefined,
|
|
241
|
+
'deposit': undefined,
|
|
242
|
+
'withdraw': undefined,
|
|
243
|
+
'networks': undefined,
|
|
244
|
+
'fee': undefined,
|
|
245
|
+
// 'fees': fees,
|
|
246
|
+
'limits': undefined,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
return result;
|
|
250
|
+
}
|
|
251
|
+
async fetchMarkets(params = {}) {
|
|
252
|
+
/**
|
|
253
|
+
* @method
|
|
254
|
+
* @name hyperliquid#fetchMarkets
|
|
255
|
+
* @description retrieves data on all markets for hyperliquid
|
|
256
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-asset-contexts-includes-mark-price-current-funding-open-interest-etc
|
|
257
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
258
|
+
* @returns {object[]} an array of objects representing market data
|
|
259
|
+
*/
|
|
260
|
+
const request = {
|
|
261
|
+
'type': 'metaAndAssetCtxs',
|
|
262
|
+
};
|
|
263
|
+
const response = await this.publicPostInfo(this.extend(request, params));
|
|
264
|
+
//
|
|
265
|
+
// [
|
|
266
|
+
// {
|
|
267
|
+
// "universe": [
|
|
268
|
+
// {
|
|
269
|
+
// "maxLeverage": 50,
|
|
270
|
+
// "name": "SOL",
|
|
271
|
+
// "onlyIsolated": false,
|
|
272
|
+
// "szDecimals": 2
|
|
273
|
+
// }
|
|
274
|
+
// ]
|
|
275
|
+
// },
|
|
276
|
+
// [
|
|
277
|
+
// {
|
|
278
|
+
// "dayNtlVlm": "9450588.2273",
|
|
279
|
+
// "funding": "0.0000198",
|
|
280
|
+
// "impactPxs": [
|
|
281
|
+
// "108.04",
|
|
282
|
+
// "108.06"
|
|
283
|
+
// ],
|
|
284
|
+
// "markPx": "108.04",
|
|
285
|
+
// "midPx": "108.05",
|
|
286
|
+
// "openInterest": "10764.48",
|
|
287
|
+
// "oraclePx": "107.99",
|
|
288
|
+
// "premium": "0.00055561",
|
|
289
|
+
// "prevDayPx": "111.81"
|
|
290
|
+
// }
|
|
291
|
+
// ]
|
|
292
|
+
// ]
|
|
293
|
+
//
|
|
294
|
+
let meta = this.safeDict(response, 0, {});
|
|
295
|
+
meta = this.safeList(meta, 'universe', []);
|
|
296
|
+
const assetCtxs = this.safeDict(response, 1, {});
|
|
297
|
+
const result = [];
|
|
298
|
+
for (let i = 0; i < meta.length; i++) {
|
|
299
|
+
const data = this.extend(this.safeDict(meta, i, {}), this.safeDict(assetCtxs, i, {}));
|
|
300
|
+
data['baseId'] = i;
|
|
301
|
+
result.push(data);
|
|
302
|
+
}
|
|
303
|
+
return this.parseMarkets(result);
|
|
304
|
+
}
|
|
305
|
+
parseMarket(market) {
|
|
306
|
+
//
|
|
307
|
+
// {
|
|
308
|
+
// "maxLeverage": "50",
|
|
309
|
+
// "name": "ETH",
|
|
310
|
+
// "onlyIsolated": false,
|
|
311
|
+
// "szDecimals": "4",
|
|
312
|
+
// "dayNtlVlm": "1709813.11535",
|
|
313
|
+
// "funding": "0.00004807",
|
|
314
|
+
// "impactPxs": [
|
|
315
|
+
// "2369.3",
|
|
316
|
+
// "2369.6"
|
|
317
|
+
// ],
|
|
318
|
+
// "markPx": "2369.6",
|
|
319
|
+
// "midPx": "2369.45",
|
|
320
|
+
// "openInterest": "1815.4712",
|
|
321
|
+
// "oraclePx": "2367.3",
|
|
322
|
+
// "premium": "0.00090821",
|
|
323
|
+
// "prevDayPx": "2381.5"
|
|
324
|
+
// }
|
|
325
|
+
//
|
|
326
|
+
const quoteId = 'USDC';
|
|
327
|
+
const base = this.safeString(market, 'name');
|
|
328
|
+
const quote = this.safeCurrencyCode(quoteId);
|
|
329
|
+
const baseId = this.safeString(market, 'baseId');
|
|
330
|
+
const settleId = 'USDC';
|
|
331
|
+
const settle = this.safeCurrencyCode(settleId);
|
|
332
|
+
let symbol = base + '/' + quote;
|
|
333
|
+
const contract = true;
|
|
334
|
+
const swap = true;
|
|
335
|
+
if (contract) {
|
|
336
|
+
if (swap) {
|
|
337
|
+
symbol = symbol + ':' + settle;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
const fees = this.safeDict(this.fees, 'swap', {});
|
|
341
|
+
const taker = this.safeNumber(fees, 'taker');
|
|
342
|
+
const maker = this.safeNumber(fees, 'maker');
|
|
343
|
+
return {
|
|
344
|
+
'id': baseId,
|
|
345
|
+
'symbol': symbol,
|
|
346
|
+
'base': base,
|
|
347
|
+
'quote': quote,
|
|
348
|
+
'settle': settle,
|
|
349
|
+
'baseId': baseId,
|
|
350
|
+
'quoteId': quoteId,
|
|
351
|
+
'settleId': settleId,
|
|
352
|
+
'type': 'swap',
|
|
353
|
+
'spot': false,
|
|
354
|
+
'margin': undefined,
|
|
355
|
+
'swap': swap,
|
|
356
|
+
'future': false,
|
|
357
|
+
'option': false,
|
|
358
|
+
'active': true,
|
|
359
|
+
'contract': contract,
|
|
360
|
+
'linear': true,
|
|
361
|
+
'inverse': false,
|
|
362
|
+
'taker': taker,
|
|
363
|
+
'maker': maker,
|
|
364
|
+
'contractSize': this.parseNumber('1'),
|
|
365
|
+
'expiry': undefined,
|
|
366
|
+
'expiryDatetime': undefined,
|
|
367
|
+
'strike': undefined,
|
|
368
|
+
'optionType': undefined,
|
|
369
|
+
'precision': {
|
|
370
|
+
'amount': 0.00000001,
|
|
371
|
+
'price': 0.00000001,
|
|
372
|
+
},
|
|
373
|
+
'limits': {
|
|
374
|
+
'leverage': {
|
|
375
|
+
'min': undefined,
|
|
376
|
+
'max': undefined,
|
|
377
|
+
},
|
|
378
|
+
'amount': {
|
|
379
|
+
'min': undefined,
|
|
380
|
+
'max': undefined,
|
|
381
|
+
},
|
|
382
|
+
'price': {
|
|
383
|
+
'min': undefined,
|
|
384
|
+
'max': undefined,
|
|
385
|
+
},
|
|
386
|
+
'cost': {
|
|
387
|
+
'min': undefined,
|
|
388
|
+
'max': undefined,
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
'created': undefined,
|
|
392
|
+
'info': market,
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
async fetchBalance(params = {}) {
|
|
396
|
+
/**
|
|
397
|
+
* @method
|
|
398
|
+
* @name hyperliquid#fetchBalance
|
|
399
|
+
* @description query for balance and get the amount of funds available for trading or funds locked in orders
|
|
400
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-state
|
|
401
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
402
|
+
* @param {string} [params.user] user address, will default to this.walletAddress if not provided
|
|
403
|
+
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
|
|
404
|
+
*/
|
|
405
|
+
let userAddress = undefined;
|
|
406
|
+
[userAddress, params] = this.handlePublicAddress('fetchBalance', params);
|
|
407
|
+
const request = {
|
|
408
|
+
'type': 'clearinghouseState',
|
|
409
|
+
'user': userAddress,
|
|
410
|
+
};
|
|
411
|
+
const response = await this.publicPostInfo(this.extend(request, params));
|
|
412
|
+
//
|
|
413
|
+
// {
|
|
414
|
+
// "assetPositions": [],
|
|
415
|
+
// "crossMaintenanceMarginUsed": "0.0",
|
|
416
|
+
// "crossMarginSummary": {
|
|
417
|
+
// "accountValue": "100.0",
|
|
418
|
+
// "totalMarginUsed": "0.0",
|
|
419
|
+
// "totalNtlPos": "0.0",
|
|
420
|
+
// "totalRawUsd": "100.0"
|
|
421
|
+
// },
|
|
422
|
+
// "marginSummary": {
|
|
423
|
+
// "accountValue": "100.0",
|
|
424
|
+
// "totalMarginUsed": "0.0",
|
|
425
|
+
// "totalNtlPos": "0.0",
|
|
426
|
+
// "totalRawUsd": "100.0"
|
|
427
|
+
// },
|
|
428
|
+
// "time": "1704261007014",
|
|
429
|
+
// "withdrawable": "100.0"
|
|
430
|
+
// }
|
|
431
|
+
//
|
|
432
|
+
const data = this.safeDict(response, 'marginSummary', {});
|
|
433
|
+
const result = {
|
|
434
|
+
'info': response,
|
|
435
|
+
'USDC': {
|
|
436
|
+
'total': this.safeFloat(data, 'accountValue'),
|
|
437
|
+
'used': this.safeFloat(data, 'totalMarginUsed'),
|
|
438
|
+
},
|
|
439
|
+
};
|
|
440
|
+
const timestamp = this.safeInteger(response, 'time');
|
|
441
|
+
result['timestamp'] = timestamp;
|
|
442
|
+
result['datetime'] = this.iso8601(timestamp);
|
|
443
|
+
return this.safeBalance(result);
|
|
444
|
+
}
|
|
445
|
+
async fetchOrderBook(symbol, limit = undefined, params = {}) {
|
|
446
|
+
/**
|
|
447
|
+
* @method
|
|
448
|
+
* @name hyperliquid#fetchOrderBook
|
|
449
|
+
* @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
450
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#info
|
|
451
|
+
* @param {string} symbol unified symbol of the market to fetch the order book for
|
|
452
|
+
* @param {int} [limit] the maximum amount of order book entries to return
|
|
453
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
454
|
+
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
|
|
455
|
+
*/
|
|
456
|
+
await this.loadMarkets();
|
|
457
|
+
const market = this.market(symbol);
|
|
458
|
+
const request = {
|
|
459
|
+
'type': 'l2Book',
|
|
460
|
+
'coin': market['base'],
|
|
461
|
+
};
|
|
462
|
+
const response = await this.publicPostInfo(this.extend(request, params));
|
|
463
|
+
//
|
|
464
|
+
// {
|
|
465
|
+
// "coin": "ETH",
|
|
466
|
+
// "levels": [
|
|
467
|
+
// [
|
|
468
|
+
// {
|
|
469
|
+
// "n": "2",
|
|
470
|
+
// "px": "2216.2",
|
|
471
|
+
// "sz": "74.0637"
|
|
472
|
+
// }
|
|
473
|
+
// ],
|
|
474
|
+
// [
|
|
475
|
+
// {
|
|
476
|
+
// "n": "2",
|
|
477
|
+
// "px": "2216.5",
|
|
478
|
+
// "sz": "70.5893"
|
|
479
|
+
// }
|
|
480
|
+
// ]
|
|
481
|
+
// ],
|
|
482
|
+
// "time": "1704290104840"
|
|
483
|
+
// }
|
|
484
|
+
//
|
|
485
|
+
const data = this.safeList(response, 'levels', []);
|
|
486
|
+
const result = {
|
|
487
|
+
'bids': this.safeList(data, 0, []),
|
|
488
|
+
'asks': this.safeList(data, 1, []),
|
|
489
|
+
};
|
|
490
|
+
const timestamp = this.safeInteger(response, 'time');
|
|
491
|
+
return this.parseOrderBook(result, market['symbol'], timestamp, 'bids', 'asks', 'px', 'sz');
|
|
492
|
+
}
|
|
493
|
+
async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
|
|
494
|
+
/**
|
|
495
|
+
* @method
|
|
496
|
+
* @name hyperliquid#fetchOHLCV
|
|
497
|
+
* @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
498
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#info-1
|
|
499
|
+
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
|
|
500
|
+
* @param {string} timeframe the length of time each candle represents, support '1m', '15m', '1h', '1d'
|
|
501
|
+
* @param {int} [since] timestamp in ms of the earliest candle to fetch
|
|
502
|
+
* @param {int} [limit] the maximum amount of candles to fetch
|
|
503
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
504
|
+
* @param {int} [params.until] timestamp in ms of the latest candle to fetch
|
|
505
|
+
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
506
|
+
*/
|
|
507
|
+
await this.loadMarkets();
|
|
508
|
+
const market = this.market(symbol);
|
|
509
|
+
const until = this.safeInteger(params, 'until', this.milliseconds());
|
|
510
|
+
if (since === undefined) {
|
|
511
|
+
since = 0;
|
|
512
|
+
}
|
|
513
|
+
if (limit === undefined) {
|
|
514
|
+
limit = 500;
|
|
515
|
+
}
|
|
516
|
+
params = this.omit(params, ['until']);
|
|
517
|
+
const request = {
|
|
518
|
+
'type': 'candleSnapshot',
|
|
519
|
+
'req': {
|
|
520
|
+
'coin': market['base'],
|
|
521
|
+
'interval': timeframe,
|
|
522
|
+
'startTime': since,
|
|
523
|
+
'endTime': until,
|
|
524
|
+
},
|
|
525
|
+
};
|
|
526
|
+
const response = await this.publicPostInfo(this.extend(request, params));
|
|
527
|
+
//
|
|
528
|
+
// [
|
|
529
|
+
// {
|
|
530
|
+
// "T": 1704287699999,
|
|
531
|
+
// "c": "2226.4",
|
|
532
|
+
// "h": "2247.9",
|
|
533
|
+
// "i": "15m",
|
|
534
|
+
// "l": "2224.6",
|
|
535
|
+
// "n": 46,
|
|
536
|
+
// "o": "2247.9",
|
|
537
|
+
// "s": "ETH",
|
|
538
|
+
// "t": 1704286800000,
|
|
539
|
+
// "v": "591.6427"
|
|
540
|
+
// }
|
|
541
|
+
// ]
|
|
542
|
+
//
|
|
543
|
+
return this.parseOHLCVs(response, market, timeframe, since, limit);
|
|
544
|
+
}
|
|
545
|
+
parseOHLCV(ohlcv, market = undefined) {
|
|
546
|
+
//
|
|
547
|
+
// {
|
|
548
|
+
// "T": 1704287699999,
|
|
549
|
+
// "c": "2226.4",
|
|
550
|
+
// "h": "2247.9",
|
|
551
|
+
// "i": "15m",
|
|
552
|
+
// "l": "2224.6",
|
|
553
|
+
// "n": 46,
|
|
554
|
+
// "o": "2247.9",
|
|
555
|
+
// "s": "ETH",
|
|
556
|
+
// "t": 1704286800000,
|
|
557
|
+
// "v": "591.6427"
|
|
558
|
+
// }
|
|
559
|
+
//
|
|
560
|
+
return [
|
|
561
|
+
this.safeInteger(ohlcv, 'T'),
|
|
562
|
+
this.safeNumber(ohlcv, 'o'),
|
|
563
|
+
this.safeNumber(ohlcv, 'h'),
|
|
564
|
+
this.safeNumber(ohlcv, 'l'),
|
|
565
|
+
this.safeNumber(ohlcv, 'c'),
|
|
566
|
+
this.safeNumber(ohlcv, 'v'),
|
|
567
|
+
];
|
|
568
|
+
}
|
|
569
|
+
async fetchTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
570
|
+
/**
|
|
571
|
+
* @method
|
|
572
|
+
* @name hyperliquid#fetchTrades
|
|
573
|
+
* @description get the list of most recent trades for a particular symbol
|
|
574
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-fills
|
|
575
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-fills-by-time
|
|
576
|
+
* @param {string} symbol unified market symbol
|
|
577
|
+
* @param {int} [since] the earliest time in ms to fetch trades for
|
|
578
|
+
* @param {int} [limit] the maximum number of trades structures to retrieve
|
|
579
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
580
|
+
* @param {int} [params.until] timestamp in ms of the latest trade
|
|
581
|
+
* @param {string} [params.address] wallet address that made trades
|
|
582
|
+
* @param {string} [params.user] wallet address that made trades
|
|
583
|
+
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
|
|
584
|
+
*/
|
|
585
|
+
let userAddress = undefined;
|
|
586
|
+
[userAddress, params] = this.handlePublicAddress('fetchTrades', params);
|
|
587
|
+
await this.loadMarkets();
|
|
588
|
+
const market = this.safeMarket(symbol);
|
|
589
|
+
const request = {
|
|
590
|
+
'user': userAddress,
|
|
591
|
+
};
|
|
592
|
+
if (since !== undefined) {
|
|
593
|
+
request['type'] = 'userFillsByTime';
|
|
594
|
+
request['startTime'] = since;
|
|
595
|
+
}
|
|
596
|
+
else {
|
|
597
|
+
request['type'] = 'userFills';
|
|
598
|
+
}
|
|
599
|
+
const until = this.safeInteger(params, 'until');
|
|
600
|
+
params = this.omit(params, 'until');
|
|
601
|
+
if (until !== undefined) {
|
|
602
|
+
request['endTime'] = until;
|
|
603
|
+
}
|
|
604
|
+
const response = await this.publicPostInfo(this.extend(request, params));
|
|
605
|
+
//
|
|
606
|
+
// [
|
|
607
|
+
// {
|
|
608
|
+
// "closedPnl": "0.19343",
|
|
609
|
+
// "coin": "ETH",
|
|
610
|
+
// "crossed": true,
|
|
611
|
+
// "dir": "Close Long",
|
|
612
|
+
// "fee": "0.050062",
|
|
613
|
+
// "hash": "0x09d77c96791e98b5775a04092584ab010d009445119c71e4005c0d634ea322bc",
|
|
614
|
+
// "liquidationMarkPx": null,
|
|
615
|
+
// "oid": 3929354691,
|
|
616
|
+
// "px": "2381.1",
|
|
617
|
+
// "side": "A",
|
|
618
|
+
// "startPosition": "0.0841",
|
|
619
|
+
// "sz": "0.0841",
|
|
620
|
+
// "tid": 128423918764978,
|
|
621
|
+
// "time": 1704262888911
|
|
622
|
+
// }
|
|
623
|
+
// ]
|
|
624
|
+
//
|
|
625
|
+
return this.parseTrades(response, market, since, limit);
|
|
626
|
+
}
|
|
627
|
+
amountToPrecision(symbol, amount) {
|
|
628
|
+
return this.decimalToPrecision(amount, ROUND, this.markets[symbol]['precision']['amount'], this.precisionMode);
|
|
629
|
+
}
|
|
630
|
+
hashMessage(message) {
|
|
631
|
+
return '0x' + this.hash(message, keccak, 'hex');
|
|
632
|
+
}
|
|
633
|
+
signHash(hash, privateKey) {
|
|
634
|
+
const signature = ecdsa(hash.slice(-64), privateKey.slice(-64), secp256k1, undefined);
|
|
635
|
+
return {
|
|
636
|
+
'r': '0x' + signature['r'],
|
|
637
|
+
's': '0x' + signature['s'],
|
|
638
|
+
'v': this.sum(27, signature['v']),
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
signMessage(message, privateKey) {
|
|
642
|
+
return this.signHash(this.hashMessage(message), privateKey.slice(-64));
|
|
643
|
+
}
|
|
644
|
+
constructPhantomAgent(hash, isTestnet = true) {
|
|
645
|
+
const source = (isTestnet) ? 'b' : 'a';
|
|
646
|
+
return {
|
|
647
|
+
'source': source,
|
|
648
|
+
'connectionId': hash,
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
actionHash(action, vaultAddress, nonce) {
|
|
652
|
+
const dataBinary = this.packb(action);
|
|
653
|
+
const dataHex = this.binaryToBase16(dataBinary);
|
|
654
|
+
let data = dataHex;
|
|
655
|
+
data += '00000' + this.intToBase16(nonce);
|
|
656
|
+
if (vaultAddress === undefined) {
|
|
657
|
+
data += '00';
|
|
658
|
+
}
|
|
659
|
+
else {
|
|
660
|
+
data += '01';
|
|
661
|
+
data += vaultAddress;
|
|
662
|
+
}
|
|
663
|
+
return this.hash(this.base16ToBinary(data), keccak, 'binary');
|
|
664
|
+
}
|
|
665
|
+
signL1Action(action, nonce, vaultAdress = undefined) {
|
|
666
|
+
const hash = this.actionHash(action, vaultAdress, nonce);
|
|
667
|
+
const isTestnet = this.safeBool(this.options, 'sandboxMode', false);
|
|
668
|
+
const phantomAgent = this.constructPhantomAgent(hash, isTestnet);
|
|
669
|
+
// const data = {
|
|
670
|
+
// 'domain': {
|
|
671
|
+
// 'chainId': 1337,
|
|
672
|
+
// 'name': 'Exchange',
|
|
673
|
+
// 'verifyingContract': '0x0000000000000000000000000000000000000000',
|
|
674
|
+
// 'version': '1',
|
|
675
|
+
// },
|
|
676
|
+
// 'types': {
|
|
677
|
+
// 'Agent': [
|
|
678
|
+
// { 'name': 'source', 'type': 'string' },
|
|
679
|
+
// { 'name': 'connectionId', 'type': 'bytes32' },
|
|
680
|
+
// ],
|
|
681
|
+
// 'EIP712Domain': [
|
|
682
|
+
// { 'name': 'name', 'type': 'string' },
|
|
683
|
+
// { 'name': 'version', 'type': 'string' },
|
|
684
|
+
// { 'name': 'chainId', 'type': 'uint256' },
|
|
685
|
+
// { 'name': 'verifyingContract', 'type': 'address' },
|
|
686
|
+
// ],
|
|
687
|
+
// },
|
|
688
|
+
// 'primaryType': 'Agent',
|
|
689
|
+
// 'message': phantomAgent,
|
|
690
|
+
// };
|
|
691
|
+
const zeroAddress = this.safeString(this.options, 'zeroAddress');
|
|
692
|
+
const chainId = 1337; // check this out
|
|
693
|
+
const domain = {
|
|
694
|
+
'chainId': chainId,
|
|
695
|
+
'name': 'Exchange',
|
|
696
|
+
'verifyingContract': zeroAddress,
|
|
697
|
+
'version': '1',
|
|
698
|
+
};
|
|
699
|
+
const messageTypes = {
|
|
700
|
+
'Agent': [
|
|
701
|
+
{ 'name': 'source', 'type': 'string' },
|
|
702
|
+
{ 'name': 'connectionId', 'type': 'bytes32' },
|
|
703
|
+
],
|
|
704
|
+
};
|
|
705
|
+
const msg = this.ethEncodeStructuredData(domain, messageTypes, phantomAgent);
|
|
706
|
+
const signature = this.signMessage(msg, this.privateKey);
|
|
707
|
+
return signature;
|
|
708
|
+
}
|
|
709
|
+
buildSig(chainId, messageTypes, message) {
|
|
710
|
+
const zeroAddress = this.safeString(this.options, 'zeroAddress');
|
|
711
|
+
const domain = {
|
|
712
|
+
'chainId': chainId,
|
|
713
|
+
'name': 'Exchange',
|
|
714
|
+
'verifyingContract': zeroAddress,
|
|
715
|
+
'version': '1',
|
|
716
|
+
};
|
|
717
|
+
const msg = this.ethEncodeStructuredData(domain, messageTypes, message);
|
|
718
|
+
const signature = this.signMessage(msg, this.privateKey);
|
|
719
|
+
return signature;
|
|
720
|
+
}
|
|
721
|
+
buildTransferSig(message) {
|
|
722
|
+
const isSandboxMode = this.safeBool(this.options, 'sandboxMode');
|
|
723
|
+
const chainId = (isSandboxMode) ? 421614 : 42161;
|
|
724
|
+
const messageTypes = {
|
|
725
|
+
'UsdTransferSignPayload': [
|
|
726
|
+
{ 'name': 'destination', 'type': 'string' },
|
|
727
|
+
{ 'name': 'amount', 'type': 'string' },
|
|
728
|
+
{ 'name': 'time', 'type': 'uint64' },
|
|
729
|
+
],
|
|
730
|
+
};
|
|
731
|
+
return this.buildSig(chainId, messageTypes, message);
|
|
732
|
+
}
|
|
733
|
+
buildWithdrawSig(message) {
|
|
734
|
+
const isSandboxMode = this.safeBool(this.options, 'sandboxMode');
|
|
735
|
+
const chainId = (isSandboxMode) ? 421614 : 42161;
|
|
736
|
+
const messageTypes = {
|
|
737
|
+
'WithdrawFromBridge2SignPayload': [
|
|
738
|
+
{ 'name': 'destination', 'type': 'string' },
|
|
739
|
+
{ 'name': 'usd', 'type': 'string' },
|
|
740
|
+
{ 'name': 'time', 'type': 'uint64' },
|
|
741
|
+
],
|
|
742
|
+
};
|
|
743
|
+
return this.buildSig(chainId, messageTypes, message);
|
|
744
|
+
}
|
|
745
|
+
async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
|
|
746
|
+
/**
|
|
747
|
+
* @method
|
|
748
|
+
* @name hyperliquid#createOrder
|
|
749
|
+
* @description create a trade order
|
|
750
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#place-an-order
|
|
751
|
+
* @param {string} symbol unified symbol of the market to create an order in
|
|
752
|
+
* @param {string} type 'market' or 'limit'
|
|
753
|
+
* @param {string} side 'buy' or 'sell'
|
|
754
|
+
* @param {float} amount how much of currency you want to trade in units of base currency
|
|
755
|
+
* @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
|
756
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
757
|
+
* @param {string} [params.timeInForce] 'Gtc', 'Ioc', 'Alo'
|
|
758
|
+
* @param {bool} [params.postOnly] true or false whether the order is post-only
|
|
759
|
+
* @param {bool} [params.reduceOnly] true or false whether the order is reduce-only
|
|
760
|
+
* @param {float} [params.triggerPrice] The price at which a trigger order is triggered at
|
|
761
|
+
* @param {string} [params.clientOrderId] client order id, optional 128 bit hex string
|
|
762
|
+
* @param {string} [params.slippage] the slippage for market order
|
|
763
|
+
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
764
|
+
*/
|
|
765
|
+
await this.loadMarkets();
|
|
766
|
+
const market = this.market(symbol);
|
|
767
|
+
symbol = market['symbol'];
|
|
768
|
+
const order = {
|
|
769
|
+
'symbol': symbol,
|
|
770
|
+
'type': type,
|
|
771
|
+
'side': side,
|
|
772
|
+
'amount': amount,
|
|
773
|
+
'price': price,
|
|
774
|
+
'params': params,
|
|
775
|
+
};
|
|
776
|
+
const response = await this.createOrders([order], params);
|
|
777
|
+
const first = this.safeDict(response, 0);
|
|
778
|
+
return first;
|
|
779
|
+
}
|
|
780
|
+
async createOrders(orders, params = {}) {
|
|
781
|
+
/**
|
|
782
|
+
* @method
|
|
783
|
+
* @name hyperliquid#createOrders
|
|
784
|
+
* @description create a list of trade orders
|
|
785
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#place-an-order
|
|
786
|
+
* @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
|
|
787
|
+
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
788
|
+
*/
|
|
789
|
+
this.checkRequiredCredentials();
|
|
790
|
+
await this.loadMarkets();
|
|
791
|
+
let defaultSlippage = this.safeString(this.options, 'defaultSlippage');
|
|
792
|
+
defaultSlippage = this.safeString(params, 'slippage', defaultSlippage);
|
|
793
|
+
let hasClientOrderId = false;
|
|
794
|
+
for (let i = 0; i < orders.length; i++) {
|
|
795
|
+
const rawOrder = orders[i];
|
|
796
|
+
const orderParams = this.safeDict(rawOrder, 'params', {});
|
|
797
|
+
const clientOrderId = this.safeString2(orderParams, 'clientOrderId', 'client_id');
|
|
798
|
+
if (clientOrderId !== undefined) {
|
|
799
|
+
hasClientOrderId = true;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
if (hasClientOrderId) {
|
|
803
|
+
for (let i = 0; i < orders.length; i++) {
|
|
804
|
+
const rawOrder = orders[i];
|
|
805
|
+
const orderParams = this.safeDict(rawOrder, 'params', {});
|
|
806
|
+
const clientOrderId = this.safeString2(orderParams, 'clientOrderId', 'client_id');
|
|
807
|
+
if (clientOrderId === undefined) {
|
|
808
|
+
throw new ArgumentsRequired(this.id + ' createOrders() all orders must have clientOrderId if at least one has a clientOrderId');
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
params = this.omit(params, ['slippage', 'clientOrderId', 'client_id', 'slippage', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice']);
|
|
813
|
+
const nonce = this.milliseconds();
|
|
814
|
+
const orderReq = [];
|
|
815
|
+
for (let i = 0; i < orders.length; i++) {
|
|
816
|
+
const rawOrder = orders[i];
|
|
817
|
+
const marketId = this.safeString(rawOrder, 'symbol');
|
|
818
|
+
const market = this.market(marketId);
|
|
819
|
+
const symbol = market['symbol'];
|
|
820
|
+
const type = this.safeStringUpper(rawOrder, 'type');
|
|
821
|
+
const isMarket = (type === 'MARKET');
|
|
822
|
+
const side = this.safeStringUpper(rawOrder, 'side');
|
|
823
|
+
const isBuy = (side === 'BUY');
|
|
824
|
+
const amount = this.safeString(rawOrder, 'amount');
|
|
825
|
+
const price = this.safeString(rawOrder, 'price');
|
|
826
|
+
let orderParams = this.safeDict(rawOrder, 'params', {});
|
|
827
|
+
orderParams = this.extend(params, orderParams);
|
|
828
|
+
const clientOrderId = this.safeString2(orderParams, 'clientOrderId', 'client_id');
|
|
829
|
+
const slippage = this.safeString(orderParams, 'slippage', defaultSlippage);
|
|
830
|
+
let defaultTimeInForce = (isMarket) ? 'ioc' : 'gtc';
|
|
831
|
+
const postOnly = this.safeBool(orderParams, 'postOnly', false);
|
|
832
|
+
if (postOnly) {
|
|
833
|
+
defaultTimeInForce = 'alo';
|
|
834
|
+
}
|
|
835
|
+
let timeInForce = this.safeStringLower(orderParams, 'timeInForce', defaultTimeInForce);
|
|
836
|
+
timeInForce = this.capitalize(timeInForce);
|
|
837
|
+
let triggerPrice = this.safeString2(orderParams, 'triggerPrice', 'stopPrice');
|
|
838
|
+
const stopLossPrice = this.safeString(orderParams, 'stopLossPrice', triggerPrice);
|
|
839
|
+
const takeProfitPrice = this.safeString(orderParams, 'takeProfitPrice');
|
|
840
|
+
const isTrigger = (stopLossPrice || takeProfitPrice);
|
|
841
|
+
let px = undefined;
|
|
842
|
+
if (isMarket) {
|
|
843
|
+
if (price === undefined) {
|
|
844
|
+
throw new ArgumentsRequired(this.id + ' market orders require price to calculate the max slippage price. Default slippage can be set in options (default is 5%).');
|
|
845
|
+
}
|
|
846
|
+
px = (isBuy) ? Precise.stringMul(price, Precise.stringAdd('1', slippage)) : Precise.stringMul(price, Precise.stringSub('1', slippage));
|
|
847
|
+
}
|
|
848
|
+
else {
|
|
849
|
+
px = this.priceToPrecision(symbol, price);
|
|
850
|
+
}
|
|
851
|
+
const sz = this.amountToPrecision(symbol, amount);
|
|
852
|
+
const reduceOnly = this.safeBool(orderParams, 'reduceOnly', false);
|
|
853
|
+
const orderType = {};
|
|
854
|
+
if (isTrigger) {
|
|
855
|
+
let isTp = false;
|
|
856
|
+
if (takeProfitPrice !== undefined) {
|
|
857
|
+
triggerPrice = this.priceToPrecision(symbol, takeProfitPrice);
|
|
858
|
+
isTp = true;
|
|
859
|
+
}
|
|
860
|
+
else {
|
|
861
|
+
triggerPrice = this.priceToPrecision(symbol, stopLossPrice);
|
|
862
|
+
}
|
|
863
|
+
orderType['trigger'] = {
|
|
864
|
+
'isMarket': isMarket,
|
|
865
|
+
'triggerPx': triggerPrice,
|
|
866
|
+
'tpsl': (isTp) ? 'tp' : 'sl',
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
else {
|
|
870
|
+
orderType['limit'] = {
|
|
871
|
+
'tif': timeInForce,
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
const orderObj = {
|
|
875
|
+
'a': this.parseToInt(market['baseId']),
|
|
876
|
+
'b': isBuy,
|
|
877
|
+
'p': px,
|
|
878
|
+
's': sz,
|
|
879
|
+
'r': reduceOnly,
|
|
880
|
+
't': orderType,
|
|
881
|
+
// 'c': clientOrderId,
|
|
882
|
+
};
|
|
883
|
+
if (clientOrderId !== undefined) {
|
|
884
|
+
orderObj['c'] = clientOrderId;
|
|
885
|
+
}
|
|
886
|
+
orderReq.push(orderObj);
|
|
887
|
+
}
|
|
888
|
+
const orderAction = {
|
|
889
|
+
'type': 'order',
|
|
890
|
+
'orders': orderReq,
|
|
891
|
+
'grouping': 'na',
|
|
892
|
+
'brokerCode': 1,
|
|
893
|
+
};
|
|
894
|
+
const vaultAddress = this.safeString(params, 'vaultAddress');
|
|
895
|
+
const signature = this.signL1Action(orderAction, nonce, vaultAddress);
|
|
896
|
+
const request = {
|
|
897
|
+
'action': orderAction,
|
|
898
|
+
'nonce': nonce,
|
|
899
|
+
'signature': signature,
|
|
900
|
+
// 'vaultAddress': vaultAddress,
|
|
901
|
+
};
|
|
902
|
+
const response = await this.privatePostExchange(this.extend(request, params));
|
|
903
|
+
//
|
|
904
|
+
// {
|
|
905
|
+
// "status": "ok",
|
|
906
|
+
// "response": {
|
|
907
|
+
// "type": "order",
|
|
908
|
+
// "data": {
|
|
909
|
+
// "statuses": [
|
|
910
|
+
// {
|
|
911
|
+
// "resting": {
|
|
912
|
+
// "oid": 5063830287
|
|
913
|
+
// }
|
|
914
|
+
// }
|
|
915
|
+
// ]
|
|
916
|
+
// }
|
|
917
|
+
// }
|
|
918
|
+
// }
|
|
919
|
+
//
|
|
920
|
+
const responseObj = this.safeDict(response, 'response', {});
|
|
921
|
+
const data = this.safeDict(responseObj, 'data', {});
|
|
922
|
+
const statuses = this.safeList(data, 'statuses', []);
|
|
923
|
+
return this.parseOrders(statuses, undefined);
|
|
924
|
+
}
|
|
925
|
+
async cancelOrder(id, symbol = undefined, params = {}) {
|
|
926
|
+
/**
|
|
927
|
+
* @method
|
|
928
|
+
* @name hyperliquid#cancelOrder
|
|
929
|
+
* @description cancels an open order
|
|
930
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s
|
|
931
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s-by-cloid
|
|
932
|
+
* @param {string} id order id
|
|
933
|
+
* @param {string} symbol unified symbol of the market the order was made in
|
|
934
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
935
|
+
* @param {string} [params.clientOrderId] client order id (default undefined)
|
|
936
|
+
* @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
937
|
+
*/
|
|
938
|
+
return await this.cancelOrders([id], symbol, params);
|
|
939
|
+
}
|
|
940
|
+
async cancelOrders(ids, symbol = undefined, params = {}) {
|
|
941
|
+
/**
|
|
942
|
+
* @method
|
|
943
|
+
* @name hyperliquid#cancelOrders
|
|
944
|
+
* @description cancel multiple orders
|
|
945
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s
|
|
946
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s-by-cloid
|
|
947
|
+
* @param {string[]} ids order ids
|
|
948
|
+
* @param {string} [symbol] unified market symbol
|
|
949
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
950
|
+
* @param {string|string[]} [params.clientOrderId] client order ids (default undefined)
|
|
951
|
+
* @returns {object} an list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
952
|
+
*/
|
|
953
|
+
this.checkRequiredCredentials();
|
|
954
|
+
if (symbol === undefined) {
|
|
955
|
+
throw new ArgumentsRequired(this.id + ' cancelOrders() requires a symbol argument');
|
|
956
|
+
}
|
|
957
|
+
await this.loadMarkets();
|
|
958
|
+
const market = this.market(symbol);
|
|
959
|
+
let clientOrderId = this.safeValue2(params, 'clientOrderId', 'client_id');
|
|
960
|
+
params = this.omit(params, ['clientOrderId', 'client_id']);
|
|
961
|
+
const nonce = this.milliseconds();
|
|
962
|
+
const request = {
|
|
963
|
+
'nonce': nonce,
|
|
964
|
+
// 'vaultAddress': vaultAddress,
|
|
965
|
+
};
|
|
966
|
+
const cancelReq = [];
|
|
967
|
+
const cancelAction = {
|
|
968
|
+
'type': '',
|
|
969
|
+
'cancels': [],
|
|
970
|
+
};
|
|
971
|
+
const baseId = this.parseToNumeric(market['baseId']);
|
|
972
|
+
if (clientOrderId !== undefined) {
|
|
973
|
+
if (!Array.isArray(clientOrderId)) {
|
|
974
|
+
clientOrderId = [clientOrderId];
|
|
975
|
+
}
|
|
976
|
+
cancelAction['type'] = 'cancelByCloid';
|
|
977
|
+
for (let i = 0; i < clientOrderId.length; i++) {
|
|
978
|
+
cancelReq.push({
|
|
979
|
+
'asset': baseId,
|
|
980
|
+
'cloid': clientOrderId[i],
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
else {
|
|
985
|
+
cancelAction['type'] = 'cancel';
|
|
986
|
+
for (let i = 0; i < ids.length; i++) {
|
|
987
|
+
cancelReq.push({
|
|
988
|
+
'a': baseId,
|
|
989
|
+
'o': this.parseToNumeric(ids[i]),
|
|
990
|
+
});
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
cancelAction['cancels'] = cancelReq;
|
|
994
|
+
const vaultAddress = this.safeString(params, 'vaultAddress');
|
|
995
|
+
const signature = this.signL1Action(cancelAction, nonce, vaultAddress);
|
|
996
|
+
request['action'] = cancelAction;
|
|
997
|
+
request['signature'] = signature;
|
|
998
|
+
const response = await this.privatePostExchange(this.extend(request, params));
|
|
999
|
+
//
|
|
1000
|
+
// {
|
|
1001
|
+
// "status":"ok",
|
|
1002
|
+
// "response":{
|
|
1003
|
+
// "type":"cancel",
|
|
1004
|
+
// "data":{
|
|
1005
|
+
// "statuses":[
|
|
1006
|
+
// "success"
|
|
1007
|
+
// ]
|
|
1008
|
+
// }
|
|
1009
|
+
// }
|
|
1010
|
+
// }
|
|
1011
|
+
//
|
|
1012
|
+
return response;
|
|
1013
|
+
}
|
|
1014
|
+
async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
|
|
1015
|
+
/**
|
|
1016
|
+
* @method
|
|
1017
|
+
* @name hyperliquid#editOrder
|
|
1018
|
+
* @description edit a trade order
|
|
1019
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-an-order
|
|
1020
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-multiple-orders
|
|
1021
|
+
* @param {string} id cancel order id
|
|
1022
|
+
* @param {string} symbol unified symbol of the market to create an order in
|
|
1023
|
+
* @param {string} type 'market' or 'limit'
|
|
1024
|
+
* @param {string} side 'buy' or 'sell'
|
|
1025
|
+
* @param {float} amount how much of currency you want to trade in units of base currency
|
|
1026
|
+
* @param {float} [price] the price at which the order is to be fullfilled, in units of the base currency, ignored in market orders
|
|
1027
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1028
|
+
* @param {string} [params.timeInForce] 'Gtc', 'Ioc', 'Alo'
|
|
1029
|
+
* @param {bool} [params.postOnly] true or false whether the order is post-only
|
|
1030
|
+
* @param {bool} [params.reduceOnly] true or false whether the order is reduce-only
|
|
1031
|
+
* @param {float} [params.triggerPrice] The price at which a trigger order is triggered at
|
|
1032
|
+
* @param {string} [params.clientOrderId] client order id, (optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
|
|
1033
|
+
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
1034
|
+
*/
|
|
1035
|
+
this.checkRequiredCredentials();
|
|
1036
|
+
if (id === undefined) {
|
|
1037
|
+
throw new ArgumentsRequired(this.id + ' editOrder() requires an id argument');
|
|
1038
|
+
}
|
|
1039
|
+
await this.loadMarkets();
|
|
1040
|
+
const market = this.market(symbol);
|
|
1041
|
+
type = type.toUpperCase();
|
|
1042
|
+
const isMarket = (type === 'MARKET');
|
|
1043
|
+
side = side.toUpperCase();
|
|
1044
|
+
const isBuy = (side === 'BUY');
|
|
1045
|
+
const defaultSlippage = this.safeString(this.options, 'defaultSlippage');
|
|
1046
|
+
const slippage = this.safeString(params, 'slippage', defaultSlippage);
|
|
1047
|
+
let defaultTimeInForce = (isMarket) ? 'ioc' : 'gtc';
|
|
1048
|
+
const postOnly = this.safeBool(params, 'postOnly', false);
|
|
1049
|
+
if (postOnly) {
|
|
1050
|
+
defaultTimeInForce = 'alo';
|
|
1051
|
+
}
|
|
1052
|
+
let timeInForce = this.safeStringLower(params, 'timeInForce', defaultTimeInForce);
|
|
1053
|
+
timeInForce = this.capitalize(timeInForce);
|
|
1054
|
+
const clientOrderId = this.safeString2(params, 'clientOrderId', 'client_id');
|
|
1055
|
+
let triggerPrice = this.safeString2(params, 'triggerPrice', 'stopPrice');
|
|
1056
|
+
const stopLossPrice = this.safeString(params, 'stopLossPrice', triggerPrice);
|
|
1057
|
+
const takeProfitPrice = this.safeString(params, 'takeProfitPrice');
|
|
1058
|
+
const isTrigger = (stopLossPrice || takeProfitPrice);
|
|
1059
|
+
params = this.omit(params, ['slippage', 'timeInForce', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'clientOrderId', 'client_id']);
|
|
1060
|
+
let px = price.toString();
|
|
1061
|
+
if (isMarket) {
|
|
1062
|
+
px = (isBuy) ? Precise.stringMul(price.toString(), Precise.stringAdd('1', slippage)) : Precise.stringMul(price.toString(), Precise.stringSub('1', slippage));
|
|
1063
|
+
}
|
|
1064
|
+
else {
|
|
1065
|
+
px = this.priceToPrecision(symbol, price.toString());
|
|
1066
|
+
}
|
|
1067
|
+
const sz = this.amountToPrecision(symbol, amount);
|
|
1068
|
+
const reduceOnly = this.safeBool(params, 'reduceOnly', false);
|
|
1069
|
+
const orderType = {};
|
|
1070
|
+
if (isTrigger) {
|
|
1071
|
+
let isTp = false;
|
|
1072
|
+
if (takeProfitPrice !== undefined) {
|
|
1073
|
+
triggerPrice = this.priceToPrecision(symbol, takeProfitPrice);
|
|
1074
|
+
isTp = true;
|
|
1075
|
+
}
|
|
1076
|
+
else {
|
|
1077
|
+
triggerPrice = this.priceToPrecision(symbol, stopLossPrice);
|
|
1078
|
+
}
|
|
1079
|
+
orderType['trigger'] = {
|
|
1080
|
+
'isMarket': isMarket,
|
|
1081
|
+
'triggerPx': triggerPrice,
|
|
1082
|
+
'tpsl': (isTp) ? 'tp' : 'sl',
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
else {
|
|
1086
|
+
orderType['limit'] = {
|
|
1087
|
+
'tif': timeInForce,
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
if (triggerPrice === undefined) {
|
|
1091
|
+
triggerPrice = '0';
|
|
1092
|
+
}
|
|
1093
|
+
const nonce = this.milliseconds();
|
|
1094
|
+
const orderReq = {
|
|
1095
|
+
'a': this.parseToInt(market['baseId']),
|
|
1096
|
+
'b': isBuy,
|
|
1097
|
+
'p': px,
|
|
1098
|
+
's': sz,
|
|
1099
|
+
'r': reduceOnly,
|
|
1100
|
+
't': orderType,
|
|
1101
|
+
// 'c': clientOrderId,
|
|
1102
|
+
};
|
|
1103
|
+
if (clientOrderId !== undefined) {
|
|
1104
|
+
orderReq['c'] = clientOrderId;
|
|
1105
|
+
}
|
|
1106
|
+
const modifyReq = {
|
|
1107
|
+
'oid': this.parseToInt(id),
|
|
1108
|
+
'order': orderReq,
|
|
1109
|
+
};
|
|
1110
|
+
const modifyAction = {
|
|
1111
|
+
'type': 'batchModify',
|
|
1112
|
+
'modifies': [modifyReq],
|
|
1113
|
+
};
|
|
1114
|
+
const vaultAddress = this.safeString(params, 'vaultAddress');
|
|
1115
|
+
const signature = this.signL1Action(modifyAction, nonce, vaultAddress);
|
|
1116
|
+
const request = {
|
|
1117
|
+
'action': modifyAction,
|
|
1118
|
+
'nonce': nonce,
|
|
1119
|
+
'signature': signature,
|
|
1120
|
+
// 'vaultAddress': vaultAddress,
|
|
1121
|
+
};
|
|
1122
|
+
const response = await this.privatePostExchange(this.extend(request, params));
|
|
1123
|
+
//
|
|
1124
|
+
// {
|
|
1125
|
+
// "status": "ok",
|
|
1126
|
+
// "response": {
|
|
1127
|
+
// "type": "order",
|
|
1128
|
+
// "data": {
|
|
1129
|
+
// "statuses": [
|
|
1130
|
+
// {
|
|
1131
|
+
// "resting": {
|
|
1132
|
+
// "oid": 5063830287
|
|
1133
|
+
// }
|
|
1134
|
+
// }
|
|
1135
|
+
// ]
|
|
1136
|
+
// }
|
|
1137
|
+
// }
|
|
1138
|
+
// }
|
|
1139
|
+
// when the order is filled immediately
|
|
1140
|
+
// {
|
|
1141
|
+
// "status":"ok",
|
|
1142
|
+
// "response":{
|
|
1143
|
+
// "type":"order",
|
|
1144
|
+
// "data":{
|
|
1145
|
+
// "statuses":[
|
|
1146
|
+
// {
|
|
1147
|
+
// "filled":{
|
|
1148
|
+
// "totalSz":"0.1",
|
|
1149
|
+
// "avgPx":"100.84",
|
|
1150
|
+
// "oid":6195281425
|
|
1151
|
+
// }
|
|
1152
|
+
// }
|
|
1153
|
+
// ]
|
|
1154
|
+
// }
|
|
1155
|
+
// }
|
|
1156
|
+
// }
|
|
1157
|
+
//
|
|
1158
|
+
const responseObject = this.safeDict(response, 'response', {});
|
|
1159
|
+
const dataObject = this.safeDict(responseObject, 'data', {});
|
|
1160
|
+
const statuses = this.safeList(dataObject, 'statuses', []);
|
|
1161
|
+
const first = this.safeDict(statuses, 0, {});
|
|
1162
|
+
return this.parseOrder(first, market);
|
|
1163
|
+
}
|
|
1164
|
+
async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
1165
|
+
/**
|
|
1166
|
+
* @method
|
|
1167
|
+
* @name hyperliquid#fetchFundingRateHistory
|
|
1168
|
+
* @description fetches historical funding rate prices
|
|
1169
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-historical-funding-rates
|
|
1170
|
+
* @param {string} symbol unified symbol of the market to fetch the funding rate history for
|
|
1171
|
+
* @param {int} [since] timestamp in ms of the earliest funding rate to fetch
|
|
1172
|
+
* @param {int} [limit] the maximum amount of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure} to fetch
|
|
1173
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1174
|
+
* @param {int} [params.until] timestamp in ms of the latest funding rate
|
|
1175
|
+
* @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure}
|
|
1176
|
+
*/
|
|
1177
|
+
await this.loadMarkets();
|
|
1178
|
+
const market = this.market(symbol);
|
|
1179
|
+
const request = {
|
|
1180
|
+
'type': 'fundingHistory',
|
|
1181
|
+
'coin': market['base'],
|
|
1182
|
+
};
|
|
1183
|
+
if (since !== undefined) {
|
|
1184
|
+
request['startTime'] = since;
|
|
1185
|
+
}
|
|
1186
|
+
else {
|
|
1187
|
+
request['startTime'] = this.milliseconds() - 100 * 60 * 60 * 1000;
|
|
1188
|
+
}
|
|
1189
|
+
const until = this.safeInteger(params, 'until');
|
|
1190
|
+
params = this.omit(params, 'until');
|
|
1191
|
+
if (until !== undefined) {
|
|
1192
|
+
request['endTime'] = until;
|
|
1193
|
+
}
|
|
1194
|
+
const response = await this.publicPostInfo(this.extend(request, params));
|
|
1195
|
+
//
|
|
1196
|
+
// [
|
|
1197
|
+
// {
|
|
1198
|
+
// "coin": "ETH",
|
|
1199
|
+
// "fundingRate": "0.0000125",
|
|
1200
|
+
// "premium": "0.00057962",
|
|
1201
|
+
// "time": 1704290400031
|
|
1202
|
+
// }
|
|
1203
|
+
// ]
|
|
1204
|
+
//
|
|
1205
|
+
const result = [];
|
|
1206
|
+
for (let i = 0; i < response.length; i++) {
|
|
1207
|
+
const entry = response[i];
|
|
1208
|
+
const timestamp = this.safeInteger(entry, 'time');
|
|
1209
|
+
result.push({
|
|
1210
|
+
'info': entry,
|
|
1211
|
+
'symbol': this.safeSymbol(undefined, market),
|
|
1212
|
+
'fundingRate': this.safeNumber(entry, 'fundingRate'),
|
|
1213
|
+
'timestamp': timestamp,
|
|
1214
|
+
'datetime': this.iso8601(timestamp),
|
|
1215
|
+
});
|
|
1216
|
+
}
|
|
1217
|
+
const sorted = this.sortBy(result, 'timestamp');
|
|
1218
|
+
return this.filterBySymbolSinceLimit(sorted, symbol, since, limit);
|
|
1219
|
+
}
|
|
1220
|
+
async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
1221
|
+
/**
|
|
1222
|
+
* @method
|
|
1223
|
+
* @name hyperliquid#fetchOpenOrders
|
|
1224
|
+
* @description fetch all unfilled currently open orders
|
|
1225
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-open-orders
|
|
1226
|
+
* @param {string} symbol unified market symbol
|
|
1227
|
+
* @param {int} [since] the earliest time in ms to fetch open orders for
|
|
1228
|
+
* @param {int} [limit] the maximum number of open orders structures to retrieve
|
|
1229
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1230
|
+
* @param {string} [params.user] user address, will default to this.walletAddress if not provided
|
|
1231
|
+
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
1232
|
+
*/
|
|
1233
|
+
let userAddress = undefined;
|
|
1234
|
+
[userAddress, params] = this.handlePublicAddress('fetchOpenOrders', params);
|
|
1235
|
+
await this.loadMarkets();
|
|
1236
|
+
const market = this.safeMarket(symbol);
|
|
1237
|
+
const request = {
|
|
1238
|
+
'type': 'openOrders',
|
|
1239
|
+
'user': userAddress,
|
|
1240
|
+
};
|
|
1241
|
+
const response = await this.publicPostInfo(this.extend(request, params));
|
|
1242
|
+
//
|
|
1243
|
+
// [
|
|
1244
|
+
// {
|
|
1245
|
+
// "coin": "ETH",
|
|
1246
|
+
// "limitPx": "2000.0",
|
|
1247
|
+
// "oid": 3991946565,
|
|
1248
|
+
// "origSz": "0.1",
|
|
1249
|
+
// "side": "B",
|
|
1250
|
+
// "sz": "0.1",
|
|
1251
|
+
// "timestamp": 1704346468838
|
|
1252
|
+
// }
|
|
1253
|
+
// ]
|
|
1254
|
+
//
|
|
1255
|
+
return this.parseOrders(response, market, since, limit);
|
|
1256
|
+
}
|
|
1257
|
+
async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
1258
|
+
/**
|
|
1259
|
+
* @method
|
|
1260
|
+
* @name hyperliquid#fetchClosedOrders
|
|
1261
|
+
* @description fetch all unfilled currently closed orders
|
|
1262
|
+
* @param {string} symbol unified market symbol
|
|
1263
|
+
* @param {int} [since] the earliest time in ms to fetch open orders for
|
|
1264
|
+
* @param {int} [limit] the maximum number of open orders structures to retrieve
|
|
1265
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1266
|
+
* @param {string} [params.user] user address, will default to this.walletAddress if not provided
|
|
1267
|
+
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
1268
|
+
*/
|
|
1269
|
+
let userAddress = undefined;
|
|
1270
|
+
[userAddress, params] = this.handlePublicAddress('fetchClosedOrders', params);
|
|
1271
|
+
await this.loadMarkets();
|
|
1272
|
+
const market = this.safeMarket(symbol);
|
|
1273
|
+
const request = {
|
|
1274
|
+
'type': 'historicalOrders',
|
|
1275
|
+
'user': userAddress,
|
|
1276
|
+
};
|
|
1277
|
+
const response = await this.publicPostInfo(this.extend(request, params));
|
|
1278
|
+
//
|
|
1279
|
+
// [
|
|
1280
|
+
// {
|
|
1281
|
+
// "coin": "ETH",
|
|
1282
|
+
// "limitPx": "2000.0",
|
|
1283
|
+
// "oid": 3991946565,
|
|
1284
|
+
// "origSz": "0.1",
|
|
1285
|
+
// "side": "B",
|
|
1286
|
+
// "sz": "0.1",
|
|
1287
|
+
// "timestamp": 1704346468838
|
|
1288
|
+
// }
|
|
1289
|
+
// ]
|
|
1290
|
+
//
|
|
1291
|
+
return this.parseOrders(response, market, since, limit);
|
|
1292
|
+
}
|
|
1293
|
+
async fetchOrder(id, symbol = undefined, params = {}) {
|
|
1294
|
+
/**
|
|
1295
|
+
* @method
|
|
1296
|
+
* @name hyperliquid#fetchOrder
|
|
1297
|
+
* @description fetches information on an order made by the user
|
|
1298
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#query-order-status-by-oid-or-cloid
|
|
1299
|
+
* @param {string} symbol unified symbol of the market the order was made in
|
|
1300
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1301
|
+
* @param {string} [params.user] user address, will default to this.walletAddress if not provided
|
|
1302
|
+
* @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
1303
|
+
*/
|
|
1304
|
+
let userAddress = undefined;
|
|
1305
|
+
[userAddress, params] = this.handlePublicAddress('fetchOrder', params);
|
|
1306
|
+
await this.loadMarkets();
|
|
1307
|
+
const market = this.safeMarket(symbol);
|
|
1308
|
+
const request = {
|
|
1309
|
+
'type': 'orderStatus',
|
|
1310
|
+
'oid': this.parseToNumeric(id),
|
|
1311
|
+
'user': userAddress,
|
|
1312
|
+
};
|
|
1313
|
+
const response = await this.publicPostInfo(this.extend(request, params));
|
|
1314
|
+
//
|
|
1315
|
+
// {
|
|
1316
|
+
// "order": {
|
|
1317
|
+
// "order": {
|
|
1318
|
+
// "children": [],
|
|
1319
|
+
// "cloid": null,
|
|
1320
|
+
// "coin": "ETH",
|
|
1321
|
+
// "isPositionTpsl": false,
|
|
1322
|
+
// "isTrigger": false,
|
|
1323
|
+
// "limitPx": "2000.0",
|
|
1324
|
+
// "oid": "3991946565",
|
|
1325
|
+
// "orderType": "Limit",
|
|
1326
|
+
// "origSz": "0.1",
|
|
1327
|
+
// "reduceOnly": false,
|
|
1328
|
+
// "side": "B",
|
|
1329
|
+
// "sz": "0.1",
|
|
1330
|
+
// "tif": "Gtc",
|
|
1331
|
+
// "timestamp": "1704346468838",
|
|
1332
|
+
// "triggerCondition": "N/A",
|
|
1333
|
+
// "triggerPx": "0.0"
|
|
1334
|
+
// },
|
|
1335
|
+
// "status": "open",
|
|
1336
|
+
// "statusTimestamp": "1704346468838"
|
|
1337
|
+
// },
|
|
1338
|
+
// "status": "order"
|
|
1339
|
+
// }
|
|
1340
|
+
//
|
|
1341
|
+
const data = this.safeDict(response, 'order');
|
|
1342
|
+
return this.parseOrder(data, market);
|
|
1343
|
+
}
|
|
1344
|
+
parseOrder(order, market = undefined) {
|
|
1345
|
+
//
|
|
1346
|
+
// fetchOpenOrders
|
|
1347
|
+
//
|
|
1348
|
+
// {
|
|
1349
|
+
// "coin": "ETH",
|
|
1350
|
+
// "limitPx": "2000.0",
|
|
1351
|
+
// "oid": 3991946565,
|
|
1352
|
+
// "origSz": "0.1",
|
|
1353
|
+
// "side": "B",
|
|
1354
|
+
// "sz": "0.1",
|
|
1355
|
+
// "timestamp": 1704346468838
|
|
1356
|
+
// }
|
|
1357
|
+
// fetchClosedorders
|
|
1358
|
+
// {
|
|
1359
|
+
// "cloid": null,
|
|
1360
|
+
// "closedPnl": "0.0",
|
|
1361
|
+
// "coin": "SOL",
|
|
1362
|
+
// "crossed": true,
|
|
1363
|
+
// "dir": "Open Long",
|
|
1364
|
+
// "fee": "0.003879",
|
|
1365
|
+
// "hash": "0x4a2647998682b7f07bc5040ab531e1011400f9a51bfa0346a0b41ebe510e8875",
|
|
1366
|
+
// "liquidationMarkPx": null,
|
|
1367
|
+
// "oid": "6463280784",
|
|
1368
|
+
// "px": "110.83",
|
|
1369
|
+
// "side": "B",
|
|
1370
|
+
// "startPosition": "1.64",
|
|
1371
|
+
// "sz": "0.1",
|
|
1372
|
+
// "tid": "232174667018988",
|
|
1373
|
+
// "time": "1709142268394"
|
|
1374
|
+
// }
|
|
1375
|
+
//
|
|
1376
|
+
// fetchOrder
|
|
1377
|
+
//
|
|
1378
|
+
// {
|
|
1379
|
+
// "order": {
|
|
1380
|
+
// "children": [],
|
|
1381
|
+
// "cloid": null,
|
|
1382
|
+
// "coin": "ETH",
|
|
1383
|
+
// "isPositionTpsl": false,
|
|
1384
|
+
// "isTrigger": false,
|
|
1385
|
+
// "limitPx": "2000.0",
|
|
1386
|
+
// "oid": "3991946565",
|
|
1387
|
+
// "orderType": "Limit",
|
|
1388
|
+
// "origSz": "0.1",
|
|
1389
|
+
// "reduceOnly": false,
|
|
1390
|
+
// "side": "B",
|
|
1391
|
+
// "sz": "0.1",
|
|
1392
|
+
// "tif": "Gtc",
|
|
1393
|
+
// "timestamp": "1704346468838",
|
|
1394
|
+
// "triggerCondition": "N/A",
|
|
1395
|
+
// "triggerPx": "0.0"
|
|
1396
|
+
// },
|
|
1397
|
+
// "status": "open",
|
|
1398
|
+
// "statusTimestamp": "1704346468838"
|
|
1399
|
+
// }
|
|
1400
|
+
//
|
|
1401
|
+
// createOrder
|
|
1402
|
+
//
|
|
1403
|
+
// {
|
|
1404
|
+
// "resting": {
|
|
1405
|
+
// "oid": 5063830287
|
|
1406
|
+
// }
|
|
1407
|
+
// }
|
|
1408
|
+
//
|
|
1409
|
+
// {
|
|
1410
|
+
// "filled":{
|
|
1411
|
+
// "totalSz":"0.1",
|
|
1412
|
+
// "avgPx":"100.84",
|
|
1413
|
+
// "oid":6195281425
|
|
1414
|
+
// }
|
|
1415
|
+
// }
|
|
1416
|
+
//
|
|
1417
|
+
let entry = this.safeDictN(order, ['order', 'resting', 'filled']);
|
|
1418
|
+
if (entry === undefined) {
|
|
1419
|
+
entry = order;
|
|
1420
|
+
}
|
|
1421
|
+
const coin = this.safeString(entry, 'coin');
|
|
1422
|
+
let marketId = undefined;
|
|
1423
|
+
if (coin !== undefined) {
|
|
1424
|
+
marketId = coin + '/USDC:USDC';
|
|
1425
|
+
}
|
|
1426
|
+
if (this.safeString(entry, 'id') === undefined) {
|
|
1427
|
+
market = this.safeMarket(marketId, undefined);
|
|
1428
|
+
}
|
|
1429
|
+
else {
|
|
1430
|
+
market = this.safeMarket(marketId, market);
|
|
1431
|
+
}
|
|
1432
|
+
const symbol = market['symbol'];
|
|
1433
|
+
const timestamp = this.safeInteger2(order, 'timestamp', 'statusTimestamp');
|
|
1434
|
+
const status = this.safeString(order, 'status');
|
|
1435
|
+
let side = this.safeString(entry, 'side');
|
|
1436
|
+
if (side !== undefined) {
|
|
1437
|
+
side = (side === 'A') ? 'sell' : 'buy';
|
|
1438
|
+
}
|
|
1439
|
+
return this.safeOrder({
|
|
1440
|
+
'info': order,
|
|
1441
|
+
'id': this.safeString(entry, 'oid'),
|
|
1442
|
+
'clientOrderId': this.safeString(entry, 'cloid'),
|
|
1443
|
+
'timestamp': timestamp,
|
|
1444
|
+
'datetime': this.iso8601(timestamp),
|
|
1445
|
+
'lastTradeTimestamp': undefined,
|
|
1446
|
+
'lastUpdateTimestamp': undefined,
|
|
1447
|
+
'symbol': symbol,
|
|
1448
|
+
'type': this.safeStringLower(entry, 'orderType'),
|
|
1449
|
+
'timeInForce': this.safeStringUpper(entry, 'tif'),
|
|
1450
|
+
'postOnly': undefined,
|
|
1451
|
+
'reduceOnly': this.safeBool(entry, 'reduceOnly'),
|
|
1452
|
+
'side': side,
|
|
1453
|
+
'price': this.safeNumber(entry, 'limitPx'),
|
|
1454
|
+
'triggerPrice': this.safeBool(entry, 'isTrigger') ? this.safeNumber(entry, 'triggerPx') : undefined,
|
|
1455
|
+
'amount': this.safeNumber2(entry, 'sz', 'totalSz'),
|
|
1456
|
+
'cost': undefined,
|
|
1457
|
+
'average': this.safeNumber(entry, 'avgPx'),
|
|
1458
|
+
'filled': undefined,
|
|
1459
|
+
'remaining': undefined,
|
|
1460
|
+
'status': this.parseOrderStatus(status),
|
|
1461
|
+
'fee': undefined,
|
|
1462
|
+
'trades': undefined,
|
|
1463
|
+
}, market);
|
|
1464
|
+
}
|
|
1465
|
+
parseOrderStatus(status) {
|
|
1466
|
+
const statuses = {
|
|
1467
|
+
'triggered': 'open',
|
|
1468
|
+
'filled': 'closed',
|
|
1469
|
+
};
|
|
1470
|
+
return this.safeString(statuses, status, status);
|
|
1471
|
+
}
|
|
1472
|
+
parseOrderType(status) {
|
|
1473
|
+
const statuses = {
|
|
1474
|
+
'stop limit': 'limit',
|
|
1475
|
+
'stop market': 'market',
|
|
1476
|
+
};
|
|
1477
|
+
return this.safeString(statuses, status, status);
|
|
1478
|
+
}
|
|
1479
|
+
async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
1480
|
+
/**
|
|
1481
|
+
* @method
|
|
1482
|
+
* @name hyperliquid#fetchMyTrades
|
|
1483
|
+
* @description fetch all trades made by the user
|
|
1484
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-fills
|
|
1485
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-fills-by-time
|
|
1486
|
+
* @param {string} symbol unified market symbol
|
|
1487
|
+
* @param {int} [since] the earliest time in ms to fetch trades for
|
|
1488
|
+
* @param {int} [limit] the maximum number of trades structures to retrieve
|
|
1489
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1490
|
+
* @param {int} [params.until] timestamp in ms of the latest trade
|
|
1491
|
+
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
|
|
1492
|
+
*/
|
|
1493
|
+
let userAddress = undefined;
|
|
1494
|
+
[userAddress, params] = this.handlePublicAddress('fetchMyTrades', params);
|
|
1495
|
+
await this.loadMarkets();
|
|
1496
|
+
const market = this.safeMarket(symbol);
|
|
1497
|
+
const request = {
|
|
1498
|
+
'user': userAddress,
|
|
1499
|
+
};
|
|
1500
|
+
if (since !== undefined) {
|
|
1501
|
+
request['type'] = 'userFillsByTime';
|
|
1502
|
+
request['startTime'] = since;
|
|
1503
|
+
}
|
|
1504
|
+
else {
|
|
1505
|
+
request['type'] = 'userFills';
|
|
1506
|
+
}
|
|
1507
|
+
const until = this.safeInteger(params, 'until');
|
|
1508
|
+
params = this.omit(params, 'until');
|
|
1509
|
+
if (until !== undefined) {
|
|
1510
|
+
request['endTime'] = until;
|
|
1511
|
+
}
|
|
1512
|
+
const response = await this.publicPostInfo(this.extend(request, params));
|
|
1513
|
+
//
|
|
1514
|
+
// [
|
|
1515
|
+
// {
|
|
1516
|
+
// "closedPnl": "0.19343",
|
|
1517
|
+
// "coin": "ETH",
|
|
1518
|
+
// "crossed": true,
|
|
1519
|
+
// "dir": "Close Long",
|
|
1520
|
+
// "fee": "0.050062",
|
|
1521
|
+
// "hash": "0x09d77c96791e98b5775a04092584ab010d009445119c71e4005c0d634ea322bc",
|
|
1522
|
+
// "liquidationMarkPx": null,
|
|
1523
|
+
// "oid": 3929354691,
|
|
1524
|
+
// "px": "2381.1",
|
|
1525
|
+
// "side": "A",
|
|
1526
|
+
// "startPosition": "0.0841",
|
|
1527
|
+
// "sz": "0.0841",
|
|
1528
|
+
// "tid": 128423918764978,
|
|
1529
|
+
// "time": 1704262888911
|
|
1530
|
+
// }
|
|
1531
|
+
// ]
|
|
1532
|
+
//
|
|
1533
|
+
return this.parseTrades(response, market, since, limit);
|
|
1534
|
+
}
|
|
1535
|
+
parseTrade(trade, market = undefined) {
|
|
1536
|
+
//
|
|
1537
|
+
// {
|
|
1538
|
+
// "closedPnl": "0.19343",
|
|
1539
|
+
// "coin": "ETH",
|
|
1540
|
+
// "crossed": true,
|
|
1541
|
+
// "dir": "Close Long",
|
|
1542
|
+
// "fee": "0.050062",
|
|
1543
|
+
// "hash": "0x09d77c96791e98b5775a04092584ab010d009445119c71e4005c0d634ea322bc",
|
|
1544
|
+
// "liquidationMarkPx": null,
|
|
1545
|
+
// "oid": 3929354691,
|
|
1546
|
+
// "px": "2381.1",
|
|
1547
|
+
// "side": "A",
|
|
1548
|
+
// "startPosition": "0.0841",
|
|
1549
|
+
// "sz": "0.0841",
|
|
1550
|
+
// "tid": 128423918764978,
|
|
1551
|
+
// "time": 1704262888911
|
|
1552
|
+
// }
|
|
1553
|
+
//
|
|
1554
|
+
const timestamp = this.safeInteger(trade, 'time');
|
|
1555
|
+
const price = this.safeString(trade, 'px');
|
|
1556
|
+
const amount = this.safeString(trade, 'sz');
|
|
1557
|
+
const coin = this.safeString(trade, 'coin');
|
|
1558
|
+
const marketId = coin + '/USDC:USDC';
|
|
1559
|
+
market = this.safeMarket(marketId, undefined);
|
|
1560
|
+
const symbol = market['symbol'];
|
|
1561
|
+
const id = this.safeString(trade, 'tid');
|
|
1562
|
+
let side = this.safeString(trade, 'side');
|
|
1563
|
+
if (side !== undefined) {
|
|
1564
|
+
side = (side === 'A') ? 'sell' : 'buy';
|
|
1565
|
+
}
|
|
1566
|
+
const fee = this.safeString(trade, 'fee');
|
|
1567
|
+
return this.safeTrade({
|
|
1568
|
+
'info': trade,
|
|
1569
|
+
'timestamp': timestamp,
|
|
1570
|
+
'datetime': this.iso8601(timestamp),
|
|
1571
|
+
'symbol': symbol,
|
|
1572
|
+
'id': id,
|
|
1573
|
+
'order': this.safeString(trade, 'oid'),
|
|
1574
|
+
'type': undefined,
|
|
1575
|
+
'side': side,
|
|
1576
|
+
'takerOrMaker': undefined,
|
|
1577
|
+
'price': price,
|
|
1578
|
+
'amount': amount,
|
|
1579
|
+
'cost': undefined,
|
|
1580
|
+
'fee': { 'cost': fee, 'currency': 'USDC' },
|
|
1581
|
+
}, market);
|
|
1582
|
+
}
|
|
1583
|
+
async fetchPosition(symbol, params = {}) {
|
|
1584
|
+
/**
|
|
1585
|
+
* @method
|
|
1586
|
+
* @name hyperliquid#fetchPosition
|
|
1587
|
+
* @description fetch data on an open position
|
|
1588
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-state
|
|
1589
|
+
* @param {string} symbol unified market symbol of the market the position is held in
|
|
1590
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1591
|
+
* @param {string} [params.user] user address, will default to this.walletAddress if not provided
|
|
1592
|
+
* @returns {object} a [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
|
|
1593
|
+
*/
|
|
1594
|
+
const positions = await this.fetchPositions([symbol], params);
|
|
1595
|
+
return this.safeDict(positions, 0, {});
|
|
1596
|
+
}
|
|
1597
|
+
async fetchPositions(symbols = undefined, params = {}) {
|
|
1598
|
+
/**
|
|
1599
|
+
* @method
|
|
1600
|
+
* @name hyperliquid#fetchPositions
|
|
1601
|
+
* @description fetch all open positions
|
|
1602
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-state
|
|
1603
|
+
* @param {string[]} [symbols] list of unified market symbols
|
|
1604
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1605
|
+
* @param {string} [params.user] user address, will default to this.walletAddress if not provided
|
|
1606
|
+
* @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
|
|
1607
|
+
*/
|
|
1608
|
+
await this.loadMarkets();
|
|
1609
|
+
let userAddress = undefined;
|
|
1610
|
+
[userAddress, params] = this.handlePublicAddress('fetchPositions', params);
|
|
1611
|
+
symbols = this.marketSymbols(symbols);
|
|
1612
|
+
const request = {
|
|
1613
|
+
'type': 'clearinghouseState',
|
|
1614
|
+
'user': userAddress,
|
|
1615
|
+
};
|
|
1616
|
+
const response = await this.publicPostInfo(this.extend(request, params));
|
|
1617
|
+
//
|
|
1618
|
+
// {
|
|
1619
|
+
// "assetPositions": [
|
|
1620
|
+
// {
|
|
1621
|
+
// "position": {
|
|
1622
|
+
// "coin": "ETH",
|
|
1623
|
+
// "cumFunding": {
|
|
1624
|
+
// "allTime": "0.0",
|
|
1625
|
+
// "sinceChange": "0.0",
|
|
1626
|
+
// "sinceOpen": "0.0"
|
|
1627
|
+
// },
|
|
1628
|
+
// "entryPx": "2213.9",
|
|
1629
|
+
// "leverage": {
|
|
1630
|
+
// "rawUsd": "-475.23904",
|
|
1631
|
+
// "type": "isolated",
|
|
1632
|
+
// "value": "20"
|
|
1633
|
+
// },
|
|
1634
|
+
// "liquidationPx": "2125.00856238",
|
|
1635
|
+
// "marginUsed": "24.88097",
|
|
1636
|
+
// "maxLeverage": "50",
|
|
1637
|
+
// "positionValue": "500.12001",
|
|
1638
|
+
// "returnOnEquity": "0.0",
|
|
1639
|
+
// "szi": "0.2259",
|
|
1640
|
+
// "unrealizedPnl": "0.0"
|
|
1641
|
+
// },
|
|
1642
|
+
// "type": "oneWay"
|
|
1643
|
+
// }
|
|
1644
|
+
// ],
|
|
1645
|
+
// "crossMaintenanceMarginUsed": "0.0",
|
|
1646
|
+
// "crossMarginSummary": {
|
|
1647
|
+
// "accountValue": "100.0",
|
|
1648
|
+
// "totalMarginUsed": "0.0",
|
|
1649
|
+
// "totalNtlPos": "0.0",
|
|
1650
|
+
// "totalRawUsd": "100.0"
|
|
1651
|
+
// },
|
|
1652
|
+
// "marginSummary": {
|
|
1653
|
+
// "accountValue": "100.0",
|
|
1654
|
+
// "totalMarginUsed": "0.0",
|
|
1655
|
+
// "totalNtlPos": "0.0",
|
|
1656
|
+
// "totalRawUsd": "100.0"
|
|
1657
|
+
// },
|
|
1658
|
+
// "time": "1704261007014",
|
|
1659
|
+
// "withdrawable": "100.0"
|
|
1660
|
+
// }
|
|
1661
|
+
//
|
|
1662
|
+
const data = this.safeList(response, 'assetPositions', []);
|
|
1663
|
+
const result = [];
|
|
1664
|
+
for (let i = 0; i < data.length; i++) {
|
|
1665
|
+
result.push(this.parsePosition(data[i], undefined));
|
|
1666
|
+
}
|
|
1667
|
+
return this.filterByArrayPositions(result, 'symbol', symbols, false);
|
|
1668
|
+
}
|
|
1669
|
+
parsePosition(position, market = undefined) {
|
|
1670
|
+
//
|
|
1671
|
+
// {
|
|
1672
|
+
// "position": {
|
|
1673
|
+
// "coin": "ETH",
|
|
1674
|
+
// "cumFunding": {
|
|
1675
|
+
// "allTime": "0.0",
|
|
1676
|
+
// "sinceChange": "0.0",
|
|
1677
|
+
// "sinceOpen": "0.0"
|
|
1678
|
+
// },
|
|
1679
|
+
// "entryPx": "2213.9",
|
|
1680
|
+
// "leverage": {
|
|
1681
|
+
// "rawUsd": "-475.23904",
|
|
1682
|
+
// "type": "isolated",
|
|
1683
|
+
// "value": "20"
|
|
1684
|
+
// },
|
|
1685
|
+
// "liquidationPx": "2125.00856238",
|
|
1686
|
+
// "marginUsed": "24.88097",
|
|
1687
|
+
// "maxLeverage": "50",
|
|
1688
|
+
// "positionValue": "500.12001",
|
|
1689
|
+
// "returnOnEquity": "0.0",
|
|
1690
|
+
// "szi": "0.2259",
|
|
1691
|
+
// "unrealizedPnl": "0.0"
|
|
1692
|
+
// },
|
|
1693
|
+
// "type": "oneWay"
|
|
1694
|
+
// }
|
|
1695
|
+
//
|
|
1696
|
+
const entry = this.safeDict(position, 'position', {});
|
|
1697
|
+
const coin = this.safeString(entry, 'coin');
|
|
1698
|
+
const marketId = coin + '/USDC:USDC';
|
|
1699
|
+
market = this.safeMarket(marketId, undefined);
|
|
1700
|
+
const symbol = market['symbol'];
|
|
1701
|
+
const leverage = this.safeDict(entry, 'leverage', {});
|
|
1702
|
+
const isIsolated = (this.safeString(leverage, 'type') === 'isolated');
|
|
1703
|
+
const quantity = this.safeNumber(leverage, 'rawUsd');
|
|
1704
|
+
let side = undefined;
|
|
1705
|
+
if (quantity !== undefined) {
|
|
1706
|
+
side = (quantity > 0) ? 'short' : 'long';
|
|
1707
|
+
}
|
|
1708
|
+
const unrealizedPnl = this.safeNumber(entry, 'unrealizedPnl');
|
|
1709
|
+
const initialMargin = this.safeNumber(entry, 'marginUsed');
|
|
1710
|
+
const percentage = unrealizedPnl / initialMargin * 100;
|
|
1711
|
+
return this.safePosition({
|
|
1712
|
+
'info': position,
|
|
1713
|
+
'id': undefined,
|
|
1714
|
+
'symbol': symbol,
|
|
1715
|
+
'timestamp': undefined,
|
|
1716
|
+
'datetime': undefined,
|
|
1717
|
+
'isolated': isIsolated,
|
|
1718
|
+
'hedged': undefined,
|
|
1719
|
+
'side': side,
|
|
1720
|
+
'contracts': this.parseNumber(quantity),
|
|
1721
|
+
'contractSize': undefined,
|
|
1722
|
+
'entryPrice': this.safeNumber(entry, 'entryPx'),
|
|
1723
|
+
'markPrice': undefined,
|
|
1724
|
+
'notional': this.safeNumber(entry, 'positionValue'),
|
|
1725
|
+
'leverage': this.safeNumber(leverage, 'value'),
|
|
1726
|
+
'collateral': undefined,
|
|
1727
|
+
'initialMargin': initialMargin,
|
|
1728
|
+
'maintenanceMargin': undefined,
|
|
1729
|
+
'initialMarginPercentage': undefined,
|
|
1730
|
+
'maintenanceMarginPercentage': undefined,
|
|
1731
|
+
'unrealizedPnl': unrealizedPnl,
|
|
1732
|
+
'liquidationPrice': this.safeNumber(entry, 'liquidationPx'),
|
|
1733
|
+
'marginMode': undefined,
|
|
1734
|
+
'percentage': percentage,
|
|
1735
|
+
});
|
|
1736
|
+
}
|
|
1737
|
+
async setMarginMode(marginMode, symbol = undefined, params = {}) {
|
|
1738
|
+
/**
|
|
1739
|
+
* @method
|
|
1740
|
+
* @name hyperliquid#setMarginMode
|
|
1741
|
+
* @description set margin mode (symbol)
|
|
1742
|
+
* @param {string} marginMode margin mode must be either [isolated, cross]
|
|
1743
|
+
* @param {string} symbol unified market symbol of the market the position is held in, default is undefined
|
|
1744
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1745
|
+
* @param {string} [params.leverage] the rate of leverage, is required if setting trade mode (symbol)
|
|
1746
|
+
* @returns {object} response from the exchange
|
|
1747
|
+
*/
|
|
1748
|
+
if (symbol === undefined) {
|
|
1749
|
+
throw new ArgumentsRequired(this.id + ' setMarginMode() requires a symbol argument');
|
|
1750
|
+
}
|
|
1751
|
+
await this.loadMarkets();
|
|
1752
|
+
const market = this.market(symbol);
|
|
1753
|
+
const leverage = this.safeInteger(params, 'leverage');
|
|
1754
|
+
if (leverage === undefined) {
|
|
1755
|
+
throw new ArgumentsRequired(this.id + ' setMarginMode() requires a leverage parameter');
|
|
1756
|
+
}
|
|
1757
|
+
const asset = this.parseToInt(market['baseId']);
|
|
1758
|
+
const isCross = (marginMode === 'isolated');
|
|
1759
|
+
const nonce = this.milliseconds();
|
|
1760
|
+
params = this.omit(params, ['leverage']);
|
|
1761
|
+
const updateAction = {
|
|
1762
|
+
'type': 'updateLeverage',
|
|
1763
|
+
'asset': asset,
|
|
1764
|
+
'isCross': isCross,
|
|
1765
|
+
'leverage': leverage,
|
|
1766
|
+
};
|
|
1767
|
+
const vaultAddress = this.safeString(params, 'vaultAddress');
|
|
1768
|
+
const signature = this.signL1Action(updateAction, nonce, vaultAddress);
|
|
1769
|
+
const request = {
|
|
1770
|
+
'action': updateAction,
|
|
1771
|
+
'nonce': nonce,
|
|
1772
|
+
'signature': signature,
|
|
1773
|
+
// 'vaultAddress': vaultAddress,
|
|
1774
|
+
};
|
|
1775
|
+
const response = await this.privatePostExchange(this.extend(request, params));
|
|
1776
|
+
//
|
|
1777
|
+
// {
|
|
1778
|
+
// 'response': {
|
|
1779
|
+
// 'type': 'default'
|
|
1780
|
+
// },
|
|
1781
|
+
// 'status': 'ok'
|
|
1782
|
+
// }
|
|
1783
|
+
//
|
|
1784
|
+
return response;
|
|
1785
|
+
}
|
|
1786
|
+
async setLeverage(leverage, symbol = undefined, params = {}) {
|
|
1787
|
+
/**
|
|
1788
|
+
* @method
|
|
1789
|
+
* @name hyperliquid#setLeverage
|
|
1790
|
+
* @description set the level of leverage for a market
|
|
1791
|
+
* @param {float} leverage the rate of leverage
|
|
1792
|
+
* @param {string} symbol unified market symbol
|
|
1793
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1794
|
+
* @param {string} [params.marginMode] margin mode must be either [isolated, cross], default is cross
|
|
1795
|
+
* @returns {object} response from the exchange
|
|
1796
|
+
*/
|
|
1797
|
+
if (symbol === undefined) {
|
|
1798
|
+
throw new ArgumentsRequired(this.id + ' setLeverage() requires a symbol argument');
|
|
1799
|
+
}
|
|
1800
|
+
await this.loadMarkets();
|
|
1801
|
+
const market = this.market(symbol);
|
|
1802
|
+
const marginMode = this.safeString(params, 'marginMode', 'cross');
|
|
1803
|
+
const isCross = (marginMode === 'cross');
|
|
1804
|
+
const asset = this.parseToInt(market['baseId']);
|
|
1805
|
+
const nonce = this.milliseconds();
|
|
1806
|
+
params = this.omit(params, 'marginMode');
|
|
1807
|
+
const updateAction = {
|
|
1808
|
+
'type': 'updateLeverage',
|
|
1809
|
+
'asset': asset,
|
|
1810
|
+
'isCross': isCross,
|
|
1811
|
+
'leverage': leverage,
|
|
1812
|
+
};
|
|
1813
|
+
const vaultAddress = this.safeString(params, 'vaultAddress');
|
|
1814
|
+
const signature = this.signL1Action(updateAction, nonce, vaultAddress);
|
|
1815
|
+
const request = {
|
|
1816
|
+
'action': updateAction,
|
|
1817
|
+
'nonce': nonce,
|
|
1818
|
+
'signature': signature,
|
|
1819
|
+
// 'vaultAddress': vaultAddress,
|
|
1820
|
+
};
|
|
1821
|
+
const response = await this.privatePostExchange(this.extend(request, params));
|
|
1822
|
+
//
|
|
1823
|
+
// {
|
|
1824
|
+
// 'response': {
|
|
1825
|
+
// 'type': 'default'
|
|
1826
|
+
// },
|
|
1827
|
+
// 'status': 'ok'
|
|
1828
|
+
// }
|
|
1829
|
+
//
|
|
1830
|
+
return response;
|
|
1831
|
+
}
|
|
1832
|
+
async addMargin(symbol, amount, params = {}) {
|
|
1833
|
+
/**
|
|
1834
|
+
* @method
|
|
1835
|
+
* @name hyperliquid#addMargin
|
|
1836
|
+
* @description add margin
|
|
1837
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#update-isolated-margin
|
|
1838
|
+
* @param {string} symbol unified market symbol
|
|
1839
|
+
* @param {float} amount amount of margin to add
|
|
1840
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1841
|
+
* @returns {object} a [margin structure]{@link https://docs.ccxt.com/#/?id=add-margin-structure}
|
|
1842
|
+
*/
|
|
1843
|
+
return await this.modifyMarginHelper(symbol, amount, 'add', params);
|
|
1844
|
+
}
|
|
1845
|
+
async reduceMargin(symbol, amount, params = {}) {
|
|
1846
|
+
/**
|
|
1847
|
+
* @method
|
|
1848
|
+
* @name hyperliquid#reduceMargin
|
|
1849
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#update-isolated-margin
|
|
1850
|
+
* @description remove margin from a position
|
|
1851
|
+
* @param {string} symbol unified market symbol
|
|
1852
|
+
* @param {float} amount the amount of margin to remove
|
|
1853
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1854
|
+
* @returns {object} a [margin structure]{@link https://docs.ccxt.com/#/?id=reduce-margin-structure}
|
|
1855
|
+
*/
|
|
1856
|
+
return await this.modifyMarginHelper(symbol, amount, 'reduce', params);
|
|
1857
|
+
}
|
|
1858
|
+
async modifyMarginHelper(symbol, amount, type, params = {}) {
|
|
1859
|
+
await this.loadMarkets();
|
|
1860
|
+
const market = this.market(symbol);
|
|
1861
|
+
const asset = this.parseToInt(market['baseId']);
|
|
1862
|
+
let sz = this.parseToInt(Precise.stringMul(this.amountToPrecision(symbol, amount), '1000000'));
|
|
1863
|
+
if (type === 'reduce') {
|
|
1864
|
+
sz = -sz;
|
|
1865
|
+
}
|
|
1866
|
+
const nonce = this.milliseconds();
|
|
1867
|
+
const updateAction = {
|
|
1868
|
+
'type': 'updateIsolatedMargin',
|
|
1869
|
+
'asset': asset,
|
|
1870
|
+
'isBuy': true,
|
|
1871
|
+
'ntli': sz,
|
|
1872
|
+
};
|
|
1873
|
+
const vaultAddress = this.safeString(params, 'vaultAddress');
|
|
1874
|
+
const signature = this.signL1Action(updateAction, nonce, vaultAddress);
|
|
1875
|
+
const request = {
|
|
1876
|
+
'action': updateAction,
|
|
1877
|
+
'nonce': nonce,
|
|
1878
|
+
'signature': signature,
|
|
1879
|
+
// 'vaultAddress': vaultAddress,
|
|
1880
|
+
};
|
|
1881
|
+
const response = await this.privatePostExchange(this.extend(request, params));
|
|
1882
|
+
//
|
|
1883
|
+
// {
|
|
1884
|
+
// 'response': {
|
|
1885
|
+
// 'type': 'default'
|
|
1886
|
+
// },
|
|
1887
|
+
// 'status': 'ok'
|
|
1888
|
+
// }
|
|
1889
|
+
//
|
|
1890
|
+
return response;
|
|
1891
|
+
// return this.extend (this.parseMarginModification (response, market), {
|
|
1892
|
+
// 'code': code,
|
|
1893
|
+
// });
|
|
1894
|
+
}
|
|
1895
|
+
async transfer(code, amount, fromAccount, toAccount, params = {}) {
|
|
1896
|
+
/**
|
|
1897
|
+
* @method
|
|
1898
|
+
* @name hyperliquid#transfer
|
|
1899
|
+
* @description transfer currency internally between wallets on the same account
|
|
1900
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#l1-usdc-transfer
|
|
1901
|
+
* @param {string} code unified currency code
|
|
1902
|
+
* @param {float} amount amount to transfer
|
|
1903
|
+
* @param {string} fromAccount account to transfer from
|
|
1904
|
+
* @param {string} toAccount account to transfer to
|
|
1905
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1906
|
+
* @returns {object} a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
|
|
1907
|
+
*/
|
|
1908
|
+
this.checkRequiredCredentials();
|
|
1909
|
+
await this.loadMarkets();
|
|
1910
|
+
this.checkAddress(toAccount);
|
|
1911
|
+
if (code !== undefined) {
|
|
1912
|
+
code = code.toUpperCase();
|
|
1913
|
+
if (code !== 'USDC') {
|
|
1914
|
+
throw new NotSupported(this.id + 'withdraw() only support USDC');
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
const isSandboxMode = this.safeBool(this.options, 'sandboxMode');
|
|
1918
|
+
const nonce = this.milliseconds();
|
|
1919
|
+
const payload = {
|
|
1920
|
+
'destination': toAccount,
|
|
1921
|
+
'amount': amount.toString(),
|
|
1922
|
+
'time': nonce,
|
|
1923
|
+
};
|
|
1924
|
+
const sig = this.buildTransferSig(payload);
|
|
1925
|
+
const request = {
|
|
1926
|
+
'action': {
|
|
1927
|
+
'chain': (isSandboxMode) ? 'ArbitrumTestnet' : 'Arbitrum',
|
|
1928
|
+
'payload': payload,
|
|
1929
|
+
'type': 'usdTransfer',
|
|
1930
|
+
},
|
|
1931
|
+
'nonce': nonce,
|
|
1932
|
+
'signature': sig,
|
|
1933
|
+
};
|
|
1934
|
+
const response = await this.privatePostExchange(this.extend(request, params));
|
|
1935
|
+
return response;
|
|
1936
|
+
}
|
|
1937
|
+
async withdraw(code, amount, address, tag = undefined, params = {}) {
|
|
1938
|
+
/**
|
|
1939
|
+
* @method
|
|
1940
|
+
* @name hyperliquid#withdraw
|
|
1941
|
+
* @description make a withdrawal (only support USDC)
|
|
1942
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#initiate-a-withdrawal-request
|
|
1943
|
+
* @param {string} code unified currency code
|
|
1944
|
+
* @param {float} amount the amount to withdraw
|
|
1945
|
+
* @param {string} address the address to withdraw to
|
|
1946
|
+
* @param {string} tag
|
|
1947
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1948
|
+
* @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
|
|
1949
|
+
*/
|
|
1950
|
+
this.checkRequiredCredentials();
|
|
1951
|
+
await this.loadMarkets();
|
|
1952
|
+
this.checkAddress(address);
|
|
1953
|
+
if (code !== undefined) {
|
|
1954
|
+
code = code.toUpperCase();
|
|
1955
|
+
if (code !== 'USDC') {
|
|
1956
|
+
throw new NotSupported(this.id + 'withdraw() only support USDC');
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
const isSandboxMode = this.safeBool(this.options, 'sandboxMode');
|
|
1960
|
+
const nonce = this.milliseconds();
|
|
1961
|
+
const payload = {
|
|
1962
|
+
'destination': address,
|
|
1963
|
+
'usd': amount.toString(),
|
|
1964
|
+
'time': nonce,
|
|
1965
|
+
};
|
|
1966
|
+
const sig = this.buildWithdrawSig(payload);
|
|
1967
|
+
const request = {
|
|
1968
|
+
'action': {
|
|
1969
|
+
'chain': (isSandboxMode) ? 'ArbitrumTestnet' : 'Arbitrum',
|
|
1970
|
+
'payload': payload,
|
|
1971
|
+
'type': 'withdraw2',
|
|
1972
|
+
},
|
|
1973
|
+
'nonce': nonce,
|
|
1974
|
+
'signature': sig,
|
|
1975
|
+
};
|
|
1976
|
+
const response = await this.privatePostExchange(this.extend(request, params));
|
|
1977
|
+
return response;
|
|
1978
|
+
}
|
|
1979
|
+
handlePublicAddress(methodName, params) {
|
|
1980
|
+
let userAux = undefined;
|
|
1981
|
+
[userAux, params] = this.handleOptionAndParams(params, methodName, 'user');
|
|
1982
|
+
let user = userAux;
|
|
1983
|
+
[user, params] = this.handleOptionAndParams(params, methodName, 'address', userAux);
|
|
1984
|
+
if (user !== undefined) {
|
|
1985
|
+
return [user, params];
|
|
1986
|
+
}
|
|
1987
|
+
if (this.walletAddress !== undefined) {
|
|
1988
|
+
return [this.walletAddress, params];
|
|
1989
|
+
}
|
|
1990
|
+
throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a user parameter inside \'params\' or the wallet address set');
|
|
1991
|
+
}
|
|
1992
|
+
handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
|
|
1993
|
+
if (!response) {
|
|
1994
|
+
return undefined; // fallback to default error handler
|
|
1995
|
+
}
|
|
1996
|
+
// {"status":"err","response":"User or API Wallet 0xb8a6f8b26223de27c31938d56e470a5b832703a5 does not exist."}
|
|
1997
|
+
//
|
|
1998
|
+
// {
|
|
1999
|
+
// status: 'ok',
|
|
2000
|
+
// response: { type: 'order', data: { statuses: [ { error: 'Insufficient margin to place order. asset=4' } ] } }
|
|
2001
|
+
// }
|
|
2002
|
+
//
|
|
2003
|
+
const status = this.safeString(response, 'status', '');
|
|
2004
|
+
let message = undefined;
|
|
2005
|
+
if (status === 'err') {
|
|
2006
|
+
message = this.safeString(response, 'response');
|
|
2007
|
+
}
|
|
2008
|
+
else {
|
|
2009
|
+
const responsePayload = this.safeDict(response, 'response', {});
|
|
2010
|
+
const data = this.safeDict(responsePayload, 'data', {});
|
|
2011
|
+
const statuses = this.safeList(data, 'statuses', []);
|
|
2012
|
+
const firstStatus = this.safeDict(statuses, 0);
|
|
2013
|
+
message = this.safeString(firstStatus, 'error');
|
|
2014
|
+
}
|
|
2015
|
+
const feedback = this.id + ' ' + body;
|
|
2016
|
+
const nonEmptyMessage = ((message !== undefined) && (message !== ''));
|
|
2017
|
+
if (nonEmptyMessage) {
|
|
2018
|
+
this.throwExactlyMatchedException(this.exceptions['exact'], message, feedback);
|
|
2019
|
+
this.throwBroadlyMatchedException(this.exceptions['broad'], message, feedback);
|
|
2020
|
+
}
|
|
2021
|
+
if (nonEmptyMessage) {
|
|
2022
|
+
throw new ExchangeError(feedback); // unknown message
|
|
2023
|
+
}
|
|
2024
|
+
return undefined;
|
|
2025
|
+
}
|
|
2026
|
+
sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
|
2027
|
+
const url = this.implodeHostname(this.urls['api'][api]) + '/' + path;
|
|
2028
|
+
if (method === 'POST') {
|
|
2029
|
+
headers = {
|
|
2030
|
+
'Content-Type': 'application/json',
|
|
2031
|
+
};
|
|
2032
|
+
body = this.json(params);
|
|
2033
|
+
}
|
|
2034
|
+
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
|
|
2035
|
+
}
|
|
2036
|
+
}
|