@nktkas/hyperliquid 0.22.1 → 0.22.2

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 (58) hide show
  1. package/README.md +84 -27
  2. package/esm/mod.d.ts +1 -1
  3. package/esm/mod.d.ts.map +1 -1
  4. package/esm/src/clients/exchange.d.ts +136 -166
  5. package/esm/src/clients/exchange.d.ts.map +1 -1
  6. package/esm/src/clients/exchange.js +121 -146
  7. package/esm/src/clients/multiSign.d.ts +121 -280
  8. package/esm/src/clients/multiSign.d.ts.map +1 -1
  9. package/esm/src/clients/multiSign.js +123 -246
  10. package/esm/src/signing/_ethers.d.ts +33 -0
  11. package/esm/src/signing/_ethers.d.ts.map +1 -0
  12. package/esm/src/signing/_ethers.js +12 -0
  13. package/esm/src/signing/_private_key.d.ts +22 -0
  14. package/esm/src/signing/_private_key.d.ts.map +1 -0
  15. package/esm/src/signing/_private_key.js +124 -0
  16. package/esm/src/signing/_sorter.d.ts +154 -0
  17. package/esm/src/signing/_sorter.d.ts.map +1 -0
  18. package/esm/src/{signing.js → signing/_sorter.js} +0 -400
  19. package/esm/src/signing/_viem.d.ts +23 -0
  20. package/esm/src/signing/_viem.d.ts.map +1 -0
  21. package/esm/src/signing/_viem.js +6 -0
  22. package/esm/src/signing/_window.d.ts +23 -0
  23. package/esm/src/signing/_window.d.ts.map +1 -0
  24. package/esm/src/signing/_window.js +29 -0
  25. package/esm/src/signing/mod.d.ts +251 -0
  26. package/esm/src/signing/mod.d.ts.map +1 -0
  27. package/esm/src/signing/mod.js +352 -0
  28. package/package.json +6 -5
  29. package/script/mod.d.ts +1 -1
  30. package/script/mod.d.ts.map +1 -1
  31. package/script/src/clients/exchange.d.ts +136 -166
  32. package/script/src/clients/exchange.d.ts.map +1 -1
  33. package/script/src/clients/exchange.js +205 -230
  34. package/script/src/clients/multiSign.d.ts +121 -280
  35. package/script/src/clients/multiSign.d.ts.map +1 -1
  36. package/script/src/clients/multiSign.js +168 -291
  37. package/script/src/signing/_ethers.d.ts +33 -0
  38. package/script/src/signing/_ethers.d.ts.map +1 -0
  39. package/script/src/signing/_ethers.js +26 -0
  40. package/script/src/signing/_private_key.d.ts +22 -0
  41. package/script/src/signing/_private_key.d.ts.map +1 -0
  42. package/script/src/signing/_private_key.js +138 -0
  43. package/script/src/signing/_sorter.d.ts +154 -0
  44. package/script/src/signing/_sorter.d.ts.map +1 -0
  45. package/script/src/{signing.js → signing/_sorter.js} +1 -409
  46. package/script/src/signing/_viem.d.ts +23 -0
  47. package/script/src/signing/_viem.d.ts.map +1 -0
  48. package/script/src/signing/_viem.js +19 -0
  49. package/script/src/signing/_window.d.ts +23 -0
  50. package/script/src/signing/_window.d.ts.map +1 -0
  51. package/script/src/signing/_window.js +43 -0
  52. package/script/src/signing/mod.d.ts +251 -0
  53. package/script/src/signing/mod.d.ts.map +1 -0
  54. package/script/src/signing/mod.js +387 -0
  55. package/esm/src/signing.d.ts +0 -463
  56. package/esm/src/signing.d.ts.map +0 -1
  57. package/script/src/signing.d.ts +0 -463
  58. package/script/src/signing.d.ts.map +0 -1
