@nktkas/hyperliquid 0.22.1 → 0.23.0

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 (230) hide show
  1. package/README.md +125 -70
  2. package/esm/mod.d.ts +1 -1
  3. package/esm/mod.d.ts.map +1 -1
  4. package/esm/src/base.d.ts +4 -1
  5. package/esm/src/base.d.ts.map +1 -1
  6. package/esm/src/base.js +2 -2
  7. package/esm/src/clients/exchange.d.ts +420 -368
  8. package/esm/src/clients/exchange.d.ts.map +1 -1
  9. package/esm/src/clients/exchange.js +721 -551
  10. package/esm/src/clients/info.d.ts +137 -41
  11. package/esm/src/clients/info.d.ts.map +1 -1
  12. package/esm/src/clients/info.js +124 -28
  13. package/esm/src/clients/multiSign.d.ts +406 -484
  14. package/esm/src/clients/multiSign.d.ts.map +1 -1
  15. package/esm/src/clients/multiSign.js +639 -734
  16. package/esm/src/clients/subscription.d.ts +38 -3
  17. package/esm/src/clients/subscription.d.ts.map +1 -1
  18. package/esm/src/clients/subscription.js +36 -3
  19. package/esm/src/signing/_signTypedData/ethers.d.ts +33 -0
  20. package/esm/src/signing/_signTypedData/ethers.d.ts.map +1 -0
  21. package/esm/src/signing/_signTypedData/ethers.js +12 -0
  22. package/esm/src/signing/_signTypedData/mod.d.ts +35 -0
  23. package/esm/src/signing/_signTypedData/mod.d.ts.map +1 -0
  24. package/esm/src/signing/_signTypedData/mod.js +59 -0
  25. package/esm/src/signing/_signTypedData/private_key.d.ts +26 -0
  26. package/esm/src/signing/_signTypedData/private_key.d.ts.map +1 -0
  27. package/esm/src/signing/_signTypedData/private_key.js +144 -0
  28. package/esm/src/signing/_signTypedData/viem.d.ts +23 -0
  29. package/esm/src/signing/_signTypedData/viem.d.ts.map +1 -0
  30. package/esm/src/signing/_signTypedData/viem.js +6 -0
  31. package/esm/src/signing/_signTypedData/window.d.ts +29 -0
  32. package/esm/src/signing/_signTypedData/window.d.ts.map +1 -0
  33. package/esm/src/signing/_signTypedData/window.js +30 -0
  34. package/esm/src/signing/_sorter.d.ts +128 -0
  35. package/esm/src/signing/_sorter.d.ts.map +1 -0
  36. package/esm/src/{signing.js → signing/_sorter.js} +36 -449
  37. package/esm/src/signing/mod.d.ts +272 -0
  38. package/esm/src/signing/mod.d.ts.map +1 -0
  39. package/esm/src/signing/mod.js +306 -0
  40. package/esm/src/transports/base.d.ts +1 -1
  41. package/esm/src/transports/base.d.ts.map +1 -1
  42. package/esm/src/transports/base.js +2 -2
  43. package/esm/src/transports/http/http_transport.d.ts +9 -15
  44. package/esm/src/transports/http/http_transport.d.ts.map +1 -1
  45. package/esm/src/transports/http/http_transport.js +64 -59
  46. package/esm/src/transports/websocket/_hyperliquid_event_target.d.ts +1 -1
  47. package/esm/src/transports/websocket/_hyperliquid_event_target.d.ts.map +1 -1
  48. package/esm/src/transports/websocket/_hyperliquid_event_target.js +1 -1
  49. package/esm/src/transports/websocket/_reconnecting_websocket.d.ts.map +1 -1
  50. package/esm/src/transports/websocket/_reconnecting_websocket.js +17 -4
  51. package/esm/src/transports/websocket/_websocket_async_request.d.ts +0 -9
  52. package/esm/src/transports/websocket/_websocket_async_request.d.ts.map +1 -1
  53. package/esm/src/transports/websocket/_websocket_async_request.js +14 -20
  54. package/esm/src/transports/websocket/websocket_transport.d.ts +8 -4
  55. package/esm/src/transports/websocket/websocket_transport.d.ts.map +1 -1
  56. package/esm/src/transports/websocket/websocket_transport.js +83 -54
  57. package/esm/src/types/exchange/requests.d.ts +27 -51
  58. package/esm/src/types/exchange/requests.d.ts.map +1 -1
  59. package/esm/src/types/explorer/requests.d.ts +5 -8
  60. package/esm/src/types/explorer/requests.d.ts.map +1 -1
  61. package/esm/src/types/info/accounts.d.ts +5 -5
  62. package/esm/src/types/info/accounts.d.ts.map +1 -1
  63. package/esm/src/types/info/delegations.d.ts +1 -1
  64. package/esm/src/types/info/delegations.d.ts.map +1 -1
  65. package/esm/src/types/info/orders.d.ts +1 -1
  66. package/esm/src/types/info/orders.d.ts.map +1 -1
  67. package/esm/src/types/info/requests.d.ts +49 -96
  68. package/esm/src/types/info/requests.d.ts.map +1 -1
  69. package/esm/src/types/subscriptions/requests.d.ts +72 -18
  70. package/esm/src/types/subscriptions/requests.d.ts.map +1 -1
  71. package/esm/src/types/subscriptions/responses.d.ts +2 -0
  72. package/esm/src/types/subscriptions/responses.d.ts.map +1 -1
  73. package/package.json +12 -8
  74. package/script/mod.d.ts +1 -1
  75. package/script/mod.d.ts.map +1 -1
  76. package/script/mod.js +13 -23
  77. package/script/src/base.d.ts +4 -1
  78. package/script/src/base.d.ts.map +1 -1
  79. package/script/src/base.js +10 -20
  80. package/script/src/clients/exchange.d.ts +420 -368
  81. package/script/src/clients/exchange.d.ts.map +1 -1
  82. package/script/src/clients/exchange.js +2000 -1840
  83. package/script/src/clients/info.d.ts +137 -41
  84. package/script/src/clients/info.d.ts.map +1 -1
  85. package/script/src/clients/info.js +1296 -1210
  86. package/script/src/clients/multiSign.d.ts +406 -484
  87. package/script/src/clients/multiSign.d.ts.map +1 -1
  88. package/script/src/clients/multiSign.js +2043 -2148
  89. package/script/src/clients/subscription.d.ts +38 -3
  90. package/script/src/clients/subscription.d.ts.map +1 -1
  91. package/script/src/clients/subscription.js +568 -545
  92. package/script/src/signing/_signTypedData/ethers.d.ts +33 -0
  93. package/script/src/signing/_signTypedData/ethers.d.ts.map +1 -0
  94. package/script/src/signing/_signTypedData/ethers.js +16 -0
  95. package/script/src/signing/_signTypedData/mod.d.ts +35 -0
  96. package/script/src/signing/_signTypedData/mod.d.ts.map +1 -0
  97. package/script/src/signing/_signTypedData/mod.js +67 -0
  98. package/script/src/signing/_signTypedData/private_key.d.ts +26 -0
  99. package/script/src/signing/_signTypedData/private_key.d.ts.map +1 -0
  100. package/script/src/signing/_signTypedData/private_key.js +148 -0
  101. package/script/src/signing/_signTypedData/viem.d.ts +23 -0
  102. package/script/src/signing/_signTypedData/viem.d.ts.map +1 -0
  103. package/script/src/signing/_signTypedData/viem.js +9 -0
  104. package/script/src/signing/_signTypedData/window.d.ts +29 -0
  105. package/script/src/signing/_signTypedData/window.d.ts.map +1 -0
  106. package/script/src/signing/_signTypedData/window.js +34 -0
  107. package/script/src/signing/_sorter.d.ts +128 -0
  108. package/script/src/signing/_sorter.d.ts.map +1 -0
  109. package/script/src/signing/_sorter.js +698 -0
  110. package/script/src/signing/mod.d.ts +272 -0
  111. package/script/src/signing/mod.d.ts.map +1 -0
  112. package/script/src/signing/mod.js +331 -0
  113. package/script/src/transports/base.d.ts +1 -1
  114. package/script/src/transports/base.d.ts.map +1 -1
  115. package/script/src/transports/base.js +11 -21
  116. package/script/src/transports/http/http_transport.d.ts +9 -15
  117. package/script/src/transports/http/http_transport.d.ts.map +1 -1
  118. package/script/src/transports/http/http_transport.js +97 -102
  119. package/script/src/transports/websocket/_hyperliquid_event_target.d.ts +1 -1
  120. package/script/src/transports/websocket/_hyperliquid_event_target.d.ts.map +1 -1
  121. package/script/src/transports/websocket/_hyperliquid_event_target.js +51 -61
  122. package/script/src/transports/websocket/_reconnecting_websocket.d.ts.map +1 -1
  123. package/script/src/transports/websocket/_reconnecting_websocket.js +271 -268
  124. package/script/src/transports/websocket/_websocket_async_request.d.ts +0 -9
  125. package/script/src/transports/websocket/_websocket_async_request.d.ts.map +1 -1
  126. package/script/src/transports/websocket/_websocket_async_request.js +157 -174
  127. package/script/src/transports/websocket/websocket_transport.d.ts +8 -4
  128. package/script/src/transports/websocket/websocket_transport.d.ts.map +1 -1
  129. package/script/src/transports/websocket/websocket_transport.js +209 -189
  130. package/script/src/types/exchange/requests.d.ts +27 -51
  131. package/script/src/types/exchange/requests.d.ts.map +1 -1
  132. package/script/src/types/exchange/requests.js +2 -12
  133. package/script/src/types/exchange/responses.js +2 -12
  134. package/script/src/types/explorer/requests.d.ts +5 -8
  135. package/script/src/types/explorer/requests.d.ts.map +1 -1
  136. package/script/src/types/explorer/requests.js +2 -12
  137. package/script/src/types/explorer/responses.js +2 -12
  138. package/script/src/types/info/accounts.d.ts +5 -5
  139. package/script/src/types/info/accounts.d.ts.map +1 -1
  140. package/script/src/types/info/accounts.js +2 -12
  141. package/script/src/types/info/assets.js +2 -12
  142. package/script/src/types/info/delegations.d.ts +1 -1
  143. package/script/src/types/info/delegations.d.ts.map +1 -1
  144. package/script/src/types/info/delegations.js +2 -12
  145. package/script/src/types/info/markets.js +2 -12
  146. package/script/src/types/info/orders.d.ts +1 -1
  147. package/script/src/types/info/orders.d.ts.map +1 -1
  148. package/script/src/types/info/orders.js +2 -12
  149. package/script/src/types/info/requests.d.ts +49 -96
  150. package/script/src/types/info/requests.d.ts.map +1 -1
  151. package/script/src/types/info/requests.js +2 -12
  152. package/script/src/types/info/vaults.js +2 -12
  153. package/script/src/types/mod.js +2 -12
  154. package/script/src/types/subscriptions/requests.d.ts +72 -18
  155. package/script/src/types/subscriptions/requests.d.ts.map +1 -1
  156. package/script/src/types/subscriptions/requests.js +2 -12
  157. package/script/src/types/subscriptions/responses.d.ts +2 -0
  158. package/script/src/types/subscriptions/responses.d.ts.map +1 -1
  159. package/script/src/types/subscriptions/responses.js +2 -12
  160. package/esm/deps/jsr.io/@derzade/typescript-event-target/1.1.1/mod.d.ts +0 -2
  161. package/esm/deps/jsr.io/@derzade/typescript-event-target/1.1.1/mod.d.ts.map +0 -1
  162. package/esm/deps/jsr.io/@derzade/typescript-event-target/1.1.1/mod.js +0 -1
  163. package/esm/deps/jsr.io/@derzade/typescript-event-target/1.1.1/src/TypedEventTarget.d.ts +0 -95
  164. package/esm/deps/jsr.io/@derzade/typescript-event-target/1.1.1/src/TypedEventTarget.d.ts.map +0 -1
  165. package/esm/deps/jsr.io/@derzade/typescript-event-target/1.1.1/src/TypedEventTarget.js +0 -10
  166. package/esm/deps/jsr.io/@std/async/1.0.13/delay.d.ts +0 -43
  167. package/esm/deps/jsr.io/@std/async/1.0.13/delay.d.ts.map +0 -1
  168. package/esm/deps/jsr.io/@std/async/1.0.13/delay.js +0 -63
  169. package/esm/deps/jsr.io/@std/bytes/1.0.6/_types.d.ts +0 -9
  170. package/esm/deps/jsr.io/@std/bytes/1.0.6/_types.d.ts.map +0 -1
  171. package/esm/deps/jsr.io/@std/bytes/1.0.6/_types.js +0 -2
  172. package/esm/deps/jsr.io/@std/bytes/1.0.6/concat.d.ts +0 -21
  173. package/esm/deps/jsr.io/@std/bytes/1.0.6/concat.d.ts.map +0 -1
  174. package/esm/deps/jsr.io/@std/bytes/1.0.6/concat.js +0 -32
  175. package/esm/deps/jsr.io/@std/encoding/1.0.10/_common16.d.ts +0 -23
  176. package/esm/deps/jsr.io/@std/encoding/1.0.10/_common16.d.ts.map +0 -1
  177. package/esm/deps/jsr.io/@std/encoding/1.0.10/_common16.js +0 -51
  178. package/esm/deps/jsr.io/@std/encoding/1.0.10/_common_detach.d.ts +0 -4
  179. package/esm/deps/jsr.io/@std/encoding/1.0.10/_common_detach.d.ts.map +0 -1
  180. package/esm/deps/jsr.io/@std/encoding/1.0.10/_common_detach.js +0 -13
  181. package/esm/deps/jsr.io/@std/encoding/1.0.10/_types.d.ts +0 -9
  182. package/esm/deps/jsr.io/@std/encoding/1.0.10/_types.d.ts.map +0 -1
  183. package/esm/deps/jsr.io/@std/encoding/1.0.10/_types.js +0 -2
  184. package/esm/deps/jsr.io/@std/encoding/1.0.10/hex.d.ts +0 -39
  185. package/esm/deps/jsr.io/@std/encoding/1.0.10/hex.d.ts.map +0 -1
  186. package/esm/deps/jsr.io/@std/encoding/1.0.10/hex.js +0 -87
  187. package/esm/deps/jsr.io/@std/msgpack/1.0.3/_types.d.ts +0 -9
  188. package/esm/deps/jsr.io/@std/msgpack/1.0.3/_types.d.ts.map +0 -1
  189. package/esm/deps/jsr.io/@std/msgpack/1.0.3/_types.js +0 -2
  190. package/esm/deps/jsr.io/@std/msgpack/1.0.3/encode.d.ts +0 -39
  191. package/esm/deps/jsr.io/@std/msgpack/1.0.3/encode.d.ts.map +0 -1
  192. package/esm/deps/jsr.io/@std/msgpack/1.0.3/encode.js +0 -237
  193. package/esm/src/signing.d.ts +0 -463
  194. package/esm/src/signing.d.ts.map +0 -1
  195. package/script/deps/jsr.io/@derzade/typescript-event-target/1.1.1/mod.d.ts +0 -2
  196. package/script/deps/jsr.io/@derzade/typescript-event-target/1.1.1/mod.d.ts.map +0 -1
  197. package/script/deps/jsr.io/@derzade/typescript-event-target/1.1.1/mod.js +0 -27
  198. package/script/deps/jsr.io/@derzade/typescript-event-target/1.1.1/src/TypedEventTarget.d.ts +0 -95
  199. package/script/deps/jsr.io/@derzade/typescript-event-target/1.1.1/src/TypedEventTarget.d.ts.map +0 -1
  200. package/script/deps/jsr.io/@derzade/typescript-event-target/1.1.1/src/TypedEventTarget.js +0 -24
  201. package/script/deps/jsr.io/@std/async/1.0.13/delay.d.ts +0 -43
  202. package/script/deps/jsr.io/@std/async/1.0.13/delay.d.ts.map +0 -1
  203. package/script/deps/jsr.io/@std/async/1.0.13/delay.js +0 -76
  204. package/script/deps/jsr.io/@std/bytes/1.0.6/_types.d.ts +0 -9
  205. package/script/deps/jsr.io/@std/bytes/1.0.6/_types.d.ts.map +0 -1
  206. package/script/deps/jsr.io/@std/bytes/1.0.6/_types.js +0 -13
  207. package/script/deps/jsr.io/@std/bytes/1.0.6/concat.d.ts +0 -21
  208. package/script/deps/jsr.io/@std/bytes/1.0.6/concat.d.ts.map +0 -1
  209. package/script/deps/jsr.io/@std/bytes/1.0.6/concat.js +0 -45
  210. package/script/deps/jsr.io/@std/encoding/1.0.10/_common16.d.ts +0 -23
  211. package/script/deps/jsr.io/@std/encoding/1.0.10/_common16.d.ts.map +0 -1
  212. package/script/deps/jsr.io/@std/encoding/1.0.10/_common16.js +0 -67
  213. package/script/deps/jsr.io/@std/encoding/1.0.10/_common_detach.d.ts +0 -4
  214. package/script/deps/jsr.io/@std/encoding/1.0.10/_common_detach.d.ts.map +0 -1
  215. package/script/deps/jsr.io/@std/encoding/1.0.10/_common_detach.js +0 -26
  216. package/script/deps/jsr.io/@std/encoding/1.0.10/_types.d.ts +0 -9
  217. package/script/deps/jsr.io/@std/encoding/1.0.10/_types.d.ts.map +0 -1
  218. package/script/deps/jsr.io/@std/encoding/1.0.10/_types.js +0 -13
  219. package/script/deps/jsr.io/@std/encoding/1.0.10/hex.d.ts +0 -39
  220. package/script/deps/jsr.io/@std/encoding/1.0.10/hex.d.ts.map +0 -1
  221. package/script/deps/jsr.io/@std/encoding/1.0.10/hex.js +0 -101
  222. package/script/deps/jsr.io/@std/msgpack/1.0.3/_types.d.ts +0 -9
  223. package/script/deps/jsr.io/@std/msgpack/1.0.3/_types.d.ts.map +0 -1
  224. package/script/deps/jsr.io/@std/msgpack/1.0.3/_types.js +0 -13
  225. package/script/deps/jsr.io/@std/msgpack/1.0.3/encode.d.ts +0 -39
  226. package/script/deps/jsr.io/@std/msgpack/1.0.3/encode.d.ts.map +0 -1
  227. package/script/deps/jsr.io/@std/msgpack/1.0.3/encode.js +0 -250
  228. package/script/src/signing.d.ts +0 -463
  229. package/script/src/signing.d.ts.map +0 -1
  230. package/script/src/signing.js +0 -1129
