@nktkas/hyperliquid 0.25.0-beta.1 → 0.25.0-beta.3

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.
Files changed (284) hide show
  1. package/README.md +64 -16
  2. package/esm/bin/cli.d.ts +3 -0
  3. package/esm/bin/cli.d.ts.map +1 -0
  4. package/esm/bin/cli.js +452 -0
  5. package/esm/bin/cli.js.map +1 -0
  6. package/{script/src/errors.d.ts → esm/src/_errors.d.ts} +1 -1
  7. package/esm/src/_errors.d.ts.map +1 -0
  8. package/esm/src/{errors.js → _errors.js} +1 -0
  9. package/esm/src/_errors.js.map +1 -0
  10. package/esm/src/clients/exchange.d.ts +4 -11
  11. package/esm/src/clients/exchange.d.ts.map +1 -1
  12. package/esm/src/clients/exchange.js +8 -9
  13. package/esm/src/clients/exchange.js.map +1 -0
  14. package/esm/src/clients/info.d.ts +86 -2
  15. package/esm/src/clients/info.d.ts.map +1 -1
  16. package/esm/src/clients/info.js +103 -1
  17. package/esm/src/clients/info.js.map +1 -0
  18. package/esm/src/clients/multiSign.d.ts +1 -1
  19. package/esm/src/clients/multiSign.d.ts.map +1 -1
  20. package/esm/src/clients/multiSign.js +3 -2
  21. package/esm/src/clients/multiSign.js.map +1 -0
  22. package/esm/src/clients/subscription.js +1 -0
  23. package/esm/src/clients/subscription.js.map +1 -0
  24. package/esm/src/mod.d.ts +21 -0
  25. package/esm/src/mod.d.ts.map +1 -0
  26. package/esm/src/mod.js +14 -0
  27. package/esm/src/mod.js.map +1 -0
  28. package/esm/src/schemas/_base.d.ts +11 -3
  29. package/esm/src/schemas/_base.d.ts.map +1 -1
  30. package/esm/src/schemas/_base.js +30 -2
  31. package/esm/src/schemas/_base.js.map +1 -0
  32. package/esm/src/schemas/exchange/requests.d.ts +1872 -1872
  33. package/esm/src/schemas/exchange/requests.d.ts.map +1 -1
  34. package/esm/src/schemas/exchange/requests.js +277 -281
  35. package/esm/src/schemas/exchange/requests.js.map +1 -0
  36. package/esm/src/schemas/exchange/responses.d.ts +51 -51
  37. package/esm/src/schemas/exchange/responses.js +55 -54
  38. package/esm/src/schemas/exchange/responses.js.map +1 -0
  39. package/esm/src/schemas/explorer/requests.d.ts +5 -5
  40. package/esm/src/schemas/explorer/requests.js +6 -5
  41. package/esm/src/schemas/explorer/requests.js.map +1 -0
  42. package/esm/src/schemas/explorer/responses.d.ts +10 -10
  43. package/esm/src/schemas/explorer/responses.js +12 -11
  44. package/esm/src/schemas/explorer/responses.js.map +1 -0
  45. package/esm/src/schemas/info/accounts.d.ts +1042 -296
  46. package/esm/src/schemas/info/accounts.d.ts.map +1 -1
  47. package/esm/src/schemas/info/accounts.js +154 -109
  48. package/esm/src/schemas/info/accounts.js.map +1 -0
  49. package/esm/src/schemas/info/assets.d.ts +130 -101
  50. package/esm/src/schemas/info/assets.d.ts.map +1 -1
  51. package/esm/src/schemas/info/assets.js +69 -49
  52. package/esm/src/schemas/info/assets.js.map +1 -0
  53. package/esm/src/schemas/info/markets.d.ts +35 -18
  54. package/esm/src/schemas/info/markets.d.ts.map +1 -1
  55. package/esm/src/schemas/info/markets.js +27 -15
  56. package/esm/src/schemas/info/markets.js.map +1 -0
  57. package/esm/src/schemas/info/orders.d.ts +151 -151
  58. package/esm/src/schemas/info/orders.js +37 -36
  59. package/esm/src/schemas/info/orders.js.map +1 -0
  60. package/esm/src/schemas/info/requests.d.ts +145 -88
  61. package/esm/src/schemas/info/requests.d.ts.map +1 -1
  62. package/esm/src/schemas/info/requests.js +116 -73
  63. package/esm/src/schemas/info/requests.js.map +1 -0
  64. package/esm/src/schemas/info/validators.d.ts +60 -39
  65. package/esm/src/schemas/info/validators.d.ts.map +1 -1
  66. package/esm/src/schemas/info/validators.js +40 -26
  67. package/esm/src/schemas/info/validators.js.map +1 -0
  68. package/esm/src/schemas/info/vaults.d.ts +59 -59
  69. package/esm/src/schemas/info/vaults.js +20 -19
  70. package/esm/src/schemas/info/vaults.js.map +1 -0
  71. package/esm/src/schemas/mod.d.ts +4 -3
  72. package/esm/src/schemas/mod.d.ts.map +1 -1
  73. package/esm/src/schemas/mod.js +5 -3
  74. package/esm/src/schemas/mod.js.map +1 -0
  75. package/esm/src/schemas/subscriptions/requests.d.ts +23 -23
  76. package/esm/src/schemas/subscriptions/requests.d.ts.map +1 -1
  77. package/esm/src/schemas/subscriptions/requests.js +25 -24
  78. package/esm/src/schemas/subscriptions/requests.js.map +1 -0
  79. package/esm/src/schemas/subscriptions/responses.d.ts +547 -547
  80. package/esm/src/schemas/subscriptions/responses.js +41 -40
  81. package/esm/src/schemas/subscriptions/responses.js.map +1 -0
  82. package/esm/src/signing/mod.d.ts +1 -1
  83. package/esm/src/signing/mod.d.ts.map +1 -1
  84. package/esm/src/signing/mod.js +3 -2
  85. package/esm/src/signing/mod.js.map +1 -0
  86. package/esm/src/signing/signTypedData/ethers.d.ts.map +1 -0
  87. package/esm/src/signing/{_signTypedData → signTypedData}/ethers.js +1 -0
  88. package/esm/src/signing/signTypedData/ethers.js.map +1 -0
  89. package/esm/src/signing/signTypedData/mod.d.ts.map +1 -0
  90. package/esm/src/signing/{_signTypedData → signTypedData}/mod.js +1 -0
  91. package/esm/src/signing/signTypedData/mod.js.map +1 -0
  92. package/esm/src/signing/signTypedData/private_key.d.ts.map +1 -0
  93. package/esm/src/signing/{_signTypedData → signTypedData}/private_key.js +10 -8
  94. package/esm/src/signing/signTypedData/private_key.js.map +1 -0
  95. package/esm/src/signing/signTypedData/viem.d.ts.map +1 -0
  96. package/esm/src/signing/{_signTypedData → signTypedData}/viem.js +1 -0
  97. package/esm/src/signing/signTypedData/viem.js.map +1 -0
  98. package/esm/src/transports/base.d.ts +4 -4
  99. package/esm/src/transports/base.d.ts.map +1 -1
  100. package/esm/src/transports/base.js +3 -2
  101. package/esm/src/transports/base.js.map +1 -0
  102. package/esm/src/transports/http/http_transport.d.ts +1 -1
  103. package/esm/src/transports/http/http_transport.js +1 -0
  104. package/esm/src/transports/http/http_transport.js.map +1 -0
  105. package/esm/src/transports/websocket/_hyperliquid_event_target.js +1 -0
  106. package/esm/src/transports/websocket/_hyperliquid_event_target.js.map +1 -0
  107. package/esm/src/transports/websocket/_reconnecting_websocket.js +1 -0
  108. package/esm/src/transports/websocket/_reconnecting_websocket.js.map +1 -0
  109. package/esm/src/transports/websocket/_websocket_async_request.js +1 -0
  110. package/esm/src/transports/websocket/_websocket_async_request.js.map +1 -0
  111. package/esm/src/transports/websocket/websocket_transport.d.ts +7 -0
  112. package/esm/src/transports/websocket/websocket_transport.d.ts.map +1 -1
  113. package/esm/src/transports/websocket/websocket_transport.js +4 -0
  114. package/esm/src/transports/websocket/websocket_transport.js.map +1 -0
  115. package/package.json +15 -7
  116. package/script/bin/cli.d.ts +3 -0
  117. package/script/bin/cli.d.ts.map +1 -0
  118. package/script/bin/cli.js +490 -0
  119. package/script/bin/cli.js.map +1 -0
  120. package/{esm/src/errors.d.ts → script/src/_errors.d.ts} +1 -1
  121. package/script/src/_errors.d.ts.map +1 -0
  122. package/script/src/{errors.js → _errors.js} +1 -0
  123. package/script/src/_errors.js.map +1 -0
  124. package/script/src/clients/exchange.d.ts +4 -11
  125. package/script/src/clients/exchange.d.ts.map +1 -1
  126. package/script/src/clients/exchange.js +9 -10
  127. package/script/src/clients/exchange.js.map +1 -0
  128. package/script/src/clients/info.d.ts +86 -2
  129. package/script/src/clients/info.d.ts.map +1 -1
  130. package/script/src/clients/info.js +102 -0
  131. package/script/src/clients/info.js.map +1 -0
  132. package/script/src/clients/multiSign.d.ts +1 -1
  133. package/script/src/clients/multiSign.d.ts.map +1 -1
  134. package/script/src/clients/multiSign.js +3 -2
  135. package/script/src/clients/multiSign.js.map +1 -0
  136. package/script/src/clients/subscription.js +1 -0
  137. package/script/src/clients/subscription.js.map +1 -0
  138. package/script/src/mod.d.ts +21 -0
  139. package/script/src/mod.d.ts.map +1 -0
  140. package/script/{mod.js → src/mod.js} +13 -8
  141. package/script/src/mod.js.map +1 -0
  142. package/script/src/schemas/_base.d.ts +11 -3
  143. package/script/src/schemas/_base.d.ts.map +1 -1
  144. package/script/src/schemas/_base.js +31 -3
  145. package/script/src/schemas/_base.js.map +1 -0
  146. package/script/src/schemas/exchange/requests.d.ts +1872 -1872
  147. package/script/src/schemas/exchange/requests.d.ts.map +1 -1
  148. package/script/src/schemas/exchange/requests.js +276 -280
  149. package/script/src/schemas/exchange/requests.js.map +1 -0
  150. package/script/src/schemas/exchange/responses.d.ts +51 -51
  151. package/script/src/schemas/exchange/responses.js +54 -53
  152. package/script/src/schemas/exchange/responses.js.map +1 -0
  153. package/script/src/schemas/explorer/requests.d.ts +5 -5
  154. package/script/src/schemas/explorer/requests.js +5 -4
  155. package/script/src/schemas/explorer/requests.js.map +1 -0
  156. package/script/src/schemas/explorer/responses.d.ts +10 -10
  157. package/script/src/schemas/explorer/responses.js +11 -10
  158. package/script/src/schemas/explorer/responses.js.map +1 -0
  159. package/script/src/schemas/info/accounts.d.ts +1042 -296
  160. package/script/src/schemas/info/accounts.d.ts.map +1 -1
  161. package/script/src/schemas/info/accounts.js +154 -109
  162. package/script/src/schemas/info/accounts.js.map +1 -0
  163. package/script/src/schemas/info/assets.d.ts +130 -101
  164. package/script/src/schemas/info/assets.d.ts.map +1 -1
  165. package/script/src/schemas/info/assets.js +69 -49
  166. package/script/src/schemas/info/assets.js.map +1 -0
  167. package/script/src/schemas/info/markets.d.ts +35 -18
  168. package/script/src/schemas/info/markets.d.ts.map +1 -1
  169. package/script/src/schemas/info/markets.js +27 -15
  170. package/script/src/schemas/info/markets.js.map +1 -0
  171. package/script/src/schemas/info/orders.d.ts +151 -151
  172. package/script/src/schemas/info/orders.js +36 -35
  173. package/script/src/schemas/info/orders.js.map +1 -0
  174. package/script/src/schemas/info/requests.d.ts +145 -88
  175. package/script/src/schemas/info/requests.d.ts.map +1 -1
  176. package/script/src/schemas/info/requests.js +116 -73
  177. package/script/src/schemas/info/requests.js.map +1 -0
  178. package/script/src/schemas/info/validators.d.ts +60 -39
  179. package/script/src/schemas/info/validators.d.ts.map +1 -1
  180. package/script/src/schemas/info/validators.js +40 -26
  181. package/script/src/schemas/info/validators.js.map +1 -0
  182. package/script/src/schemas/info/vaults.d.ts +59 -59
  183. package/script/src/schemas/info/vaults.js +19 -18
  184. package/script/src/schemas/info/vaults.js.map +1 -0
  185. package/script/src/schemas/mod.d.ts +4 -3
  186. package/script/src/schemas/mod.d.ts.map +1 -1
  187. package/script/src/schemas/mod.js +8 -5
  188. package/script/src/schemas/mod.js.map +1 -0
  189. package/script/src/schemas/subscriptions/requests.d.ts +23 -23
  190. package/script/src/schemas/subscriptions/requests.d.ts.map +1 -1
  191. package/script/src/schemas/subscriptions/requests.js +24 -23
  192. package/script/src/schemas/subscriptions/requests.js.map +1 -0
  193. package/script/src/schemas/subscriptions/responses.d.ts +547 -547
  194. package/script/src/schemas/subscriptions/responses.js +40 -39
  195. package/script/src/schemas/subscriptions/responses.js.map +1 -0
  196. package/script/src/signing/mod.d.ts +1 -1
  197. package/script/src/signing/mod.d.ts.map +1 -1
  198. package/script/src/signing/mod.js +4 -3
  199. package/script/src/signing/mod.js.map +1 -0
  200. package/script/src/signing/signTypedData/ethers.d.ts.map +1 -0
  201. package/script/src/signing/{_signTypedData → signTypedData}/ethers.js +1 -0
  202. package/script/src/signing/signTypedData/ethers.js.map +1 -0
  203. package/script/src/signing/signTypedData/mod.d.ts.map +1 -0
  204. package/script/src/signing/{_signTypedData → signTypedData}/mod.js +1 -0
  205. package/script/src/signing/signTypedData/mod.js.map +1 -0
  206. package/script/src/signing/signTypedData/private_key.d.ts.map +1 -0
  207. package/script/src/signing/{_signTypedData → signTypedData}/private_key.js +17 -15
  208. package/script/src/signing/signTypedData/private_key.js.map +1 -0
  209. package/script/src/signing/signTypedData/viem.d.ts.map +1 -0
  210. package/script/src/signing/{_signTypedData → signTypedData}/viem.js +1 -0
  211. package/script/src/signing/signTypedData/viem.js.map +1 -0
  212. package/script/src/transports/base.d.ts +4 -4
  213. package/script/src/transports/base.d.ts.map +1 -1
  214. package/script/src/transports/base.js +4 -3
  215. package/script/src/transports/base.js.map +1 -0
  216. package/script/src/transports/http/http_transport.d.ts +1 -1
  217. package/script/src/transports/http/http_transport.js +1 -0
  218. package/script/src/transports/http/http_transport.js.map +1 -0
  219. package/script/src/transports/websocket/_hyperliquid_event_target.js +1 -0
  220. package/script/src/transports/websocket/_hyperliquid_event_target.js.map +1 -0
  221. package/script/src/transports/websocket/_reconnecting_websocket.js +1 -0
  222. package/script/src/transports/websocket/_reconnecting_websocket.js.map +1 -0
  223. package/script/src/transports/websocket/_websocket_async_request.js +1 -0
  224. package/script/src/transports/websocket/_websocket_async_request.js.map +1 -0
  225. package/script/src/transports/websocket/websocket_transport.d.ts +7 -0
  226. package/script/src/transports/websocket/websocket_transport.d.ts.map +1 -1
  227. package/script/src/transports/websocket/websocket_transport.js +4 -0
  228. package/script/src/transports/websocket/websocket_transport.js.map +1 -0
  229. package/src/bin/cli.ts +481 -0
  230. package/src/src/_errors.ts +7 -0
  231. package/src/src/clients/exchange.ts +2246 -0
  232. package/src/src/clients/info.ts +2110 -0
  233. package/src/src/clients/multiSign.ts +183 -0
  234. package/src/src/clients/subscription.ts +841 -0
  235. package/src/src/mod.ts +29 -0
  236. package/src/src/schemas/_base.ts +82 -0
  237. package/src/src/schemas/exchange/requests.ts +3052 -0
  238. package/src/src/schemas/exchange/responses.ts +540 -0
  239. package/src/src/schemas/explorer/requests.ts +65 -0
  240. package/src/src/schemas/explorer/responses.ts +138 -0
  241. package/src/src/schemas/info/accounts.ts +1598 -0
  242. package/src/src/schemas/info/assets.ts +693 -0
  243. package/src/src/schemas/info/markets.ts +171 -0
  244. package/src/src/schemas/info/orders.ts +597 -0
  245. package/src/src/schemas/info/requests.ts +1401 -0
  246. package/src/src/schemas/info/validators.ts +297 -0
  247. package/src/src/schemas/info/vaults.ts +262 -0
  248. package/src/src/schemas/mod.ts +121 -0
  249. package/src/src/schemas/subscriptions/requests.ts +514 -0
  250. package/src/src/schemas/subscriptions/responses.ts +576 -0
  251. package/src/src/signing/mod.ts +572 -0
  252. package/src/src/signing/signTypedData/ethers.ts +59 -0
  253. package/src/src/signing/signTypedData/mod.ts +121 -0
  254. package/src/src/signing/signTypedData/private_key.ts +234 -0
  255. package/src/src/signing/signTypedData/viem.ts +55 -0
  256. package/src/src/transports/base.ts +54 -0
  257. package/src/src/transports/http/http_transport.ts +208 -0
  258. package/src/src/transports/websocket/_hyperliquid_event_target.ts +118 -0
  259. package/src/src/transports/websocket/_reconnecting_websocket.ts +404 -0
  260. package/src/src/transports/websocket/_websocket_async_request.ts +229 -0
  261. package/src/src/transports/websocket/websocket_transport.ts +394 -0
  262. package/esm/mod.d.ts +0 -20
  263. package/esm/mod.d.ts.map +0 -1
  264. package/esm/mod.js +0 -11
  265. package/esm/src/errors.d.ts.map +0 -1
  266. package/esm/src/signing/_signTypedData/ethers.d.ts.map +0 -1
  267. package/esm/src/signing/_signTypedData/mod.d.ts.map +0 -1
  268. package/esm/src/signing/_signTypedData/private_key.d.ts.map +0 -1
  269. package/esm/src/signing/_signTypedData/viem.d.ts.map +0 -1
  270. package/script/mod.d.ts +0 -20
  271. package/script/mod.d.ts.map +0 -1
  272. package/script/src/errors.d.ts.map +0 -1
  273. package/script/src/signing/_signTypedData/ethers.d.ts.map +0 -1
  274. package/script/src/signing/_signTypedData/mod.d.ts.map +0 -1
  275. package/script/src/signing/_signTypedData/private_key.d.ts.map +0 -1
  276. package/script/src/signing/_signTypedData/viem.d.ts.map +0 -1
  277. /package/esm/src/signing/{_signTypedData → signTypedData}/ethers.d.ts +0 -0
  278. /package/esm/src/signing/{_signTypedData → signTypedData}/mod.d.ts +0 -0
  279. /package/esm/src/signing/{_signTypedData → signTypedData}/private_key.d.ts +0 -0
  280. /package/esm/src/signing/{_signTypedData → signTypedData}/viem.d.ts +0 -0
  281. /package/script/src/signing/{_signTypedData → signTypedData}/ethers.d.ts +0 -0
  282. /package/script/src/signing/{_signTypedData → signTypedData}/mod.d.ts +0 -0
  283. /package/script/src/signing/{_signTypedData → signTypedData}/private_key.d.ts +0 -0
  284. /package/script/src/signing/{_signTypedData → signTypedData}/viem.d.ts +0 -0