@@ -0,0 +1,251 @@
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 { type ValueMap, type ValueType } from "../../deps/jsr.io/@std/msgpack/1.0.3/encode.js";
53
+ import { type AbstractEthersSigner, type AbstractEthersV5Signer, isAbstractEthersSigner, isAbstractEthersV5Signer } from "./_ethers.js";
54
+ import { isValidPrivateKey } from "./_private_key.js";
55
+ import { type AbstractViemWalletClient, isAbstractViemWalletClient } from "./_viem.js";
56
+ import { type AbstractWindowEthereum, isAbstractWindowEthereum } from "./_window.js";
57
+ import type { Hex } from "../base.js";
58
+ export { type AbstractEthersSigner, type AbstractEthersV5Signer, type AbstractViemWalletClient, type AbstractWindowEthereum, type Hex, isAbstractEthersSigner, isAbstractEthersV5Signer, isAbstractViemWalletClient, isAbstractWindowEthereum, isValidPrivateKey, type ValueMap, type ValueType, };
59
+ export * from "./_sorter.js";
60
+ /** Abstract interface for a wallet that can sign typed data. */
61
+ export type AbstractWallet = Hex | AbstractViemWalletClient | AbstractEthersSigner | AbstractEthersV5Signer | AbstractWindowEthereum;
62
+ export interface Signature {
63
+ r: Hex;
64
+ s: Hex;
65
+ v: number;
66
+ }
67
+ /**
68
+ * Create a hash of the L1 action.
69
+ *
70
+ * Note: Hash generation depends on the order of the action keys.
71
+ *
72
+ * @param action - The action to be hashed.
73
+ * @param nonce - Unique request identifier (recommended current timestamp in ms).
74
+ * @param vaultAddress - Optional vault address used in the action.
75
+ * @param expiresAfter - Optional expiration time of the action in milliseconds since the epoch.
76
+ * @returns The hash of the action.
77
+ */
78
+ export declare function createL1ActionHash(action: ValueType, nonce: number, vaultAddress?: Hex, expiresAfter?: number): Hex;
79
+ /**
80
+ * Sign an L1 action.
81
+ *
82
+ * Note: Signature generation depends on the order of the action keys.
83
+ * @param args - Arguments for signing the action.
84
+ * @returns The signature components r, s, and v.
85
+ * @example
86
+ * ```ts
87
+ * import { signL1Action } from "@nktkas/hyperliquid/signing";
88
+ *
89
+ * const privateKey = "0x..."; // or `viem`, `ethers`
90
+ *
91
+ * const action = {
92
+ * type: "cancel",
93
+ * cancels: [
94
+ * { a: 0, o: 12345 }, // Asset index and order ID
95
+ * ],
96
+ * };
97
+ * const nonce = Date.now();
98
+ *
99
+ * const signature = await signL1Action({
100
+ * wallet: privateKey,
101
+ * action,
102
+ * nonce,
103
+ * isTestnet: true, // Change to false for mainnet
104
+ * });
105
+ *
106
+ * const response = await fetch("https://api.hyperliquid-testnet.xyz/exchange", {
107
+ * method: "POST",
108
+ * headers: { "Content-Type": "application/json" },
109
+ * body: JSON.stringify({ action, signature, nonce }),
110
+ * });
111
+ * const body = await response.json();
112
+ * ```
113
+ */
114
+ export declare function signL1Action(args: {
115
+ /** Wallet to sign the action. */
116
+ wallet: AbstractWallet;
117
+ /** The action to be signed. */
118
+ action: ValueType;
119
+ /** Unique request identifier (recommended current timestamp in ms). */
120
+ nonce: number;
121
+ /** Indicates if the action is for the testnet. Default is `false`. */
122
+ isTestnet?: boolean;
123
+ /** Optional vault address used in the action. */
124
+ vaultAddress?: Hex;
125
+ /** Optional expiration time of the action in milliseconds since the epoch. */
126
+ expiresAfter?: number;
127
+ }): Promise<Signature>;
128
+ /**
129
+ * Sign a user-signed action.
130
+ *
131
+ * Note: Signature generation depends on the order of types.
132
+ *
133
+ * @param args - Arguments for signing the action.
134
+ * @returns The signature components r, s, and v.
135
+ * @example
136
+ * ```ts
137
+ * import { signUserSignedAction } from "@nktkas/hyperliquid/signing";
138
+ *
139
+ * const privateKey = "0x..."; // or `viem`, `ethers`
140
+ *
141
+ * const action = {
142
+ * type: "approveAgent",
143
+ * hyperliquidChain: "Testnet", // "Mainnet" or "Testnet"
144
+ * signatureChainId: "0x66eee",
145
+ * nonce: Date.now(),
146
+ * agentAddress: "0x...", // Change to your agent address
147
+ * agentName: "Agent",
148
+ * };
149
+ *
150
+ * const signature = await signUserSignedAction({
151
+ * wallet: privateKey,
152
+ * action,
153
+ * types: {
154
+ * "HyperliquidTransaction:ApproveAgent": [
155
+ * { name: "hyperliquidChain", type: "string" },
156
+ * { name: "agentAddress", type: "address" },
157
+ * { name: "agentName", type: "string" },
158
+ * { name: "nonce", type: "uint64" },
159
+ * ],
160
+ * },
161
+ * chainId: parseInt(action.signatureChainId, 16),
162
+ * });
163
+ *
164
+ * const response = await fetch("https://api.hyperliquid-testnet.xyz/exchange", {
165
+ * method: "POST",
166
+ * headers: { "Content-Type": "application/json" },
167
+ * body: JSON.stringify({ action, signature, nonce: action.nonce }),
168
+ * });
169
+ * const body = await response.json();
170
+ * ```
171
+ */
172
+ export declare function signUserSignedAction(args: {
173
+ /** Wallet to sign the action. */
174
+ wallet: AbstractWallet;
175
+ /** The action to be signed. */
176
+ action: Record<string, unknown>;
177
+ /** The types of the action. */
178
+ types: {
179
+ [key: string]: {
180
+ name: string;
181
+ type: string;
182
+ }[];
183
+ };
184
+ /** The chain ID. */
185
+ chainId: number;
186
+ }): Promise<Signature>;
187
+ /**
188
+ * Sign a multi-signature action.
189
+ *
190
+ * Note: Signature generation depends on the order of the action keys.
191
+ *
192
+ * @param args - Arguments for signing the action.
193
+ * @returns The signature components r, s, and v.
194
+ * @example
195
+ * ```ts
196
+ * import { signL1Action, signMultiSigAction } from "@nktkas/hyperliquid/signing";
197
+ * import { privateKeyToAccount } from "viem/accounts";
198
+ *
199
+ * const wallet = privateKeyToAccount("0x...");
200
+ * const multiSigUser = "0x..."; // Multi-sig user address
201
+ *
202
+ * const nonce = Date.now();
203
+ * const action = { // Example action
204
+ * type: "scheduleCancel",
205
+ * time: Date.now() + 10000
206
+ * };
207
+ *
208
+ * // First, create signature from one of the authorized signers
209
+ * const signature = await signL1Action({
210
+ * wallet,
211
+ * action: [multiSigUser.toLowerCase(), wallet.address.toLowerCase(), action],
212
+ * nonce,
213
+ * isTestnet: true,
214
+ * });
215
+ *
216
+ * // Then use it in the multi-sig action
217
+ * const multiSigSignature = await signMultiSigAction({
218
+ * wallet,
219
+ * action: {
220
+ * type: "multiSig",
221
+ * signatureChainId: "0x66eee",
222
+ * signatures: [signature],
223
+ * payload: {
224
+ * multiSigUser,
225
+ * outerSigner: wallet.address,
226
+ * action,
227
+ * }
228
+ * },
229
+ * nonce,
230
+ * hyperliquidChain: "Testnet",
231
+ * signatureChainId: "0x66eee",
232
+ * });
233
+ * ```
234
+ */
235
+ export declare function signMultiSigAction(args: {
236
+ /** Wallet to sign the action. */
237
+ wallet: AbstractWallet;
238
+ /** The action to be signed. */
239
+ action: ValueMap;
240
+ /** Unique request identifier (recommended current timestamp in ms). */
241
+ nonce: number;
242
+ /** Optional vault address used in the action. */
243
+ vaultAddress?: Hex;
244
+ /** Optional expiration time of the action in milliseconds since the epoch. */
245
+ expiresAfter?: number;
246
+ /** HyperLiquid network ("Mainnet" or "Testnet"). */
247
+ hyperliquidChain: "Mainnet" | "Testnet";
248
+ /** Chain ID used for signing. */
249
+ signatureChainId: Hex;
250
+ }): Promise<Signature>;
251
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../../src/src/signing/mod.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,352 @@
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 as concatBytes } from "../../deps/jsr.io/@std/bytes/1.0.6/concat.js";
56
+ import { isAbstractEthersSigner, isAbstractEthersV5Signer, } from "./_ethers.js";
57
+ import { isValidPrivateKey, signTypedDataWithPrivateKey } from "./_private_key.js";
58
+ import { isAbstractViemWalletClient } from "./_viem.js";
59
+ import { isAbstractWindowEthereum, signTypedDataWithWindowEthereum } from "./_window.js";
60
+ export { isAbstractEthersSigner, isAbstractEthersV5Signer, isAbstractViemWalletClient, isAbstractWindowEthereum, isValidPrivateKey, };
61
+ export * from "./_sorter.js";
62
+ /**
63
+ * Create a hash of the L1 action.
64
+ *
65
+ * Note: Hash generation depends on the order of the action keys.
66
+ *
67
+ * @param action - The action to be hashed.
68
+ * @param nonce - Unique request identifier (recommended current timestamp in ms).
69
+ * @param vaultAddress - Optional vault address used in the action.
70
+ * @param expiresAfter - Optional expiration time of the action in milliseconds since the epoch.
71
+ * @returns The hash of the action.
72
+ */
73
+ export function createL1ActionHash(action, nonce, vaultAddress, expiresAfter) {
74
+ // 1. Action
75
+ const actionBytes = encodeMsgpack(normalizeIntegersForMsgPack(action));
76
+ // 2. Nonce
77
+ const nonceBytes = new Uint8Array(8);
78
+ new DataView(nonceBytes.buffer).setBigUint64(0, BigInt(nonce));
79
+ // 3. Vault address
80
+ const vaultMarker = vaultAddress ? Uint8Array.of(1) : Uint8Array.of(0);
81
+ const vaultBytes = vaultAddress ? decodeHex(vaultAddress.slice(2)) : new Uint8Array();
82
+ // 4. Expires after
83
+ let expiresMarker;
84
+ let expiresBytes;
85
+ if (expiresAfter !== undefined) {
86
+ expiresMarker = Uint8Array.of(0);
87
+ expiresBytes = new Uint8Array(8);
88
+ new DataView(expiresBytes.buffer).setBigUint64(0, BigInt(expiresAfter));
89
+ }
90
+ else {
91
+ expiresMarker = new Uint8Array();
92
+ expiresBytes = new Uint8Array();
93
+ }
94
+ // Create a keccak256 hash
95
+ const bytes = concatBytes([
96
+ actionBytes,
97
+ nonceBytes,
98
+ vaultMarker,
99
+ vaultBytes,
100
+ expiresMarker,
101
+ expiresBytes,
102
+ ]);
103
+ const hash = keccak_256(bytes);
104
+ return `0x${encodeHex(hash)}`;
105
+ }
106
+ /** Layer to make {@link https://jsr.io/@std/msgpack | @std/msgpack} compatible with {@link https://github.com/msgpack/msgpack-javascript | @msgpack/msgpack}. */
107
+ function normalizeIntegersForMsgPack(obj) {
108
+ const THIRTY_ONE_BITS = 2147483648;
109
+ const THIRTY_TWO_BITS = 4294967296;
110
+ if (typeof obj === "number" && Number.isInteger(obj) &&
111
+ obj <= Number.MAX_SAFE_INTEGER && obj >= Number.MIN_SAFE_INTEGER &&
112
+ (obj >= THIRTY_TWO_BITS || obj < -THIRTY_ONE_BITS)) {
113
+ return BigInt(obj);
114
+ }
115
+ if (Array.isArray(obj)) {
116
+ return obj.map(normalizeIntegersForMsgPack);
117
+ }
118
+ if (obj && typeof obj === "object" && obj !== null) {
119
+ return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, normalizeIntegersForMsgPack(value)]));
120
+ }
121
+ return obj;
122
+ }
123
+ /**
124
+ * Sign an L1 action.
125
+ *
126
+ * Note: Signature generation depends on the order of the action keys.
127
+ * @param args - Arguments for signing the action.
128
+ * @returns The signature components r, s, and v.
129
+ * @example
130
+ * ```ts
131
+ * import { signL1Action } from "@nktkas/hyperliquid/signing";
132
+ *
133
+ * const privateKey = "0x..."; // or `viem`, `ethers`
134
+ *
135
+ * const action = {
136
+ * type: "cancel",
137
+ * cancels: [
138
+ * { a: 0, o: 12345 }, // Asset index and order ID
139
+ * ],
140
+ * };
141
+ * const nonce = Date.now();
142
+ *
143
+ * const signature = await signL1Action({
144
+ * wallet: privateKey,
145
+ * action,
146
+ * nonce,
147
+ * isTestnet: true, // Change to false for mainnet
148
+ * });
149
+ *
150
+ * const response = await fetch("https://api.hyperliquid-testnet.xyz/exchange", {
151
+ * method: "POST",
152
+ * headers: { "Content-Type": "application/json" },
153
+ * body: JSON.stringify({ action, signature, nonce }),
154
+ * });
155
+ * const body = await response.json();
156
+ * ```
157
+ */
158
+ export async function signL1Action(args) {
159
+ const { wallet, action, nonce, isTestnet = false, vaultAddress, expiresAfter, } = args;
160
+ const domain = {
161
+ name: "Exchange",
162
+ version: "1",
163
+ chainId: 1337, // hyperliquid requires a fixed chain
164
+ verifyingContract: "0x0000000000000000000000000000000000000000",
165
+ };
166
+ const types = {
167
+ Agent: [
168
+ { name: "source", type: "string" },
169
+ { name: "connectionId", type: "bytes32" },
170
+ ],
171
+ };
172
+ const actionHash = createL1ActionHash(action, nonce, vaultAddress, expiresAfter);
173
+ const message = {
174
+ source: isTestnet ? "b" : "a",
175
+ connectionId: actionHash,
176
+ };
177
+ const signature = await abstractSignTypedData({ wallet, domain, types, message });
178
+ return splitSignature(signature);
179
+ }
180
+ /**
181
+ * Sign a user-signed action.
182
+ *
183
+ * Note: Signature generation depends on the order of types.
184
+ *
185
+ * @param args - Arguments for signing the action.
186
+ * @returns The signature components r, s, and v.
187
+ * @example
188
+ * ```ts
189
+ * import { signUserSignedAction } from "@nktkas/hyperliquid/signing";
190
+ *
191
+ * const privateKey = "0x..."; // or `viem`, `ethers`
192
+ *
193
+ * const action = {
194
+ * type: "approveAgent",
195
+ * hyperliquidChain: "Testnet", // "Mainnet" or "Testnet"
196
+ * signatureChainId: "0x66eee",
197
+ * nonce: Date.now(),
198
+ * agentAddress: "0x...", // Change to your agent address
199
+ * agentName: "Agent",
200
+ * };
201
+ *
202
+ * const signature = await signUserSignedAction({
203
+ * wallet: privateKey,
204
+ * action,
205
+ * types: {
206
+ * "HyperliquidTransaction:ApproveAgent": [
207
+ * { name: "hyperliquidChain", type: "string" },
208
+ * { name: "agentAddress", type: "address" },
209
+ * { name: "agentName", type: "string" },
210
+ * { name: "nonce", type: "uint64" },
211
+ * ],
212
+ * },
213
+ * chainId: parseInt(action.signatureChainId, 16),
214
+ * });
215
+ *
216
+ * const response = await fetch("https://api.hyperliquid-testnet.xyz/exchange", {
217
+ * method: "POST",
218
+ * headers: { "Content-Type": "application/json" },
219
+ * body: JSON.stringify({ action, signature, nonce: action.nonce }),
220
+ * });
221
+ * const body = await response.json();
222
+ * ```
223
+ */
224
+ export async function signUserSignedAction(args) {
225
+ const { wallet, action, types, chainId } = args;
226
+ const domain = {
227
+ name: "HyperliquidSignTransaction",
228
+ version: "1",
229
+ chainId,
230
+ verifyingContract: "0x0000000000000000000000000000000000000000",
231
+ };
232
+ const signature = await abstractSignTypedData({ wallet, domain, types, message: action });
233
+ return splitSignature(signature);
234
+ }
235
+ /**
236
+ * Sign a multi-signature action.
237
+ *
238
+ * Note: Signature generation depends on the order of the action keys.
239
+ *
240
+ * @param args - Arguments for signing the action.
241
+ * @returns The signature components r, s, and v.
242
+ * @example
243
+ * ```ts
244
+ * import { signL1Action, signMultiSigAction } from "@nktkas/hyperliquid/signing";
245
+ * import { privateKeyToAccount } from "viem/accounts";
246
+ *
247
+ * const wallet = privateKeyToAccount("0x...");
248
+ * const multiSigUser = "0x..."; // Multi-sig user address
249
+ *
250
+ * const nonce = Date.now();
251
+ * const action = { // Example action
252
+ * type: "scheduleCancel",
253
+ * time: Date.now() + 10000
254
+ * };
255
+ *
256
+ * // First, create signature from one of the authorized signers
257
+ * const signature = await signL1Action({
258
+ * wallet,
259
+ * action: [multiSigUser.toLowerCase(), wallet.address.toLowerCase(), action],
260
+ * nonce,
261
+ * isTestnet: true,
262
+ * });
263
+ *
264
+ * // Then use it in the multi-sig action
265
+ * const multiSigSignature = await signMultiSigAction({
266
+ * wallet,
267
+ * action: {
268
+ * type: "multiSig",
269
+ * signatureChainId: "0x66eee",
270
+ * signatures: [signature],
271
+ * payload: {
272
+ * multiSigUser,
273
+ * outerSigner: wallet.address,
274
+ * action,
275
+ * }
276
+ * },
277
+ * nonce,
278
+ * hyperliquidChain: "Testnet",
279
+ * signatureChainId: "0x66eee",
280
+ * });
281
+ * ```
282
+ */
283
+ export async function signMultiSigAction(args) {
284
+ const { wallet, action, nonce, hyperliquidChain, signatureChainId, vaultAddress, expiresAfter, } = args;
285
+ const multiSigActionHash = createL1ActionHash(action, nonce, vaultAddress, expiresAfter);
286
+ const message = {
287
+ multiSigActionHash,
288
+ hyperliquidChain,
289
+ signatureChainId,
290
+ nonce,
291
+ };
292
+ return await signUserSignedAction({
293
+ wallet,
294
+ action: message,
295
+ types: {
296
+ "HyperliquidTransaction:SendMultiSig": [
297
+ { name: "hyperliquidChain", type: "string" },
298
+ { name: "multiSigActionHash", type: "bytes32" },
299
+ { name: "nonce", type: "uint64" },
300
+ ],
301
+ },
302
+ chainId: parseInt(signatureChainId, 16),
303
+ });
304
+ }
305
+ /** Signs typed data with the provided wallet using EIP-712. */
306
+ async function abstractSignTypedData(args) {
307
+ const { wallet, domain, types, message } = args;
308
+ if (isValidPrivateKey(wallet)) {
309
+ return await signTypedDataWithPrivateKey({
310
+ privateKey: wallet,
311
+ domain,
312
+ types,
313
+ primaryType: Object.keys(types)[0],
314
+ message,
315
+ });
316
+ }
317
+ else if (isAbstractViemWalletClient(wallet)) {
318
+ return await wallet.signTypedData({
319
+ domain,
320
+ types: {
321
+ EIP712Domain: [
322
+ { name: "name", type: "string" },
323
+ { name: "version", type: "string" },
324
+ { name: "chainId", type: "uint256" },
325
+ { name: "verifyingContract", type: "address" },
326
+ ],
327
+ ...types,
328
+ },
329
+ primaryType: Object.keys(types)[0],
330
+ message,
331
+ });
332
+ }
333
+ else if (isAbstractEthersSigner(wallet)) {
334
+ return await wallet.signTypedData(domain, types, message);
335
+ }
336
+ else if (isAbstractEthersV5Signer(wallet)) {
337
+ return await wallet._signTypedData(domain, types, message);
338
+ }
339
+ else if (isAbstractWindowEthereum(wallet)) {
340
+ return await signTypedDataWithWindowEthereum(wallet, domain, types, message);
341
+ }
342
+ else {
343
+ throw new Error("Unsupported wallet for signing typed data");
344
+ }
345
+ }
346
+ /** Splits a signature hexadecimal string into its components. */
347
+ function splitSignature(signature) {
348
+ const r = `0x${signature.slice(2, 66)}`;
349
+ const s = `0x${signature.slice(66, 130)}`;
350
+ const v = parseInt(signature.slice(130, 132), 16);
351
+ return { r, s, v };
352
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nktkas/hyperliquid",
3
- "version": "0.22.1",
3
+ "version": "0.22.2",
4
4
  "description": "Unofficial Hyperliquid API SDK for all major JS runtimes, written in TypeScript and provided with tests",
5
5
  "keywords": [
6
6
  "api",
@@ -42,17 +42,18 @@
42
42
  "require": "./script/src/types/mod.js"
43
43
  },
44
44
  "./signing": {
45
- "import": "./esm/src/signing.js",
46
- "require": "./script/src/signing.js"
45
+ "import": "./esm/src/signing/mod.js",
46
+ "require": "./script/src/signing/mod.js"
47
47
  }
48
48
  },