@@ -1,406 +1,5 @@
1
- /**
2
- * This module contains functions for generating Hyperliquid transaction signatures
3
- * and interfaces to various wallet implementations.
4
- *
5
- * @example
6
- * ```ts
7
- * import { signL1Action } from "@nktkas/hyperliquid/signing";
8
- *
9
- * const action = {
10
- * type: "cancel",
11
- * cancels: [{ a: 0, o: 12345 }],
12
- * };
13
- * const nonce = Date.now();
14
- *
15
- * const signature = await signL1Action({
16
- * wallet,
17
- * action,
18
- * nonce,
19
- * isTestnet: true, // Change to false for mainnet
20
- * });
21
- * ```
22
- * @example
23
- * ```ts
24
- * import { signUserSignedAction } from "@nktkas/hyperliquid/signing";
25
- *
26
- * const action = {
27
- * type: "approveAgent",
28
- * hyperliquidChain: "Testnet", // "Mainnet" or "Testnet"
29
- * signatureChainId: "0x66eee",
30
- * nonce: Date.now(),
31
- * agentAddress: "0x...",
32
- * agentName: "Agent",
33
- * };
34
- *
35
- * const signature = await signUserSignedAction({
36
- * wallet,
37
- * action,
38
- * types: {
39
- * "HyperliquidTransaction:ApproveAgent": [
40
- * { name: "hyperliquidChain", type: "string" },
41
- * { name: "agentAddress", type: "address" },
42
- * { name: "agentName", type: "string" },
43
- * { name: "nonce", type: "uint64" },
44
- * ],
45
- * },
46
- * chainId: parseInt(action.signatureChainId, 16),
47
- * });
48
- * ```
49
- *
50
- * @module
51
- */
52
- import { keccak_256 } from "@noble/hashes/sha3";
53
- import { encode as encodeMsgpack } from "../deps/jsr.io/@std/msgpack/1.0.3/encode.js";
54
- import { decodeHex, encodeHex } from "../deps/jsr.io/@std/encoding/1.0.10/hex.js";
55
- import { concat } from "../deps/jsr.io/@std/bytes/1.0.6/concat.js";
56
- /**
57
- * Create a hash of the L1 action.
58
- *
59
- * Note: Hash generation depends on the order of the action keys.
60
- * @param action - The action to be hashed.
61
- * @param nonce - Unique request identifier (recommended current timestamp in ms).
62
- * @param vaultAddress - Optional vault address used in the action.
63
- * @param expiresAfter - Optional expiration time of the action in milliseconds since the epoch.
64
- * @returns The hash of the action.
65
- */
66
- export function createL1ActionHash(action, nonce, vaultAddress, expiresAfter) {
67
- // 1. Action
68
- const actionBytes = encodeMsgpack(normalizeIntegersForMsgPack(action));
69
- // 2. Nonce
70
- const nonceBytes = new Uint8Array(8);
71
- new DataView(nonceBytes.buffer).setBigUint64(0, BigInt(nonce));
72
- // 3. Vault address
73
- let vaultMarker;
74
- let vaultBytes;
75
- if (vaultAddress) {
76
- vaultMarker = Uint8Array.of(1);
77
- vaultBytes = decodeHex(vaultAddress.slice(2));
78
- }
79
- else {
80
- vaultMarker = new Uint8Array(1);
81
- vaultBytes = new Uint8Array();
82
- }
83
- // 4. Expires after
84
- let expiresMarker;
85
- let expiresBytes;
86
- if (expiresAfter !== undefined) {
87
- expiresMarker = new Uint8Array(1);
88
- expiresBytes = new Uint8Array(8);
89
- new DataView(expiresBytes.buffer).setBigUint64(0, BigInt(expiresAfter));
90
- }
91
- else {
92
- expiresMarker = new Uint8Array();
93
- expiresBytes = new Uint8Array();
94
- }
95
- // Create a keccak256 hash
96
- const chunks = [
97
- actionBytes,
98
- nonceBytes,
99
- vaultMarker,
100
- vaultBytes,
101
- expiresMarker,
102
- expiresBytes,
103
- ];
104
- const bytes = concat(chunks);
105
- const hash = keccak_256(bytes);
106
- return `0x${encodeHex(hash)}`;
107
- }
108
- /** Layer to make {@link https://jsr.io/@std/msgpack | @std/msgpack} compatible with {@link https://github.com/msgpack/msgpack-javascript | @msgpack/msgpack}. */
109
- function normalizeIntegersForMsgPack(obj) {
110
- const THIRTY_ONE_BITS = 2147483648;
111
- const THIRTY_TWO_BITS = 4294967296;
112
- if (typeof obj === "number" && Number.isInteger(obj) &&
113
- obj <= Number.MAX_SAFE_INTEGER && obj >= Number.MIN_SAFE_INTEGER &&
114
- (obj >= THIRTY_TWO_BITS || obj < -THIRTY_ONE_BITS)) {
115
- return BigInt(obj);
116
- }
117
- if (Array.isArray(obj)) {
118
- return obj.map(normalizeIntegersForMsgPack);
119
- }
120
- if (obj && typeof obj === "object" && obj !== null) {
121
- return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, normalizeIntegersForMsgPack(value)]));
122
- }
123
- return obj;
124
- }
125
- /**
126
- * Sign an L1 action.
127
- *
128
- * Note: Signature generation depends on the order of the action keys.
129
- * @param args - Arguments for signing the action.
130
- * @returns The signature components r, s, and v.
131
- * @example
132
- * ```ts
133
- * import { signL1Action } from "@nktkas/hyperliquid/signing";
134
- * import { privateKeyToAccount } from "viem/accounts";
135
- *
136
- * const wallet = privateKeyToAccount("0x..."); // Your private key
137
- *
138
- * const action = {
139
- * type: "cancel",
140
- * cancels: [
141
- * { a: 0, o: 12345 }, // Asset index and order ID
142
- * ],
143
- * };
144
- * const nonce = Date.now();
145
- *
146
- * const signature = await signL1Action({
147
- * wallet,
148
- * action,
149
- * nonce,
150
- * isTestnet: true, // Change to false for mainnet
151
- * });
152
- *
153
- * const response = await fetch("https://api.hyperliquid-testnet.xyz/exchange", {
154
- * method: "POST",
155
- * headers: { "Content-Type": "application/json" },
156
- * body: JSON.stringify({ action, signature, nonce }),
157
- * });
158
- * const body = await response.json();
159
- * ```
160
- */
161
- export async function signL1Action(args) {
162
- const { wallet, action, nonce, isTestnet = false, vaultAddress, expiresAfter, } = args;
163
- const domain = {
164
- name: "Exchange",
165
- version: "1",
166
- chainId: 1337,
167
- verifyingContract: "0x0000000000000000000000000000000000000000",
168
- };
169
- const types = {
170
- Agent: [
171
- { name: "source", type: "string" },
172
- { name: "connectionId", type: "bytes32" },
173
- ],
174
- };
175
- const actionHash = createL1ActionHash(action, nonce, vaultAddress, expiresAfter);
176
- const message = {
177
- source: isTestnet ? "b" : "a",
178
- connectionId: actionHash,
179
- };
180
- const signature = await abstractSignTypedData({ wallet, domain, types, message });
181
- return splitSignature(signature);
182
- }
183
- /**
184
- * Sign a user-signed action.
185
- *
186
- * Note: Signature generation depends on the order of types.
187
- *
188
- * @param args - Arguments for signing the action.
189
- * @returns The signature components r, s, and v.
190
- * @example
191
- * ```ts
192
- * import { signUserSignedAction } from "@nktkas/hyperliquid/signing";
193
- * import { privateKeyToAccount } from "viem/accounts";
194
- *
195
- * const wallet = privateKeyToAccount("0x..."); // Your private key
196
- *
197
- * const action = {
198
- * type: "approveAgent",
199
- * hyperliquidChain: "Testnet", // "Mainnet" or "Testnet"
200
- * signatureChainId: "0x66eee",
201
- * nonce: Date.now(),
202
- * agentAddress: "0x...", // Change to your agent address
203
- * agentName: "Agent",
204
- * };
205
- *
206
- * const signature = await signUserSignedAction({
207
- * wallet,
208
- * action,
209
- * types: {
210
- * "HyperliquidTransaction:ApproveAgent": [
211
- * { name: "hyperliquidChain", type: "string" },
212
- * { name: "agentAddress", type: "address" },
213
- * { name: "agentName", type: "string" },
214
- * { name: "nonce", type: "uint64" },
215
- * ],
216
- * },
217
- * chainId: parseInt(action.signatureChainId, 16),
218
- * });
219
- *
220
- * const response = await fetch("https://api.hyperliquid-testnet.xyz/exchange", {
221
- * method: "POST",
222
- * headers: { "Content-Type": "application/json" },
223
- * body: JSON.stringify({ action, signature, nonce: action.nonce }),
224
- * });
225
- * const body = await response.json();
226
- * ```
227
- */
228
- export async function signUserSignedAction(args) {
229
- const { wallet, action, types, chainId } = args;
230
- const domain = {
231
- name: "HyperliquidSignTransaction",
232
- version: "1",
233
- chainId,
234
- verifyingContract: "0x0000000000000000000000000000000000000000",
235
- };
236
- const signature = await abstractSignTypedData({ wallet, domain, types, message: action });
237
- return splitSignature(signature);
238
- }
239
- /**
240
- * Sign a multi-signature action.
241
- *
242
- * Note: Signature generation depends on the order of the action keys.
243
- *
244
- * @param args - Arguments for signing the action.
245
- * @returns The signature components r, s, and v.
246
- * @example
247
- * ```ts
248
- * import { signL1Action, signMultiSigAction } from "@nktkas/hyperliquid/signing";
249
- * import { privateKeyToAccount } from "viem/accounts";
250
- *
251
- * const wallet = privateKeyToAccount("0x..."); // Your private key
252
- * const multiSigUser = "0x..."; // Multi-sig user address
253
- *
254
- * const nonce = Date.now();
255
- * const action = { // Example action
256
- * type: "scheduleCancel",
257
- * time: Date.now() + 10000
258
- * };
259
- *
260
- * // First, create signature from one of the authorized signers
261
- * const signature = await signL1Action({
262
- * wallet,
263
- * action: [multiSigUser.toLowerCase(), wallet.address.toLowerCase(), action],
264
- * nonce,
265
- * isTestnet: true,
266
- * });
267
- *
268
- * // Then use it in the multi-sig action
269
- * const multiSigSignature = await signMultiSigAction({
270
- * wallet,
271
- * action: {
272
- * type: "multiSig",
273
- * signatureChainId: "0x66eee",
274
- * signatures: [signature],
275
- * payload: {
276
- * multiSigUser,
277
- * outerSigner: wallet.address,
278
- * action,
279
- * }
280
- * },
281
- * nonce,
282
- * hyperliquidChain: "Testnet",
283
- * signatureChainId: "0x66eee",
284
- * });
285
- * ```
286
- */
287
- export async function signMultiSigAction(args) {
288
- const { wallet, action, nonce, hyperliquidChain, signatureChainId, vaultAddress, expiresAfter, } = args;
289
- const multiSigActionHash = createL1ActionHash(action, nonce, vaultAddress, expiresAfter);
290
- const message = {
291
- multiSigActionHash,
292
- hyperliquidChain,
293
- signatureChainId,
294
- nonce,
295
- };
296
- return await signUserSignedAction({
297
- wallet,
298
- action: message,
299
- types: {
300
- "HyperliquidTransaction:SendMultiSig": [
301
- { name: "hyperliquidChain", type: "string" },
302
- { name: "multiSigActionHash", type: "bytes32" },
303
- { name: "nonce", type: "uint64" },
304
- ],
305
- },
306
- chainId: parseInt(signatureChainId, 16),
307
- });
308
- }
309
- /** Signs typed data with the provided wallet using EIP-712. */
310
- async function abstractSignTypedData(args) {
311
- const { wallet, domain, types, message } = args;
312
- if (isAbstractViemWalletClient(wallet)) {
313
- return await wallet.signTypedData({
314
- domain,
315
- types: {
316
- EIP712Domain: [
317
- { name: "name", type: "string" },
318
- { name: "version", type: "string" },
319
- { name: "chainId", type: "uint256" },
320
- { name: "verifyingContract", type: "address" },
321
- ],
322
- ...types,
323
- },
324
- primaryType: Object.keys(types)[0],
325
- message,
326
- });
327
- }
328
- else if (isAbstractEthersSigner(wallet)) {
329
- return await wallet.signTypedData(domain, types, message);
330
- }
331
- else if (isAbstractEthersV5Signer(wallet)) {
332
- return await wallet._signTypedData(domain, types, message);
333
- }
334
- else if (isAbstractWindowEthereum(wallet)) {
335
- return await signTypedDataWithWindowEthereum(wallet, domain, types, message);
336
- }
337
- else {
338
- throw new Error("Unsupported wallet for signing typed data");
339
- }
340
- }
341
- /** Signs typed data using `window.ethereum` (EIP-1193) with `eth_signTypedData_v4` (EIP-712). */
342
- async function signTypedDataWithWindowEthereum(ethereum, domain, types, message) {
343
- const accounts = await ethereum.request({
344
- method: "eth_requestAccounts",
345
- params: [],
346
- });
347
- if (!Array.isArray(accounts) || accounts.length === 0) {
348
- throw new Error("No Ethereum accounts available");
349
- }
350
- const from = accounts[0];
351
- const dataToSign = JSON.stringify({
352
- domain,
353
- types: {
354
- EIP712Domain: [
355
- { name: "name", type: "string" },
356
- { name: "version", type: "string" },
357
- { name: "chainId", type: "uint256" },
358
- { name: "verifyingContract", type: "address" },
359
- ],
360
- ...types,
361
- },
362
- primaryType: Object.keys(types)[0],
363
- message,
364
- });
365
- return await ethereum.request({
366
- method: "eth_signTypedData_v4",
367
- params: [from, dataToSign],
368
- });
369
- }
370
- /** Splits a signature hexadecimal string into its components. */
371
- function splitSignature(signature) {
372
- const r = `0x${signature.slice(2, 66)}`;
373
- const s = `0x${signature.slice(66, 130)}`;
374
- const v = parseInt(signature.slice(130, 132), 16);
375
- return { r, s, v };
376
- }
377
- /** Checks if the given value is an abstract viem wallet. */
378
- export function isAbstractViemWalletClient(client) {
379
- return typeof client === "object" && client !== null &&
380
- "signTypedData" in client && typeof client.signTypedData === "function" &&
381
- (client.signTypedData.length === 1 || client.signTypedData.length === 2);
382
- }
383
- /** Checks if the given value is an abstract ethers signer. */
384
- export function isAbstractEthersSigner(client) {
385
- return typeof client === "object" && client !== null &&
386
- "signTypedData" in client && typeof client.signTypedData === "function" &&
387
- client.signTypedData.length === 3;
388
- }
389
- /** Checks if the given value is an abstract ethers v5 signer. */
390
- export function isAbstractEthersV5Signer(client) {
391
- return typeof client === "object" && client !== null &&
392
- "_signTypedData" in client && typeof client._signTypedData === "function" &&
393
- client._signTypedData.length === 3;
394
- }
395
- /** Checks if the given value is an abstract `window.ethereum` object. */
396
- export function isAbstractWindowEthereum(client) {
397
- return typeof client === "object" && client !== null &&
398
- "request" in client && typeof client.request === "function" &&
399
- client.request.length >= 1;
400
- }
401
- /** Action sorter for correct signature generation. */
1
+ /** Action sorter and formatter for correct signature generation. */
402
2
  export const actionSorter = {
403
- /** Sorts and formats an `approveAgent` action. */
404
3
  approveAgent: (action) => {
405
4
  return {
406
5
  type: action.type,
@@ -411,7 +10,6 @@ export const actionSorter = {
411
10
  nonce: action.nonce,
412
11
  };
413
12
  },
414
- /** Sorts and formats an `approveBuilderFee` action. */
415
13
  approveBuilderFee: (action) => {
416
14
  return {
417
15
  type: action.type,
@@ -422,7 +20,6 @@ export const actionSorter = {
422
20
  nonce: action.nonce,
423
21
  };
424
22
  },
425
- /** Sorts and formats a `batchModify` action. */
426
23
  batchModify: (action) => {
427
24
  return {
428
25
  type: action.type,
@@ -457,7 +54,6 @@ export const actionSorter = {
457
54
  }),
458
55
  };
459
56
  },
460
- /** Sorts and formats a `cancel` action. */
461
57
  cancel: (action) => {
462
58
  return {
463
59
  type: action.type,
@@ -467,7 +63,6 @@ export const actionSorter = {
467
63
  })),
468
64
  };
469
65
  },