@@ -0,0 +1,121 @@
1
+ import {
2
+ type AbstractEthersV5Signer,
3
+ type AbstractEthersV6Signer,
4
+ isAbstractEthersV5Signer,
5
+ isAbstractEthersV6Signer,
6
+ } from "./ethers.js";
7
+ import { isValidPrivateKey, privateKeyToAddress, signTypedData as signTypedDataWithPrivateKey } from "./private_key.js";
8
+ import { type AbstractViemJsonRpcAccount, type AbstractViemLocalAccount, isAbstractViemWallet } from "./viem.js";
9
+
10
+ /** Abstract interface for a wallet that can sign typed data. */
11
+ export type AbstractWallet =
12
+ | `0x${string}` // Private key
13
+ | AbstractViemJsonRpcAccount
14
+ | AbstractViemLocalAccount
15
+ | AbstractEthersV6Signer
16
+ | AbstractEthersV5Signer;
17
+
18
+ /** ECDSA signature components for Ethereum transactions and typed data. */
19
+ export interface Signature {
20
+ /** First 32-byte component of ECDSA signature */
21
+ r: `0x${string}`;
22
+ /** Second 32-byte component of ECDSA signature */
23
+ s: `0x${string}`;
24
+ /** Recovery identifier */
25
+ v: 27 | 28;
26
+ }
27
+
28
+ export async function signTypedData(args: {
29
+ wallet: AbstractWallet;
30
+ domain: {
31
+ name: string;
32
+ version: string;
33
+ chainId: number;
34
+ verifyingContract: `0x${string}`;
35
+ };
36
+ types: {
37
+ [key: string]: {
38
+ name: string;
39
+ type: string;
40
+ }[];
41
+ };
42
+ primaryType: string;
43
+ message: Record<string, unknown>;
44
+ }): Promise<Signature> {
45
+ const { wallet, domain, types, primaryType, message } = args;
46
+
47
+ let signature: `0x${string}`;
48
+ if (isAbstractViemWallet(wallet)) {
49
+ signature = await wallet.signTypedData({
50
+ domain,
51
+ types: {
52
+ EIP712Domain: [
53
+ { name: "name", type: "string" },
54
+ { name: "version", type: "string" },
55
+ { name: "chainId", type: "uint256" },
56
+ { name: "verifyingContract", type: "address" },
57
+ ],
58
+ ...types,
59
+ },
60
+ primaryType,
61
+ message,
62
+ });
63
+ } else if (isAbstractEthersV6Signer(wallet)) {
64
+ signature = await wallet.signTypedData(domain, types, message) as `0x${string}`;
65
+ } else if (isAbstractEthersV5Signer(wallet)) {
66
+ signature = await wallet._signTypedData(domain, types, message) as `0x${string}`;
67
+ } else if (isValidPrivateKey(wallet)) {
68
+ signature = await signTypedDataWithPrivateKey({ privateKey: wallet, domain, types, primaryType, message });
69
+ } else {
70
+ throw new Error("Unsupported wallet for signing typed data");
71
+ }
72
+
73
+ return splitSignature(signature);
74
+ }
75
+
76
+ function splitSignature(signature: `0x${string}`): Signature {
77
+ const r = `0x${signature.slice(2, 66)}` as const;
78
+ const s = `0x${signature.slice(66, 130)}` as const;
79
+ const v = parseInt(signature.slice(130, 132), 16) as 27 | 28;
80
+ return { r, s, v };
81
+ }
82
+
83
+ /** Get the chain ID of the wallet. */
84
+ export async function getWalletChainId(wallet: AbstractWallet): Promise<`0x${string}`> {
85
+ if (isAbstractViemWallet(wallet)) {
86
+ if ("getChainId" in wallet && wallet.getChainId) {
87
+ const chainId = await wallet.getChainId();
88
+ return `0x${chainId.toString(16)}`;
89
+ } else {
90
+ return "0x1";
91
+ }
92
+ } else if (isAbstractEthersV6Signer(wallet) || isAbstractEthersV5Signer(wallet)) {
93
+ if ("provider" in wallet && wallet.provider) {
94
+ const network = await wallet.provider.getNetwork();
95
+ return `0x${network.chainId.toString(16)}`;
96
+ } else {
97
+ return "0x1";
98
+ }
99
+ } else {
100
+ return "0x1";
101
+ }
102
+ }
103
+
104
+ /** Get the wallet address from various wallet types. */
105
+ export async function getWalletAddress(wallet: AbstractWallet): Promise<`0x${string}`> {
106
+ if (isAbstractViemWallet(wallet)) {
107
+ if ("address" in wallet && wallet.address) {
108
+ return wallet.address;
109
+ } else if ("getAddresses" in wallet && wallet.getAddresses) {
110
+ const addresses = await wallet.getAddresses();
111
+ return addresses[0];
112
+ }
113
+ } else if (isAbstractEthersV6Signer(wallet) || isAbstractEthersV5Signer(wallet)) {
114
+ if ("getAddress" in wallet && wallet.getAddress) {
115
+ return await wallet.getAddress() as `0x${string}`;
116
+ }
117
+ } else if (isValidPrivateKey(wallet)) {
118
+ return privateKeyToAddress(wallet);
119
+ }
120
+ throw new Error("Unsupported wallet for getting address");
121
+ }
@@ -0,0 +1,234 @@
1
+ import { keccak_256 } from "@noble/hashes/sha3.js";
2
+ import { etc, getPublicKey, signAsync, utils } from "@noble/secp256k1";
3
+
4
+ interface Types {
5
+ [type: string]: {
6
+ name: string;
7
+ type: string;
8
+ }[];
9
+ }
10
+
11
+ interface Domain extends Record<string, unknown> {
12
+ name?: string;
13
+ version?: string;
14
+ chainId?: number | string | bigint | `0x${string}`;
15
+ verifyingContract?: `0x${string}`;
16
+ salt?: `0x${string}`;
17
+ }
18
+
19
+ /** Signs typed data with a private key. */
20
+ export async function signTypedData(args: {
21
+ privateKey: string;
22
+ domain?: Domain;
23
+ types: Types;
24
+ primaryType: string;
25
+ message: Record<string, unknown>;
26
+ }): Promise<`0x${string}`> {
27
+ const {
28
+ privateKey,
29
+ domain = {},
30
+ types,
31
+ primaryType,
32
+ message,
33
+ } = args;
34
+
35
+ const hash = hashTypedData({ domain, types, primaryType, message });
36
+
37
+ const signature = await signAsync(
38
+ hash,
39
+ etc.hexToBytes(cleanHex(privateKey)),
40
+ { prehash: false, format: "recovered" },
41
+ );
42
+
43
+ const r = etc.bytesToHex(signature.slice(1, 33));
44
+ const s = etc.bytesToHex(signature.slice(33, 65));
45
+ const v = (signature[0] + 27).toString(16).padStart(2, "0");
46
+
47
+ return `0x${r}${s}${v}`;
48
+ }
49
+
50
+ function hashTypedData(args: {
51
+ domain: Domain;
52
+ types: Types;
53
+ primaryType: string;
54
+ message: Record<string, unknown>;
55
+ }): Uint8Array {
56
+ const { domain, types: types_, primaryType, message } = args;
57
+
58
+ const domainFields = [];
59
+ if (domain.name !== undefined) {
60
+ domainFields.push({ name: "name", type: "string" });
61
+ }
62
+ if (domain.version !== undefined) {
63
+ domainFields.push({ name: "version", type: "string" });
64
+ }
65
+ if (domain.chainId !== undefined) {
66
+ domainFields.push({ name: "chainId", type: "uint256" });
67
+ }
68
+ if (domain.verifyingContract !== undefined) {
69
+ domainFields.push({ name: "verifyingContract", type: "address" });
70
+ }
71
+ if (domain.salt !== undefined) {
72
+ domainFields.push({ name: "salt", type: "bytes32" });
73
+ }
74
+
75
+ const types = {
76
+ EIP712Domain: domainFields,
77
+ ...types_,
78
+ };
79
+
80
+ const bytes: Uint8Array[] = [new Uint8Array([0x19, 0x01])];
81
+ bytes.push(hashStruct("EIP712Domain", domain, types));
82
+ if (primaryType !== "EIP712Domain") bytes.push(hashStruct(primaryType, message, types));
83
+
84
+ return keccak_256(etc.concatBytes(...bytes));
85
+ }
86
+
87
+ function hashStruct(primaryType: string, data: Record<string, unknown>, types: Types): Uint8Array {
88
+ const typeHash = keccak_256(new TextEncoder().encode(encodeType(primaryType, types)));
89
+ const encodedValues = types[primaryType].map((field) => encodeValue(field.type, data[field.name], types));
90
+ return keccak_256(etc.concatBytes(typeHash, ...encodedValues));
91
+ }
92
+
93
+ function encodeType(primaryType: string, types: Types): string {
94
+ const deps = findTypeDependencies(primaryType, types);
95
+ const sortedDeps = [primaryType, ...deps.filter((d) => d !== primaryType).sort()];
96
+ return sortedDeps
97
+ .map((type) =>
98
+ `${type}(${types[type].map((field) => `${resolveTypeAlias(field.type)} ${field.name}`).join(",")})`
99
+ )
100
+ .join("");
101
+ }
102
+
103
+ function resolveTypeAlias(type: string): string {
104
+ if (type === "uint") return "uint256";
105
+ if (type === "int") return "int256";
106
+ return type;
107
+ }
108
+
109
+ function findTypeDependencies(primaryType: string, types: Types, _found = new Set<string>()): string[] {
110
+ if (_found.has(primaryType) || !types[primaryType]) return [];
111
+ _found.add(primaryType);
112
+
113
+ for (const field of types[primaryType]) {
114
+ const baseType = field.type.replace(/\[.*?\]/g, "");
115
+ if (types[baseType]) {
116
+ findTypeDependencies(baseType, types, _found);
117
+ }
118
+ }
119
+ return Array.from(_found);
120
+ }
121
+
122
+ function encodeValue(type: string, value: unknown, types: Types): Uint8Array {
123
+ const arrayMatch = type.match(/^(.*)\[(\d*)\]$/);
124
+ if (arrayMatch) {
125
+ // Extract type info: base type and optional length
126
+ const [, baseType, len] = arrayMatch;
127
+ if (!Array.isArray(value)) {
128
+ throw new Error(`Expected array for ${type}. Received: ${typeof value}`);
129
+ }
130
+ if (len && value.length !== +len) {
131
+ throw new Error(`Invalid length for ${type}: expected ${len}. Received: ${value.length}`);
132
+ }
133
+
134
+ // Encode each element in the array and hash them together
135
+ const encodedElements = value.map((v) => encodeValue(baseType, v, types));
136
+ return keccak_256(etc.concatBytes(...encodedElements));
137
+ }
138
+
139
+ if (types[type]) {
140
+ if (value === undefined) return new Uint8Array(32);
141
+ return hashStruct(type, value as Record<string, unknown>, types);
142
+ }
143
+
144
+ if (type === "string") {
145
+ return keccak_256(new TextEncoder().encode(value as string));
146
+ }
147
+
148
+ if (type === "address") {
149
+ const bytes = etc.hexToBytes(cleanHex(value as string));
150
+ if (bytes.length !== 20) {
151
+ throw new Error(`Address must be 20 bytes.`);
152
+ }
153
+ const padded = new Uint8Array(32);
154
+ padded.set(bytes, 12);
155
+ return padded;
156
+ }
157
+
158
+ if (type.startsWith("uint") || type.startsWith("int")) {
159
+ // Extract type info: uint/int and bit size
160
+ const isUint = type.startsWith("uint");
161
+ const bitsStr = type.slice(isUint ? 4 : 3);
162
+ const bits = parseInt(bitsStr || "256");
163
+ if (bits > 256 || bits % 8 !== 0) {
164
+ throw new Error(`Invalid ${isUint ? "uint" : "int"} size: ${bitsStr}. Must be 8-256 in steps of 8`);
165
+ }
166
+
167
+ // Apply Two's complement for specified bit size
168
+ const bigIntValue = BigInt(value as number | string | bigint | `0x${string}`);
169
+ const resizedValue = isUint ? BigInt.asUintN(bits, bigIntValue) : BigInt.asIntN(bits, bigIntValue);
170
+
171
+ // Convert to 32-byte big-endian
172
+ const hex = BigInt.asUintN(256, resizedValue).toString(16).padStart(64, "0");
173
+ return etc.hexToBytes(hex);
174
+ }
175
+
176
+ if (type === "bool") {
177
+ const result = new Uint8Array(32);
178
+ result[31] = value ? 1 : 0;
179
+ return result;
180
+ }
181
+
182
+ if (type === "bytes") {
183
+ const bytes = typeof value === "string" ? etc.hexToBytes(cleanHex(value)) : value as Uint8Array;
184
+ return keccak_256(bytes);
185
+ }
186
+
187
+ const bytesMatch = type.match(/^bytes(\d+)$/);
188
+ if (bytesMatch) {
189
+ // Extract type info: bytes size
190
+ const size = parseInt(bytesMatch[1]);
191
+ if (size === 0 || size > 32) {
192
+ throw new Error(`bytesN size must be 1-32. Received: ${size}`);
193
+ }
194
+
195
+ // Convert hex to bytes
196
+ const bytes = etc.hexToBytes(cleanHex(value as string));
197
+ if (bytes.length !== size) {
198
+ throw new Error(`${type} requires exactly ${size} bytes. Received: ${bytes.length} from '${value}'`);
199
+ }
200
+
201
+ // Pad to 32 bytes
202
+ const padded = new Uint8Array(32);
203
+ padded.set(bytes, 0);
204
+ return padded;
205
+ }
206
+
207
+ throw new Error(`Unsupported type: '${type}'.`);
208
+ }
209
+
210
+ function cleanHex(hex: string): string {
211
+ return hex.startsWith("0x") ? hex.slice(2) : hex;
212
+ }
213
+
214
+ /** Validates if a string is a valid secp256k1 private key. */
215
+ export function isValidPrivateKey(privateKey: unknown): privateKey is string {
216
+ if (typeof privateKey !== "string") return false;
217
+ const privateKeyBytes = etc.hexToBytes(cleanHex(privateKey));
218
+ return utils.isValidSecretKey(privateKeyBytes);
219
+ }
220
+
221
+ /** Converts a private key to an Ethereum address. */
222
+ export function privateKeyToAddress(privateKey: string): `0x${string}` {
223
+ const privateKeyBytes = etc.hexToBytes(cleanHex(privateKey));
224
+
225
+ const publicKey = getPublicKey(privateKeyBytes, false);
226
+ const publicKeyWithoutPrefix = publicKey.slice(1);
227
+
228
+ const hash = keccak_256(publicKeyWithoutPrefix);
229
+
230
+ const addressBytes = hash.slice(-20);
231
+ const address = etc.bytesToHex(addressBytes);
232
+
233
+ return `0x${address}`;
234
+ }
@@ -0,0 +1,55 @@
1
+ /** Abstract interface for a viem {@link https://viem.sh/docs/accounts/jsonRpc#json-rpc-account | JSON-RPC Account}. */
2
+ export interface AbstractViemJsonRpcAccount {
3
+ signTypedData(
4
+ params: {
5
+ domain: {
6
+ name: string;
7
+ version: string;
8
+ chainId: number;
9
+ verifyingContract: `0x${string}`;
10
+ };
11
+ types: {
12
+ [key: string]: {
13
+ name: string;
14
+ type: string;
15
+ }[];
16
+ };
17
+ primaryType: string;
18
+ message: Record<string, unknown>;
19
+ },
20
+ options?: unknown,
21
+ ): Promise<`0x${string}`>;
22
+ getAddresses?(): Promise<`0x${string}`[]>;
23
+ getChainId?(): Promise<number>;
24
+ }
25
+
26
+ /** Abstract interface for a viem {@link https://viem.sh/docs/accounts/local | Local Account}. */
27
+ export interface AbstractViemLocalAccount {
28
+ signTypedData(
29
+ params: {
30
+ domain: {
31
+ name: string;
32
+ version: string;
33
+ chainId: number;
34
+ verifyingContract: `0x${string}`;
35
+ };
36
+ types: {
37
+ [key: string]: {
38
+ name: string;
39
+ type: string;
40
+ }[];
41
+ };
42
+ primaryType: string;
43
+ message: Record<string, unknown>;
44
+ },
45
+ options?: unknown,
46
+ ): Promise<`0x${string}`>;
47
+ address?: `0x${string}`;
48
+ }
49
+
50
+ /** Checks if the given value is an abstract viem wallet. */
51
+ export function isAbstractViemWallet(client: unknown): client is AbstractViemJsonRpcAccount | AbstractViemLocalAccount {
52
+ return typeof client === "object" && client !== null &&
53
+ "signTypedData" in client && typeof client.signTypedData === "function" &&
54
+ (client.signTypedData.length === 1 || client.signTypedData.length === 2);
55
+ }
@@ -0,0 +1,54 @@
1
+ import { HyperliquidError } from "../_errors.js";
2
+
3
+ /**
4
+ * Interface representing a REST transport.
5
+ * Handles communication with Hyperliquid API endpoints.
6
+ * @see {@link https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint | Info endpoint}
7
+ * @see {@link https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint | Exchange endpoint}
8
+ * @see {@link https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/post-requests | Websocket post requests}
9
+ */
10
+ export interface IRequestTransport extends Partial<AsyncDisposable> {
11
+ /** Indicates this transport uses testnet endpoint(s). */
12
+ isTestnet: boolean;
13
+ /**
14
+ * Sends a request to the Hyperliquid API.
15
+ * @param endpoint - The API endpoint to send the request to.
16
+ * @param payload - The payload to send with the request.
17
+ * @param signal - An {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal | AbortSignal}. If this option is set, the request can be canceled by calling {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort | abort()} on the corresponding {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/AbortController | AbortController}.
18
+ * @returns A promise that resolves with parsed JSON response body.
19
+ */
20
+ request<T>(endpoint: "info" | "exchange", payload: unknown, signal?: AbortSignal): Promise<T>;
21
+ request<T>(endpoint: "info" | "exchange" | "explorer", payload: unknown, signal?: AbortSignal): Promise<T>;
22
+ }
23
+
24
+ /**
25
+ * Interface representing an event subscription transport.
26
+ * Handles WebSocket subscriptions for real-time updates.
27
+ * @see {@link https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions | Websocket subscriptions}
28
+ */
29
+ export interface ISubscriptionTransport extends Partial<AsyncDisposable> {
30
+ /**
31
+ * Subscribes to a Hyperliquid event channel.
32
+ * @param channel - The event channel to listen to.
33
+ * @param payload - The payload to send with the subscription request.
34
+ * @param listener - The function to call when the event is dispatched.
35
+ * @returns A promise that resolves with a {@link Subscription} object to manage the subscription lifecycle.
36
+ */
37
+ subscribe<T>(channel: string, payload: unknown, listener: (data: CustomEvent<T>) => void): Promise<Subscription>;
38
+ }
39
+
40
+ /** Controls event subscription lifecycle. */
41
+ export interface Subscription {
42
+ /** Unsubscribes from the event and sends an unsubscribe request to the server. */
43
+ unsubscribe(): Promise<void>;
44
+ /** Signal that aborts when resubscription fails during reconnection. */
45
+ resubscribeSignal?: AbortSignal;
46
+ }
47
+
48
+ /** Thrown when a transport layer error occurs. */
49
+ export class TransportError extends HyperliquidError {
50
+ constructor(message?: string, options?: ErrorOptions) {
51
+ super(message, options);
52
+ this.name = "TransportError";
53
+ }
54
+ }
@@ -0,0 +1,208 @@
1
+ import { TransportError } from "../base.js";
2
+ import type { IRequestTransport } from "../base.js";
3
+
4
+ type MaybePromise<T> = T | Promise<T>;
5
+
6
+ /** Error thrown when an HTTP request fails. */
7
+ export class HttpRequestError extends TransportError {
8
+ response?: Response;
9
+ body?: string;
10
+
11
+ constructor(args?: { response?: Response; body?: string }, options?: ErrorOptions) {
12
+ const { response, body } = args ?? {};
13
+
14
+ let message: string;
15
+ if (response) {
16
+ message = `${response.status} ${response.statusText}`.trim();
17
+ if (body) message += ` - ${body}`;
18
+ } else {
19
+ message = `Unknown error while making an HTTP request: ${options?.cause}`;
20
+ }
21
+
22
+ super(message, options);
23
+ this.name = "HttpRequestError";
24
+ this.response = response;
25
+ this.body = body;
26
+ }
27
+ }
28
+
29
+ /** Configuration options for the HTTP transport layer. */
30
+ export interface HttpTransportOptions {
31
+ /**
32
+ * Specifies whether to use the testnet API endpoints from the {@linkcode server} property.
33
+ * @defaultValue `false`
34
+ */
35
+ isTestnet?: boolean;
36
+
37
+ /**
38
+ * Request timeout in ms. Set to `null` to disable.
39
+ * @defaultValue `10_000`
40
+ */
41
+ timeout?: number | null;
42
+
43
+ /**
44
+ * Custom server to use for API requests.
45
+ * @defaultValue `https://api.hyperliquid.xyz` for mainnet and `https://api.hyperliquid-testnet.xyz` for testnet.
46
+ */
47
+ server?: {
48
+ mainnet?: { api?: string | URL; rpc?: string | URL };
49
+ testnet?: { api?: string | URL; rpc?: string | URL };
50
+ };
51
+
52
+ /** A custom {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/RequestInit | RequestInit} that is merged with a fetch request. */
53
+ fetchOptions?: Omit<RequestInit, "body" | "method">;
54
+
55
+ /**
56
+ * A callback function that is called before the request is sent.
57
+ * @param request - An original request to send.
58
+ * @returns If returned a {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/Request/Request | Request}, it will replace the original request.
59
+ */
60
+ onRequest?: (request: Request) => MaybePromise<Request | void | null | undefined>;
61
+
62
+ /**
63
+ * A callback function that is called after the response is received.
64
+ * @param response - An original response to process.
65
+ * @returns If returned a {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/Response/Response | Response}, it will replace the original response.
66
+ */
67
+ onResponse?: (response: Response) => MaybePromise<Response | void | null | undefined>;
68
+ }
69
+
70
+ /** HTTP implementation of the REST transport interface. */
71
+ export class HttpTransport implements IRequestTransport, HttpTransportOptions {
72
+ isTestnet: boolean;
73
+ timeout: number | null;
74
+ server: {
75
+ mainnet: { api: string | URL; rpc: string | URL };
76
+ testnet: { api: string | URL; rpc: string | URL };
77
+ };
78
+ fetchOptions: Omit<RequestInit, "body" | "method">;
79
+ onRequest?: (request: Request) => MaybePromise<Request | void | null | undefined>;
80
+ onResponse?: (response: Response) => MaybePromise<Response | void | null | undefined>;
81
+
82
+ /**
83
+ * Creates a new HTTP transport instance.
84
+ * @param options - Configuration options for the HTTP transport layer.
85
+ */
86
+ constructor(options?: HttpTransportOptions) {
87
+ this.isTestnet = options?.isTestnet ?? false;
88
+ this.timeout = options?.timeout === undefined ? 10_000 : options.timeout;
89
+ this.server = {
90
+ mainnet: {
91
+ api: options?.server?.mainnet?.api ?? "https://api.hyperliquid.xyz",
92
+ rpc: options?.server?.mainnet?.rpc ?? "https://rpc.hyperliquid.xyz",
93
+ },
94
+ testnet: {
95
+ api: options?.server?.testnet?.api ?? "https://api.hyperliquid-testnet.xyz",
96
+ rpc: options?.server?.testnet?.rpc ?? "https://rpc.hyperliquid-testnet.xyz",
97
+ },
98
+ };
99
+ this.fetchOptions = options?.fetchOptions ?? {};
100
+ this.onRequest = options?.onRequest;
101
+ this.onResponse = options?.onResponse;
102
+ }
103
+
104
+ /**
105
+ * Sends a request to the Hyperliquid API via fetch.
106
+ * @param endpoint - The API endpoint to send the request to.
107
+ * @param payload - The payload to send with the request.
108
+ * @param signal - An {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal | AbortSignal}. If this option is set, the request can be canceled by calling {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort | abort()} on the corresponding {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/AbortController | AbortController}.
109
+ * @returns A promise that resolves with parsed JSON response body.
110
+ *
111
+ * @throws {HttpRequestError} Thrown when the HTTP request fails.
112
+ */
113
+ async request<T>(endpoint: "info" | "exchange" | "explorer", payload: unknown, signal?: AbortSignal): Promise<T> {
114
+ try {
115
+ // Construct a Request
116
+ const url = new URL(
117
+ endpoint,
118
+ this.server[this.isTestnet ? "testnet" : "mainnet"][endpoint === "explorer" ? "rpc" : "api"],
119
+ );
120
+ const init = mergeRequestInit(
121
+ {
122
+ body: JSON.stringify(payload),
123
+ headers: {
124
+ "Accept-Encoding": "gzip, deflate, br, zstd",
125
+ "Content-Type": "application/json",
126
+ },
127
+ keepalive: true,
128
+ method: "POST",
129
+ signal: this.timeout ? AbortSignal.timeout(this.timeout) : undefined,
130
+ },
131
+ this.fetchOptions,
132
+ { signal },
133
+ );
134
+ let request = new Request(url, init);
135
+
136
+ // Call the onRequest callback, if provided
137
+ if (this.onRequest) {
138
+ const customRequest = await this.onRequest(request);
139
+ if (customRequest instanceof Request) request = customRequest;
140
+ }
141
+
142
+ // Send the Request and wait for a Response
143
+ let response = await fetch(request);
144
+
145
+ // Call the onResponse callback, if provided
146
+ if (this.onResponse) {
147
+ const customResponse = await this.onResponse(response);
148
+ if (customResponse instanceof Response) response = customResponse;
149
+ }
150
+
151
+ // Validate the Response
152
+ if (!response.ok || !response.headers.get("Content-Type")?.includes("application/json")) {
153
+ // Unload the response body to prevent memory leaks
154
+ const body = await response.text().catch(() => undefined);
155
+ throw new HttpRequestError({ response, body });
156
+ }
157
+
158
+ // Parse the response body
159
+ const body = await response.json();
160
+
161
+ // Check if the response is an error
162
+ if (body?.type === "error") {
163
+ throw new HttpRequestError({ response, body: body?.message });
164
+ }
165
+
166
+ // Return the response body
167
+ return body;
168
+ } catch (error) {
169
+ if (error instanceof TransportError) throw error; // Re-throw known errors
170
+ throw new HttpRequestError(undefined, { cause: error });
171
+ }
172
+ }
173
+ }
174
+
175
+ /** Merges multiple {@linkcode HeadersInit} into one {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/Headers/Headers | Headers}. */
176
+ function mergeHeadersInit(...inits: HeadersInit[]): Headers {
177
+ if (inits.length === 0 || inits.length === 1) {
178
+ return new Headers(inits[0] as HeadersInit | undefined);
179
+ }
180
+
181
+ const merged = new Headers();
182
+ for (const headers of inits) {
183
+ const iterator = Symbol.iterator in headers ? headers : Object.entries(headers);
184
+ for (const [key, value] of iterator) {
185
+ merged.set(key, value);
186
+ }
187
+ }
188
+ return merged;
189
+ }
190
+
191
+ /** Merges multiple {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/RequestInit | RequestInit} into one {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/RequestInit | RequestInit}. */
192
+ function mergeRequestInit(...inits: RequestInit[]): RequestInit {
193
+ const merged = inits.reduce((acc, init) => ({ ...acc, ...init }), {});
194
+
195
+ const headersList = inits.map((init) => init.headers)
196
+ .filter((headers) => typeof headers === "object");
197
+ if (headersList.length > 0) {
198
+ merged.headers = mergeHeadersInit(...headersList);
199
+ }
200
+
201
+ const signals = inits.map((init) => init.signal)
202
+ .filter((signal) => signal instanceof AbortSignal);
203
+ if (signals.length > 0) {
204
+ merged.signal = signals.length > 1 ? AbortSignal.any(signals) : signals[0];
205
+ }
206
+
207
+ return merged;
208
+ }