49
49
  "scripts": {},
50
50
  "engines": {
51
- "node": ">=22.4.0"
51
+ "node": ">=24.0.0"
52
52
  },
53
53
  "sideEffects": false,
54
54
  "dependencies": {
55
- "@noble/hashes": "^1.8.0"
55
+ "@noble/hashes": "^1.8.0",
56
+ "@noble/secp256k1": "^2.3.0"
56
57
  },
57
58
  "_generatedBy": "dnt@dev"
58
59
  }
package/script/mod.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from "./src/base.js";
2
2
  export * from "./src/transports/base.js";
3
- export type { AbstractEthersSigner, AbstractEthersV5Signer, AbstractViemWalletClient, AbstractWindowEthereum, } from "./src/signing.js";
3
+ export type { AbstractEthersSigner, AbstractEthersV5Signer, AbstractViemWalletClient, AbstractWindowEthereum, } from "./src/signing/mod.js";
4
4
  export * from "./src/clients/exchange.js";
5
5
  export * from "./src/clients/info.js";
6
6
  export * from "./src/clients/multiSign.js";
@@ -1 +1 @@
1
- {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AACA,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC;AAGzC,YAAY,EACR,oBAAoB,EACpB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,GACzB,MAAM,kBAAkB,CAAC;AAG1B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,+BAA+B,CAAC;AAG9C,cAAc,yCAAyC,CAAC;AACxD,cAAc,mDAAmD,CAAC;AAGlE,mBAAmB,mCAAmC,CAAC;AACvD,mBAAmB,mCAAmC,CAAC;AACvD,mBAAmB,8BAA8B,CAAC;AAClD,mBAAmB,4BAA4B,CAAC;AAChD,mBAAmB,iCAAiC,CAAC;AACrD,mBAAmB,6BAA6B,CAAC;AACjD,mBAAmB,4BAA4B,CAAC;AAChD,mBAAmB,4BAA4B,CAAC;AAChD,mBAAmB,wCAAwC,CAAC"}
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AACA,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC;AAGzC,YAAY,EACR,oBAAoB,EACpB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,GACzB,MAAM,sBAAsB,CAAC;AAG9B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,+BAA+B,CAAC;AAG9C,cAAc,yCAAyC,CAAC;AACxD,cAAc,mDAAmD,CAAC;AAGlE,mBAAmB,mCAAmC,CAAC;AACvD,mBAAmB,mCAAmC,CAAC;AACvD,mBAAmB,8BAA8B,CAAC;AAClD,mBAAmB,4BAA4B,CAAC;AAChD,mBAAmB,iCAAiC,CAAC;AACrD,mBAAmB,6BAA6B,CAAC;AACjD,mBAAmB,4BAA4B,CAAC;AAChD,mBAAmB,4BAA4B,CAAC;AAChD,mBAAmB,wCAAwC,CAAC"}