470
- /** Sorts and formats a `cancelByCloid` action. */
471
66
  cancelByCloid: (action) => {
472
67
  return {
473
68
  type: action.type,
@@ -477,7 +72,6 @@ export const actionSorter = {
477
72
  })),
478
73
  };
479
74
  },
480
- /** Sorts and formats a `cDeposit` action. */
481
75
  cDeposit: (action) => {
482
76
  return {
483
77
  type: action.type,
@@ -487,30 +81,26 @@ export const actionSorter = {
487
81
  nonce: action.nonce,
488
82
  };
489
83
  },
490
- /** Sorts and formats a `claimRewards` action. */
491
84
  claimRewards: (action) => {
492
85
  return {
493
86
  type: action.type,
494
87
  };
495
88
  },
496
- /** Sorts and formats a `convertToMultiSigUser` action. */
497
89
  convertToMultiSigUser: (action) => {
498
90
  return {
499
91
  type: action.type,
500
92
  signatureChainId: action.signatureChainId,
501
93
  hyperliquidChain: action.hyperliquidChain,
502
- signers: action.signers,
94
+ signers: action.signers, // key order is not important
503
95
  nonce: action.nonce,
504
96
  };
505
97
  },
506
- /** Sorts and formats a `createSubAccount` action. */
507
98
  createSubAccount: (action) => {
508
99
  return {
509
100
  type: action.type,
510
101
  name: action.name,
511
102
  };
512
103
  },
513
- /** Sorts and formats a `createVault` action. */
514
104
  createVault: (action) => {
515
105
  return {
516
106
  type: action.type,
@@ -520,7 +110,6 @@ export const actionSorter = {
520
110
  nonce: action.nonce,
521
111
  };
522
112
  },
523
- /** Sorts and formats a `CSignerAction` action (jail/unjail). */
524
113
  CSignerAction: (action) => {
525
114
  if ("jailSelf" in action) {
526
115
  return {
@@ -535,7 +124,6 @@ export const actionSorter = {
535
124
  };
536
125
  }
537
126
  },
538
- /** Sorts and formats a `CValidatorAction` action (register/unregister/change profile). */
539
127
  CValidatorAction: (action) => {
540
128
  if ("changeProfile" in action) {
541
129
  return {
@@ -577,7 +165,6 @@ export const actionSorter = {
577
165
  };
578
166
  }
579
167
  },
580
- /** Sorts and formats a `cWithdraw` action. */
581
168
  cWithdraw: (action) => {
582
169
  return {
583
170
  type: action.type,
@@ -587,14 +174,12 @@ export const actionSorter = {
587
174
  nonce: action.nonce,
588
175
  };
589
176
  },
590
- /** Sorts and formats an `evmUserModify` action. */
591
177
  evmUserModify: (action) => {
592
178
  return {
593
179
  type: action.type,
594
180
  usingBigBlocks: action.usingBigBlocks,
595
181
  };
596
182
  },
597
- /** Sorts and formats a `modify` action. */
598
183
  modify: (action) => {
599
184
  const sortedAction = {
600
185
  type: action.type,
@@ -625,7 +210,6 @@ export const actionSorter = {
625
210
  delete sortedAction.order.c;
626
211
  return sortedAction;
627
212
  },
628
- /** Sorts and formats a `multiSig` action. */
629
213
  multiSig: (action) => {
630
214
  return {
631
215
  type: action.type,
@@ -638,11 +222,10 @@ export const actionSorter = {
638
222
  payload: {
639
223
  multiSigUser: action.payload.multiSigUser.toLowerCase(),
640
224
  outerSigner: action.payload.outerSigner.toLowerCase(),
641
- action: action.payload.action,
225
+ action: structuredClone(action.payload.action),
642
226
  },
643
227
  };
644
228
  },
645
- /** Sorts and formats an `order` action. */
646
229
  order: (action) => {
647
230
  const sortedAction = {
648
231
  type: action.type,
@@ -684,7 +267,6 @@ export const actionSorter = {
684
267
  delete sortedAction.builder;
685
268
  return sortedAction;
686
269
  },
687
- /** Sorts and formats a `perpDeploy` action. */
688
270
  perpDeploy: (action) => {
689
271
  if ("registerAsset" in action) {
690
272
  return {
@@ -714,13 +296,12 @@ export const actionSorter = {
714
296
  type: action.type,
715
297
  setOracle: {
716
298
  dex: action.setOracle.dex,
717
- oraclePxs: action.setOracle.oraclePxs,
718
- markPxs: action.setOracle.markPxs,
299
+ oraclePxs: action.setOracle.oraclePxs.map((el) => [...el]),
300
+ markPxs: action.setOracle.markPxs.map((el) => [...el]),
719
301
  },
720
302
  };
721
303
  }
722
304
  },
723
- /** Sorts and formats a `PerpDexClassTransfer` action. */
724
305
  PerpDexClassTransfer: (action) => {
725
306
  return {
726
307
  type: action.type,
@@ -733,21 +314,29 @@ export const actionSorter = {
733
314
  nonce: action.nonce,
734
315
  };
735
316
  },
736
- /** Sorts and formats a `registerReferrer` action. */
317
+ PerpDexTransfer: (action) => {
318
+ return {
319
+ type: action.type,
320
+ signatureChainId: action.signatureChainId,
321
+ hyperliquidChain: action.hyperliquidChain,
322
+ sourceDex: action.sourceDex,
323
+ destinationDex: action.destinationDex,
324
+ amount: action.amount,
325
+ nonce: action.nonce,
326
+ };
327
+ },
737
328
  registerReferrer: (action) => {
738
329
  return {
739
330
  type: action.type,
740
331
  code: action.code,
741
332
  };
742
333
  },
743
- /** Sorts and formats a `reserveRequestWeight` action. */
744
334
  reserveRequestWeight: (action) => {
745
335
  return {
746
336
  type: action.type,
747
337
  weight: action.weight,
748
338
  };
749
339
  },
750
- /** Sorts and formats a `scheduleCancel` action. */
751
340
  scheduleCancel: (action) => {
752
341
  const sortedAction = {
753
342
  type: action.type,
@@ -757,21 +346,18 @@ export const actionSorter = {
757
346
  delete sortedAction.time;
758
347
  return sortedAction;
759
348
  },
760
- /** Sorts and formats a `setDisplayName` action. */
761
349
  setDisplayName: (action) => {
762
350
  return {
763
351
  type: action.type,
764
352
  displayName: action.displayName,
765
353
  };
766
354
  },
767
- /** Sorts and formats a `setReferrer` action. */
768
355
  setReferrer: (action) => {
769
356
  return {
770
357
  type: action.type,
771
358
  code: action.code,
772
359
  };
773
360
  },
774
- /** Sorts and formats a `spotDeploy` action. */
775
361
  spotDeploy: (action) => {
776
362
  if ("genesis" in action) {
777
363
  const sortedAction = {
@@ -807,7 +393,7 @@ export const actionSorter = {
807
393
  return {
808
394
  type: action.type,
809
395
  registerSpot: {
810
- tokens: action.registerSpot.tokens,
396
+ tokens: [...action.registerSpot.tokens],
811
397
  },
812
398
  };
813
399
  }
@@ -843,9 +429,9 @@ export const actionSorter = {
843
429
  type: action.type,
844
430
  userGenesis: {
845
431
  token: action.userGenesis.token,
846
- userAndWei: action.userGenesis.userAndWei,
847
- existingTokenAndWei: action.userGenesis.existingTokenAndWei,
848
- blacklistUsers: action.userGenesis.blacklistUsers,
432
+ userAndWei: action.userGenesis.userAndWei.map((el) => [...el]),
433
+ existingTokenAndWei: action.userGenesis.existingTokenAndWei.map((el) => [...el]),
434
+ blacklistUsers: action.userGenesis.blacklistUsers?.map((el) => [...el]),
849
435
  },
850
436
  };
851
437
  if (sortedAction.userGenesis.blacklistUsers === undefined) {
@@ -854,7 +440,6 @@ export const actionSorter = {
854
440
  return sortedAction;
855
441
  }
856
442
  },
857
- /** Sorts and formats a `spotSend` action. */
858
443
  spotSend: (action) => {
859
444
  return {
860
445
  type: action.type,
@@ -866,7 +451,6 @@ export const actionSorter = {
866
451
  time: action.time,
867
452
  };
868
453
  },
869
- /** Sorts and formats a `spotUser` action. */
870
454
  spotUser: (action) => {
871
455
  return {
872
456
  type: action.type,
@@ -875,7 +459,6 @@ export const actionSorter = {
875
459
  },
876
460
  };
877
461
  },
878
- /** Sorts and formats a `subAccountSpotTransfer` action. */
879
462
  subAccountSpotTransfer: (action) => {
880
463
  return {
881
464
  type: action.type,
@@ -885,7 +468,6 @@ export const actionSorter = {
885
468
  amount: action.amount,
886
469
  };
887
470
  },
888
- /** Sorts and formats a `subAccountTransfer` action. */
889
471
  subAccountTransfer: (action) => {
890
472
  return {
891
473
  type: action.type,
@@ -894,7 +476,6 @@ export const actionSorter = {
894
476
  usd: action.usd,
895
477
  };
896
478
  },
897
- /** Sorts and formats a `tokenDelegate` action. */
898
479
  tokenDelegate: (action) => {
899
480
  return {
900
481
  type: action.type,
@@ -906,7 +487,6 @@ export const actionSorter = {
906
487
  nonce: action.nonce,
907
488
  };
908
489
  },
909
- /** Sorts and formats a `twapCancel` action. */
910
490
  twapCancel: (action) => {
911
491
  return {
912
492
  type: action.type,
@@ -914,7 +494,6 @@ export const actionSorter = {
914
494
  t: action.t,
915
495
  };
916
496
  },
917
- /** Sorts and formats a `twapOrder` action. */
918
497
  twapOrder: (action) => {
919
498
  return {
920
499
  type: action.type,
@@ -928,7 +507,6 @@ export const actionSorter = {
928
507
  },
929
508
  };
930
509
  },
931
- /** Sorts and formats an `updateIsolatedMargin` action. */
932
510
  updateIsolatedMargin: (action) => {
933
511
  return {
934
512
  type: action.type,
@@ -937,7 +515,6 @@ export const actionSorter = {
937
515
  ntli: action.ntli,
938
516
  };
939
517
  },
940
- /** Sorts and formats an `updateLeverage` action. */
941
518
  updateLeverage: (action) => {
942
519
  return {
943
520
  type: action.type,
@@ -946,7 +523,6 @@ export const actionSorter = {
946
523
  leverage: action.leverage,
947
524
  };
948
525
  },
949
- /** Sorts and formats an `usdClassTransfer` action. */
950
526
  usdClassTransfer: (action) => {
951
527
  return {
952
528
  type: action.type,
@@ -957,7 +533,6 @@ export const actionSorter = {
957
533
  nonce: action.nonce,
958
534
  };
959
535
  },
960
- /** Sorts and formats an `usdSend` action. */
961
536
  usdSend: (action) => {
962
537
  return {
963
538
  type: action.type,
@@ -968,7 +543,6 @@ export const actionSorter = {
968
543
  time: action.time,
969
544
  };
970
545
  },
971
- /** Sorts and formats a `vaultDistribute` action. */
972
546
  vaultDistribute: (action) => {
973
547
  return {
974
548
  type: action.type,
@@ -976,7 +550,6 @@ export const actionSorter = {
976
550
  usd: action.usd,
977
551
  };
978
552
  },
979
- /** Sorts and formats a `vaultModify` action. */
980
553
  vaultModify: (action) => {
981
554
  return {
982
555
  type: action.type,
@@ -985,7 +558,6 @@ export const actionSorter = {
985
558
  alwaysCloseOnWithdraw: action.alwaysCloseOnWithdraw,
986
559
  };
987
560
  },
988
- /** Sorts and formats a `vaultTransfer` action. */
989
561
  vaultTransfer: (action) => {
990
562
  return {
991
563
  type: action.type,
@@ -994,7 +566,6 @@ export const actionSorter = {
994
566
  usd: action.usd,
995
567
  };
996
568
  },
997
- /** Sorts and formats a `withdraw3` action. */
998
569
  withdraw3: (action) => {
999
570
  return {
1000
571
  type: action.type,
@@ -1063,6 +634,22 @@ export const userSignedActionEip712Types = {
1063
634
  { name: "nonce", type: "uint64" },
1064
635
  ],
1065
636
  },
637
+ PerpDexTransfer: {
638
+ "HyperliquidTransaction:PerpDexTransfer": [
639
+ { name: "hyperliquidChain", type: "string" },
640
+ { name: "sourceDex", type: "string" },
641
+ { name: "destinationDex", type: "string" },
642
+ { name: "amount", type: "string" },
643
+ { name: "nonce", type: "uint64" },
644
+ ],
645
+ },
646
+ multiSig: {
647
+ "HyperliquidTransaction:SendMultiSig": [
648
+ { name: "hyperliquidChain", type: "string" },
649
+ { name: "multiSigActionHash", type: "bytes32" },
650
+ { name: "nonce", type: "uint64" },
651
+ ],
652
+ },
1066
653
  spotSend: {
1067
654
  "HyperliquidTransaction:SpotSend": [
1068
655
  { name: "hyperliquidChain", type: "string" },