@continuumdao/ctm-mpc-defi 0.2.48 → 0.2.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/catalog.cjs +1083 -4
- package/dist/agent/catalog.cjs.map +1 -1
- package/dist/agent/catalog.d.ts +1191 -7
- package/dist/agent/catalog.js +1047 -5
- package/dist/agent/catalog.js.map +1 -1
- package/dist/agent/skills/derive/SKILL.md +112 -0
- package/dist/agent/skills/hyperliquid/SKILL.md +22 -2
- package/dist/chains/evm/index.d.ts +118 -6
- package/dist/chains/near/index.d.ts +7 -1
- package/dist/chains/solana/index.d.ts +7 -1
- package/dist/core/index.cjs +2 -1
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.ts +138 -7
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +848 -16
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/protocols/evm/aave-v4/index.d.ts +600 -6
- package/dist/protocols/evm/aerodrome/index.cjs.map +1 -1
- package/dist/protocols/evm/aerodrome/index.d.ts +125 -5
- package/dist/protocols/evm/aerodrome/index.js.map +1 -1
- package/dist/protocols/evm/arcus/index.d.ts +66 -2
- package/dist/protocols/evm/circle-cctp/index.d.ts +71 -2
- package/dist/protocols/evm/compound-v3/index.d.ts +52 -1
- package/dist/protocols/evm/continuum-dao/index.d.ts +56 -1
- package/dist/protocols/evm/curve-dao/index.d.ts +66 -2
- package/dist/protocols/evm/derive/index.cjs +2655 -0
- package/dist/protocols/evm/derive/index.cjs.map +1 -0
- package/dist/protocols/evm/derive/index.d.ts +859 -0
- package/dist/protocols/evm/derive/index.js +2536 -0
- package/dist/protocols/evm/derive/index.js.map +1 -0
- package/dist/protocols/evm/ethena/index.d.ts +52 -1
- package/dist/protocols/evm/euler-v2/index.d.ts +115 -16
- package/dist/protocols/evm/gmx/index.d.ts +66 -2
- package/dist/protocols/evm/hyperliquid/index.cjs +545 -267
- package/dist/protocols/evm/hyperliquid/index.cjs.map +1 -1
- package/dist/protocols/evm/hyperliquid/index.d.ts +152 -7
- package/dist/protocols/evm/hyperliquid/index.js +535 -269
- package/dist/protocols/evm/hyperliquid/index.js.map +1 -1
- package/dist/protocols/evm/lido/index.d.ts +52 -1
- package/dist/protocols/evm/maple/index.d.ts +52 -1
- package/dist/protocols/evm/morpho/index.d.ts +115 -4
- package/dist/protocols/evm/pendle/index.cjs +2 -1
- package/dist/protocols/evm/pendle/index.cjs.map +1 -1
- package/dist/protocols/evm/pendle/index.d.ts +125 -5
- package/dist/protocols/evm/pendle/index.js +2 -1
- package/dist/protocols/evm/pendle/index.js.map +1 -1
- package/dist/protocols/evm/permit2/index.d.ts +14 -1
- package/dist/protocols/evm/sky/index.d.ts +52 -1
- package/dist/protocols/evm/uniswap-v4/index.d.ts +78 -4
- package/dist/protocols/evm/venice/index.d.ts +52 -1
- package/package.json +7 -2
- package/dist/buildBatch-tsEUVn_a.d.ts +0 -45
- package/dist/eip712Multisign-6oNIlObj.d.ts +0 -39
- package/dist/envelope-Cm-llShH.d.ts +0 -37
- package/dist/merklDistributor-CdqtZC9N.d.ts +0 -65
- package/dist/multisign-Dr0j9fHm.d.ts +0 -489
- package/dist/registry-BvsXh0-r.d.ts +0 -8
- package/dist/types-RJpoU4Pc.d.ts +0 -34
- package/dist/types-lIfv59N1.d.ts +0 -63
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var msgpack = require('@msgpack/msgpack');
|
|
3
4
|
var viem = require('viem');
|
|
4
5
|
var continuumNodeSdk = require('@continuumdao/continuum-node-sdk');
|
|
5
|
-
var msgpack = require('@msgpack/msgpack');
|
|
6
6
|
|
|
7
7
|
// src/core/registry.ts
|
|
8
8
|
var modules = [];
|
|
@@ -65,6 +65,340 @@ var HYPERLIQUID_MAX_CANDLE_LIMIT = 200;
|
|
|
65
65
|
var HYPERLIQUID_MAX_OHLCV_BARS = 2e3;
|
|
66
66
|
var HYPERLIQUID_DEFAULT_LOOKBACK_DAYS = 14;
|
|
67
67
|
var HYPERLIQUID_MAX_LOOKBACK_DAYS = 90;
|
|
68
|
+
var EXCHANGE_DOMAIN = {
|
|
69
|
+
name: "Exchange",
|
|
70
|
+
version: "1",
|
|
71
|
+
chainId: 1337,
|
|
72
|
+
verifyingContract: "0x0000000000000000000000000000000000000000"
|
|
73
|
+
};
|
|
74
|
+
var AGENT_TYPES = {
|
|
75
|
+
Agent: [
|
|
76
|
+
{ name: "source", type: "string" },
|
|
77
|
+
{ name: "connectionId", type: "bytes32" }
|
|
78
|
+
]
|
|
79
|
+
};
|
|
80
|
+
function adjustMsgpackValue(value) {
|
|
81
|
+
if (Array.isArray(value)) return value.map(adjustMsgpackValue);
|
|
82
|
+
if (typeof value === "object" && value !== null) {
|
|
83
|
+
const result = {};
|
|
84
|
+
for (const key of Object.keys(value)) {
|
|
85
|
+
const entry = value[key];
|
|
86
|
+
if (entry !== void 0) result[key] = adjustMsgpackValue(entry);
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
if (typeof value === "number" && Number.isInteger(value) && (value >= 4294967296 || value < -2147483648)) {
|
|
91
|
+
return BigInt(value);
|
|
92
|
+
}
|
|
93
|
+
return value;
|
|
94
|
+
}
|
|
95
|
+
function toUint64Bytes(n) {
|
|
96
|
+
const bytes = new Uint8Array(8);
|
|
97
|
+
new DataView(bytes.buffer).setBigUint64(0, BigInt(n));
|
|
98
|
+
return bytes;
|
|
99
|
+
}
|
|
100
|
+
function concatBytes(...parts) {
|
|
101
|
+
const total = parts.reduce((sum, p) => sum + p.length, 0);
|
|
102
|
+
const out = new Uint8Array(total);
|
|
103
|
+
let offset = 0;
|
|
104
|
+
for (const p of parts) {
|
|
105
|
+
out.set(p, offset);
|
|
106
|
+
offset += p.length;
|
|
107
|
+
}
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
function hexToBytes(hex) {
|
|
111
|
+
const h = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
112
|
+
const bytes = new Uint8Array(h.length / 2);
|
|
113
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
114
|
+
bytes[i] = parseInt(h.slice(i * 2, i * 2 + 2), 16);
|
|
115
|
+
}
|
|
116
|
+
return bytes;
|
|
117
|
+
}
|
|
118
|
+
function createHyperliquidL1ActionHash(args) {
|
|
119
|
+
const { action, nonce, vaultAddress, expiresAfter } = args;
|
|
120
|
+
const actionBytes = msgpack.encode(adjustMsgpackValue(action));
|
|
121
|
+
const nonceBytes = toUint64Bytes(nonce);
|
|
122
|
+
const vaultMarker = vaultAddress ? new Uint8Array([1]) : new Uint8Array([0]);
|
|
123
|
+
const vaultBytes = vaultAddress ? hexToBytes(vaultAddress) : new Uint8Array();
|
|
124
|
+
const expiresMarker = expiresAfter !== void 0 ? new Uint8Array([0]) : new Uint8Array();
|
|
125
|
+
const expiresBytes = expiresAfter !== void 0 ? toUint64Bytes(expiresAfter) : new Uint8Array();
|
|
126
|
+
const bytes = concatBytes(actionBytes, nonceBytes, vaultMarker, vaultBytes, expiresMarker, expiresBytes);
|
|
127
|
+
return viem.keccak256(bytes);
|
|
128
|
+
}
|
|
129
|
+
function buildHyperliquidAgentTypedData(args) {
|
|
130
|
+
const connectionId = createHyperliquidL1ActionHash(args);
|
|
131
|
+
const source = args.isTestnet ? "b" : "a";
|
|
132
|
+
return {
|
|
133
|
+
domain: EXCHANGE_DOMAIN,
|
|
134
|
+
types: AGENT_TYPES,
|
|
135
|
+
primaryType: "Agent",
|
|
136
|
+
message: {
|
|
137
|
+
source,
|
|
138
|
+
connectionId
|
|
139
|
+
},
|
|
140
|
+
connectionId,
|
|
141
|
+
nonce: args.nonce,
|
|
142
|
+
action: args.action
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function buildHyperliquidUpdateLeverageAction(args) {
|
|
146
|
+
const leverage = Math.trunc(args.leverage);
|
|
147
|
+
if (!Number.isFinite(leverage) || leverage < 1) {
|
|
148
|
+
throw new Error("leverage must be a positive integer");
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
type: "updateLeverage",
|
|
152
|
+
asset: args.asset,
|
|
153
|
+
isCross: args.isCross !== false,
|
|
154
|
+
leverage
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function parseHyperliquidBorrowLendAmount(amountHuman) {
|
|
158
|
+
if (amountHuman == null) return null;
|
|
159
|
+
const trimmed = String(amountHuman).trim();
|
|
160
|
+
if (!trimmed || trimmed.toLowerCase() === "max") return null;
|
|
161
|
+
return hyperliquidFloatToWire(trimmed);
|
|
162
|
+
}
|
|
163
|
+
function buildHyperliquidBorrowLendAction(args) {
|
|
164
|
+
const operation = args.operation;
|
|
165
|
+
if (operation !== "supply" && operation !== "withdraw" && operation !== "repay" && operation !== "borrow") {
|
|
166
|
+
throw new Error("operation must be supply, withdraw, repay, or borrow");
|
|
167
|
+
}
|
|
168
|
+
const token = Math.trunc(args.token);
|
|
169
|
+
if (!Number.isFinite(token) || token < 0) {
|
|
170
|
+
throw new Error("token must be a non-negative integer token index");
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
type: "borrowLend",
|
|
174
|
+
operation,
|
|
175
|
+
token,
|
|
176
|
+
amount: args.amount
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function hyperliquidFloatToWire(value) {
|
|
180
|
+
const n = typeof value === "number" ? value : Number.parseFloat(String(value).trim());
|
|
181
|
+
if (!Number.isFinite(n)) throw new Error("Invalid Hyperliquid wire number.");
|
|
182
|
+
const rounded = n.toFixed(8);
|
|
183
|
+
if (Math.abs(Number.parseFloat(rounded) - n) >= 1e-12) {
|
|
184
|
+
throw new Error(`Hyperliquid wire value ${value} has too many decimal places.`);
|
|
185
|
+
}
|
|
186
|
+
const normalized = Number(rounded === "-0" ? "0" : rounded);
|
|
187
|
+
return String(normalized);
|
|
188
|
+
}
|
|
189
|
+
function hyperliquidL1TifFromKey(tif) {
|
|
190
|
+
const key = String(tif ?? "gtc").trim().toLowerCase();
|
|
191
|
+
if (key === "alo") return "Alo";
|
|
192
|
+
if (key === "ioc") return "Ioc";
|
|
193
|
+
if (key === "gtc") return "Gtc";
|
|
194
|
+
throw new Error(`Unknown time-in-force: ${tif}. Use alo, gtc, or ioc.`);
|
|
195
|
+
}
|
|
196
|
+
function buildHyperliquidLimitOrderWire(args) {
|
|
197
|
+
return {
|
|
198
|
+
a: args.asset,
|
|
199
|
+
b: args.isBuy,
|
|
200
|
+
p: hyperliquidFloatToWire(args.limitPxHuman),
|
|
201
|
+
s: hyperliquidFloatToWire(args.szHuman),
|
|
202
|
+
r: Boolean(args.reduceOnly),
|
|
203
|
+
t: { limit: { tif: hyperliquidL1TifFromKey(args.tif) } }
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function buildHyperliquidTriggerOrderWire(args) {
|
|
207
|
+
const mode = args.tpslExecMode ?? "limit_at_trigger";
|
|
208
|
+
const triggerPx = hyperliquidFloatToWire(args.triggerPxHuman);
|
|
209
|
+
const limitPx = mode === "market" ? triggerPx : hyperliquidFloatToWire(args.limitPxHuman ?? args.triggerPxHuman);
|
|
210
|
+
return {
|
|
211
|
+
a: args.asset,
|
|
212
|
+
b: args.isBuy,
|
|
213
|
+
p: limitPx,
|
|
214
|
+
s: hyperliquidFloatToWire(args.szHuman),
|
|
215
|
+
r: true,
|
|
216
|
+
t: {
|
|
217
|
+
trigger: {
|
|
218
|
+
isMarket: mode === "market",
|
|
219
|
+
triggerPx,
|
|
220
|
+
tpsl: args.tpsl
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function validateHyperliquidTpslGeometry(args) {
|
|
226
|
+
const entry = Number.parseFloat(String(args.entryPxHuman).trim());
|
|
227
|
+
const tp = args.takeProfitTriggerPxHuman?.trim() != null && args.takeProfitTriggerPxHuman.trim() !== "" ? Number.parseFloat(args.takeProfitTriggerPxHuman.trim()) : null;
|
|
228
|
+
const sl = args.stopLossTriggerPxHuman?.trim() != null && args.stopLossTriggerPxHuman.trim() !== "" ? Number.parseFloat(args.stopLossTriggerPxHuman.trim()) : null;
|
|
229
|
+
if (!Number.isFinite(entry)) throw new Error("Invalid entry limit price for TP/SL validation.");
|
|
230
|
+
if (tp != null && !Number.isFinite(tp)) throw new Error("Invalid take-profit trigger price.");
|
|
231
|
+
if (sl != null && !Number.isFinite(sl)) throw new Error("Invalid stop-loss trigger price.");
|
|
232
|
+
if (args.isBuy) {
|
|
233
|
+
if (sl != null && sl >= entry) {
|
|
234
|
+
throw new Error("Long stop-loss must be below entry price.");
|
|
235
|
+
}
|
|
236
|
+
if (tp != null && tp <= entry) {
|
|
237
|
+
throw new Error("Long take-profit must be above entry price.");
|
|
238
|
+
}
|
|
239
|
+
} else {
|
|
240
|
+
if (sl != null && sl <= entry) {
|
|
241
|
+
throw new Error("Short stop-loss must be above entry price.");
|
|
242
|
+
}
|
|
243
|
+
if (tp != null && tp >= entry) {
|
|
244
|
+
throw new Error("Short take-profit must be below entry price.");
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function buildHyperliquidNormalTpslOrderWires(args) {
|
|
249
|
+
validateHyperliquidTpslGeometry({
|
|
250
|
+
isBuy: args.isBuy,
|
|
251
|
+
entryPxHuman: args.limitPxHuman,
|
|
252
|
+
takeProfitTriggerPxHuman: args.takeProfitTriggerPxHuman,
|
|
253
|
+
stopLossTriggerPxHuman: args.stopLossTriggerPxHuman
|
|
254
|
+
});
|
|
255
|
+
const orders = [
|
|
256
|
+
buildHyperliquidLimitOrderWire({
|
|
257
|
+
asset: args.asset,
|
|
258
|
+
isBuy: args.isBuy,
|
|
259
|
+
limitPxHuman: args.limitPxHuman,
|
|
260
|
+
szHuman: args.szHuman,
|
|
261
|
+
tif: args.tif
|
|
262
|
+
})
|
|
263
|
+
];
|
|
264
|
+
const closeIsBuy = !args.isBuy;
|
|
265
|
+
const tp = args.takeProfitTriggerPxHuman?.trim();
|
|
266
|
+
const sl = args.stopLossTriggerPxHuman?.trim();
|
|
267
|
+
if (tp) {
|
|
268
|
+
orders.push(
|
|
269
|
+
buildHyperliquidTriggerOrderWire({
|
|
270
|
+
asset: args.asset,
|
|
271
|
+
isBuy: closeIsBuy,
|
|
272
|
+
szHuman: args.szHuman,
|
|
273
|
+
triggerPxHuman: tp,
|
|
274
|
+
tpsl: "tp",
|
|
275
|
+
tpslExecMode: args.tpslExecMode
|
|
276
|
+
})
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
if (sl) {
|
|
280
|
+
orders.push(
|
|
281
|
+
buildHyperliquidTriggerOrderWire({
|
|
282
|
+
asset: args.asset,
|
|
283
|
+
isBuy: closeIsBuy,
|
|
284
|
+
szHuman: args.szHuman,
|
|
285
|
+
triggerPxHuman: sl,
|
|
286
|
+
tpsl: "sl",
|
|
287
|
+
tpslExecMode: args.tpslExecMode
|
|
288
|
+
})
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
return orders;
|
|
292
|
+
}
|
|
293
|
+
function buildHyperliquidOrderAction(args) {
|
|
294
|
+
return {
|
|
295
|
+
type: "order",
|
|
296
|
+
orders: args.orders,
|
|
297
|
+
grouping: args.grouping ?? "na"
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
var TRAILING_PCT_DECIMALS = 4;
|
|
301
|
+
function parseHyperliquidTrailingOffsetType(value) {
|
|
302
|
+
const key = String(value ?? "percentage").trim().toLowerCase();
|
|
303
|
+
if (key === "price" || key === "px" || key === "distance") return "price";
|
|
304
|
+
if (key === "percentage" || key === "percent" || key === "pct" || key === "%") return "percentage";
|
|
305
|
+
throw new Error("trailingOffsetType must be price or percentage.");
|
|
306
|
+
}
|
|
307
|
+
function hyperliquidTrailingPercentToWire(value) {
|
|
308
|
+
const raw = typeof value === "number" ? String(value) : String(value).trim();
|
|
309
|
+
const stripped = raw.endsWith("%") ? raw.slice(0, -1).trim() : raw;
|
|
310
|
+
const n = Number.parseFloat(stripped);
|
|
311
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
312
|
+
throw new Error("Trailing retracement percentage must be greater than zero.");
|
|
313
|
+
}
|
|
314
|
+
return `${n.toFixed(TRAILING_PCT_DECIMALS)}%`;
|
|
315
|
+
}
|
|
316
|
+
function buildHyperliquidTrailingRetracement(args) {
|
|
317
|
+
const offset = String(args.offsetHuman ?? "").trim();
|
|
318
|
+
if (!offset) throw new Error("trailingOffsetHuman is required.");
|
|
319
|
+
if (args.offsetType === "percentage") {
|
|
320
|
+
return { pct: hyperliquidTrailingPercentToWire(offset) };
|
|
321
|
+
}
|
|
322
|
+
const px = hyperliquidFloatToWire(offset);
|
|
323
|
+
if (Number.parseFloat(px) <= 0) {
|
|
324
|
+
throw new Error("Trailing retracement distance must be greater than zero.");
|
|
325
|
+
}
|
|
326
|
+
return { px };
|
|
327
|
+
}
|
|
328
|
+
var HYPERLIQUID_TRAILING_ACTIVATION_PX_ERROR = "Invalid trailing activation price.";
|
|
329
|
+
var POSITIVE_DECIMAL_RE = /^\d+(\.\d+)?$/;
|
|
330
|
+
function parseHyperliquidTrailingActivationPx(value) {
|
|
331
|
+
if (value == null) return null;
|
|
332
|
+
const raw = String(value).trim().replace(/,/g, "");
|
|
333
|
+
if (!raw) return null;
|
|
334
|
+
if (!POSITIVE_DECIMAL_RE.test(raw)) {
|
|
335
|
+
throw new Error(HYPERLIQUID_TRAILING_ACTIVATION_PX_ERROR);
|
|
336
|
+
}
|
|
337
|
+
const px = Number.parseFloat(raw);
|
|
338
|
+
if (!Number.isFinite(px) || px <= 0) {
|
|
339
|
+
throw new Error(HYPERLIQUID_TRAILING_ACTIVATION_PX_ERROR);
|
|
340
|
+
}
|
|
341
|
+
hyperliquidFloatToWire(raw);
|
|
342
|
+
return raw;
|
|
343
|
+
}
|
|
344
|
+
function isHyperliquidTrailingActivationPxHuman(value) {
|
|
345
|
+
try {
|
|
346
|
+
parseHyperliquidTrailingActivationPx(value);
|
|
347
|
+
return true;
|
|
348
|
+
} catch {
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
function validateHyperliquidTrailingStopParams(args) {
|
|
353
|
+
buildHyperliquidTrailingRetracement({
|
|
354
|
+
offsetType: args.offsetType,
|
|
355
|
+
offsetHuman: args.offsetHuman
|
|
356
|
+
});
|
|
357
|
+
parseHyperliquidTrailingActivationPx(args.activationPxHuman);
|
|
358
|
+
}
|
|
359
|
+
function parseHyperliquidTrailingStopParams(args) {
|
|
360
|
+
const offset = args.trailingOffsetHuman?.trim();
|
|
361
|
+
if (!offset) return null;
|
|
362
|
+
const params = {
|
|
363
|
+
offsetType: parseHyperliquidTrailingOffsetType(args.trailingOffsetType),
|
|
364
|
+
offsetHuman: offset,
|
|
365
|
+
activationPxHuman: args.trailingActivationPxHuman?.trim() || void 0
|
|
366
|
+
};
|
|
367
|
+
validateHyperliquidTrailingStopParams(params);
|
|
368
|
+
return params;
|
|
369
|
+
}
|
|
370
|
+
function buildHyperliquidTrailingStopAction(args) {
|
|
371
|
+
const asset = Math.trunc(args.asset);
|
|
372
|
+
if (!Number.isFinite(asset) || asset < 0) {
|
|
373
|
+
throw new Error("asset must be a non-negative integer.");
|
|
374
|
+
}
|
|
375
|
+
const retracement = buildHyperliquidTrailingRetracement({
|
|
376
|
+
offsetType: args.offsetType,
|
|
377
|
+
offsetHuman: args.offsetHuman
|
|
378
|
+
});
|
|
379
|
+
const activation = parseHyperliquidTrailingActivationPx(args.activationPxHuman);
|
|
380
|
+
return {
|
|
381
|
+
type: "trailingStop",
|
|
382
|
+
asset,
|
|
383
|
+
isBuy: Boolean(args.isBuy),
|
|
384
|
+
sz: hyperliquidFloatToWire(args.szHuman),
|
|
385
|
+
reduceOnly: Boolean(args.reduceOnly),
|
|
386
|
+
retracement,
|
|
387
|
+
activationPx: activation ? hyperliquidFloatToWire(activation) : null
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
function parseHyperliquidTrailingTriggerCondition(triggerCondition) {
|
|
391
|
+
const text = String(triggerCondition ?? "").trim();
|
|
392
|
+
if (!text) return null;
|
|
393
|
+
const retracement = text.match(/(?:^|,\s*)retracement\s+([^,]+)/i)?.[1]?.trim();
|
|
394
|
+
if (!retracement) return null;
|
|
395
|
+
const activationRaw = text.match(/(?:^|,\s*)activation\s+(?:above|below)\s+([^,]+)/i)?.[1]?.trim();
|
|
396
|
+
const bestMatch = text.match(/(?:^|,\s*)best\s+([^,]+)/i);
|
|
397
|
+
const bestRaw = bestMatch?.[1]?.trim();
|
|
398
|
+
const bestPx = bestRaw && bestRaw.toLowerCase() !== "waiting" && Number.isFinite(Number.parseFloat(bestRaw)) ? bestRaw : null;
|
|
399
|
+
const activationPx = activationRaw && Number.isFinite(Number.parseFloat(activationRaw)) ? activationRaw : null;
|
|
400
|
+
return { retracement, activationPx, bestPx };
|
|
401
|
+
}
|
|
68
402
|
|
|
69
403
|
// src/protocols/evm/hyperliquid/api.ts
|
|
70
404
|
async function hyperliquidInfoPost(chainId, body) {
|
|
@@ -343,6 +677,12 @@ async function hyperliquidFetchActiveAssetData(args) {
|
|
|
343
677
|
}
|
|
344
678
|
};
|
|
345
679
|
}
|
|
680
|
+
function enrichHyperliquidFrontendOpenOrder(order) {
|
|
681
|
+
const parsed = order.trailingStop ?? parseHyperliquidTrailingTriggerCondition(order.triggerCondition);
|
|
682
|
+
const looksTrailing = parsed != null || String(order.orderType ?? "").toLowerCase().includes("trailing");
|
|
683
|
+
if (!looksTrailing) return order;
|
|
684
|
+
return { ...order, trailingStop: parsed ?? order.trailingStop ?? null };
|
|
685
|
+
}
|
|
346
686
|
async function hyperliquidFetchOpenOrders(args) {
|
|
347
687
|
const req = { type: "openOrders", user: args.user };
|
|
348
688
|
if (args.dex?.trim()) req.dex = args.dex.trim();
|
|
@@ -353,7 +693,7 @@ async function hyperliquidFetchFrontendOpenOrders(args) {
|
|
|
353
693
|
const req = { type: "frontendOpenOrders", user: args.user };
|
|
354
694
|
if (args.dex?.trim()) req.dex = args.dex.trim();
|
|
355
695
|
const orders = await hyperliquidInfoPost(args.chainId, req);
|
|
356
|
-
return { orders: orders ?? [] };
|
|
696
|
+
return { orders: (orders ?? []).map(enrichHyperliquidFrontendOpenOrder) };
|
|
357
697
|
}
|
|
358
698
|
async function hyperliquidFetchUserVaultEquities(args) {
|
|
359
699
|
const rows = await hyperliquidInfoPost(args.chainId, {
|
|
@@ -822,7 +1162,7 @@ async function hyperliquidFetchPositionDisplayRows(args) {
|
|
|
822
1162
|
return { rows };
|
|
823
1163
|
}
|
|
824
1164
|
async function hyperliquidFetchOrdersForExecutor(args) {
|
|
825
|
-
return
|
|
1165
|
+
return hyperliquidFetchFrontendOpenOrders({
|
|
826
1166
|
chainId: args.chainId,
|
|
827
1167
|
user: args.executorAddress.trim().toLowerCase(),
|
|
828
1168
|
dex: args.dex
|
|
@@ -1507,308 +1847,203 @@ function buildEip712Multisign(args) {
|
|
|
1507
1847
|
legs
|
|
1508
1848
|
});
|
|
1509
1849
|
}
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
Agent: [
|
|
1518
|
-
{ name: "source", type: "string" },
|
|
1519
|
-
{ name: "connectionId", type: "bytes32" }
|
|
1520
|
-
]
|
|
1521
|
-
};
|
|
1522
|
-
function adjustMsgpackValue(value) {
|
|
1523
|
-
if (Array.isArray(value)) return value.map(adjustMsgpackValue);
|
|
1524
|
-
if (typeof value === "object" && value !== null) {
|
|
1525
|
-
const result = {};
|
|
1526
|
-
for (const key of Object.keys(value)) {
|
|
1527
|
-
const entry = value[key];
|
|
1528
|
-
if (entry !== void 0) result[key] = adjustMsgpackValue(entry);
|
|
1529
|
-
}
|
|
1530
|
-
return result;
|
|
1531
|
-
}
|
|
1532
|
-
if (typeof value === "number" && Number.isInteger(value) && (value >= 4294967296 || value < -2147483648)) {
|
|
1533
|
-
return BigInt(value);
|
|
1534
|
-
}
|
|
1535
|
-
return value;
|
|
1536
|
-
}
|
|
1537
|
-
function toUint64Bytes(n) {
|
|
1538
|
-
const bytes = new Uint8Array(8);
|
|
1539
|
-
new DataView(bytes.buffer).setBigUint64(0, BigInt(n));
|
|
1540
|
-
return bytes;
|
|
1541
|
-
}
|
|
1542
|
-
function concatBytes(...parts) {
|
|
1543
|
-
const total = parts.reduce((sum, p) => sum + p.length, 0);
|
|
1544
|
-
const out = new Uint8Array(total);
|
|
1545
|
-
let offset = 0;
|
|
1546
|
-
for (const p of parts) {
|
|
1547
|
-
out.set(p, offset);
|
|
1548
|
-
offset += p.length;
|
|
1549
|
-
}
|
|
1550
|
-
return out;
|
|
1551
|
-
}
|
|
1552
|
-
function hexToBytes(hex) {
|
|
1553
|
-
const h = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
1554
|
-
const bytes = new Uint8Array(h.length / 2);
|
|
1555
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
1556
|
-
bytes[i] = parseInt(h.slice(i * 2, i * 2 + 2), 16);
|
|
1557
|
-
}
|
|
1558
|
-
return bytes;
|
|
1559
|
-
}
|
|
1560
|
-
function createHyperliquidL1ActionHash(args) {
|
|
1561
|
-
const { action, nonce, vaultAddress, expiresAfter } = args;
|
|
1562
|
-
const actionBytes = msgpack.encode(adjustMsgpackValue(action));
|
|
1563
|
-
const nonceBytes = toUint64Bytes(nonce);
|
|
1564
|
-
const vaultMarker = vaultAddress ? new Uint8Array([1]) : new Uint8Array([0]);
|
|
1565
|
-
const vaultBytes = vaultAddress ? hexToBytes(vaultAddress) : new Uint8Array();
|
|
1566
|
-
const expiresMarker = expiresAfter !== void 0 ? new Uint8Array([0]) : new Uint8Array();
|
|
1567
|
-
const expiresBytes = expiresAfter !== void 0 ? toUint64Bytes(expiresAfter) : new Uint8Array();
|
|
1568
|
-
const bytes = concatBytes(actionBytes, nonceBytes, vaultMarker, vaultBytes, expiresMarker, expiresBytes);
|
|
1569
|
-
return viem.keccak256(bytes);
|
|
1570
|
-
}
|
|
1571
|
-
function buildHyperliquidAgentTypedData(args) {
|
|
1572
|
-
const connectionId = createHyperliquidL1ActionHash(args);
|
|
1573
|
-
const source = args.isTestnet ? "b" : "a";
|
|
1574
|
-
return {
|
|
1575
|
-
domain: EXCHANGE_DOMAIN,
|
|
1576
|
-
types: AGENT_TYPES,
|
|
1577
|
-
primaryType: "Agent",
|
|
1578
|
-
message: {
|
|
1579
|
-
source,
|
|
1580
|
-
connectionId
|
|
1581
|
-
},
|
|
1582
|
-
connectionId,
|
|
1850
|
+
|
|
1851
|
+
// src/protocols/evm/hyperliquid/exchangeMultisign.ts
|
|
1852
|
+
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
1853
|
+
function hyperliquidExchangeLeg(args) {
|
|
1854
|
+
const isTestnet = args.chainId === 998;
|
|
1855
|
+
const typed = buildHyperliquidAgentTypedData({
|
|
1856
|
+
action: args.action,
|
|
1583
1857
|
nonce: args.nonce,
|
|
1584
|
-
|
|
1585
|
-
};
|
|
1586
|
-
}
|
|
1587
|
-
function buildHyperliquidUpdateLeverageAction(args) {
|
|
1588
|
-
const leverage = Math.trunc(args.leverage);
|
|
1589
|
-
if (!Number.isFinite(leverage) || leverage < 1) {
|
|
1590
|
-
throw new Error("leverage must be a positive integer");
|
|
1591
|
-
}
|
|
1858
|
+
isTestnet
|
|
1859
|
+
});
|
|
1592
1860
|
return {
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1861
|
+
typedData: {
|
|
1862
|
+
domain: typed.domain,
|
|
1863
|
+
types: typed.types,
|
|
1864
|
+
primaryType: typed.primaryType,
|
|
1865
|
+
message: typed.message
|
|
1866
|
+
},
|
|
1867
|
+
delivery: {
|
|
1868
|
+
kind: "hyperliquid_exchange",
|
|
1869
|
+
chainId: args.chainId,
|
|
1870
|
+
isTestnet,
|
|
1871
|
+
action: args.action,
|
|
1872
|
+
nonce: args.nonce
|
|
1873
|
+
},
|
|
1874
|
+
audit: {
|
|
1875
|
+
...args.audit,
|
|
1876
|
+
nonce: args.nonce,
|
|
1877
|
+
connectionId: typed.connectionId
|
|
1878
|
+
}
|
|
1597
1879
|
};
|
|
1598
1880
|
}
|
|
1599
|
-
function
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1881
|
+
function resolveTrailingForLimit(args) {
|
|
1882
|
+
return parseHyperliquidTrailingStopParams({
|
|
1883
|
+
trailingOffsetHuman: args.trailingOffsetHuman,
|
|
1884
|
+
trailingOffsetType: args.trailingOffsetType,
|
|
1885
|
+
trailingActivationPxHuman: args.trailingActivationPxHuman
|
|
1886
|
+
});
|
|
1604
1887
|
}
|
|
1605
|
-
function
|
|
1606
|
-
const
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
throw new Error("token must be a non-negative integer token index");
|
|
1888
|
+
async function buildHyperliquidLimitOrderWithTpslMultisign(args) {
|
|
1889
|
+
const marketKind = args.marketKind ?? "perp";
|
|
1890
|
+
const trailing = resolveTrailingForLimit(args);
|
|
1891
|
+
const tp = args.takeProfitTriggerPxHuman?.trim();
|
|
1892
|
+
const sl = args.stopLossTriggerPxHuman?.trim();
|
|
1893
|
+
if (trailing && sl) {
|
|
1894
|
+
throw new Error("Cannot combine a trailing stop with a fixed stopLossTriggerPxHuman.");
|
|
1613
1895
|
}
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
amount: args.amount
|
|
1619
|
-
};
|
|
1620
|
-
}
|
|
1621
|
-
function hyperliquidFloatToWire(value) {
|
|
1622
|
-
const n = typeof value === "number" ? value : Number.parseFloat(String(value).trim());
|
|
1623
|
-
if (!Number.isFinite(n)) throw new Error("Invalid Hyperliquid wire number.");
|
|
1624
|
-
const rounded = n.toFixed(8);
|
|
1625
|
-
if (Math.abs(Number.parseFloat(rounded) - n) >= 1e-12) {
|
|
1626
|
-
throw new Error(`Hyperliquid wire value ${value} has too many decimal places.`);
|
|
1896
|
+
if (!tp && !sl && !trailing) {
|
|
1897
|
+
throw new Error(
|
|
1898
|
+
"At least one of takeProfitTriggerPxHuman, stopLossTriggerPxHuman, or trailingOffsetHuman is required for L1 bracket orders."
|
|
1899
|
+
);
|
|
1627
1900
|
}
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
}
|
|
1631
|
-
function hyperliquidL1TifFromKey(tif) {
|
|
1632
|
-
const key = String(tif ?? "gtc").trim().toLowerCase();
|
|
1633
|
-
if (key === "alo") return "Alo";
|
|
1634
|
-
if (key === "ioc") return "Ioc";
|
|
1635
|
-
if (key === "gtc") return "Gtc";
|
|
1636
|
-
throw new Error(`Unknown time-in-force: ${tif}. Use alo, gtc, or ioc.`);
|
|
1637
|
-
}
|
|
1638
|
-
function buildHyperliquidLimitOrderWire(args) {
|
|
1639
|
-
return {
|
|
1640
|
-
a: args.asset,
|
|
1641
|
-
b: args.isBuy,
|
|
1642
|
-
p: hyperliquidFloatToWire(args.limitPxHuman),
|
|
1643
|
-
s: hyperliquidFloatToWire(args.szHuman),
|
|
1644
|
-
r: Boolean(args.reduceOnly),
|
|
1645
|
-
t: { limit: { tif: hyperliquidL1TifFromKey(args.tif) } }
|
|
1646
|
-
};
|
|
1647
|
-
}
|
|
1648
|
-
function buildHyperliquidTriggerOrderWire(args) {
|
|
1649
|
-
const mode = args.tpslExecMode ?? "limit_at_trigger";
|
|
1650
|
-
const triggerPx = hyperliquidFloatToWire(args.triggerPxHuman);
|
|
1651
|
-
const limitPx = mode === "market" ? triggerPx : hyperliquidFloatToWire(args.limitPxHuman ?? args.triggerPxHuman);
|
|
1652
|
-
return {
|
|
1653
|
-
a: args.asset,
|
|
1654
|
-
b: args.isBuy,
|
|
1655
|
-
p: limitPx,
|
|
1656
|
-
s: hyperliquidFloatToWire(args.szHuman),
|
|
1657
|
-
r: true,
|
|
1658
|
-
t: {
|
|
1659
|
-
trigger: {
|
|
1660
|
-
isMarket: mode === "market",
|
|
1661
|
-
triggerPx,
|
|
1662
|
-
tpsl: args.tpsl
|
|
1663
|
-
}
|
|
1664
|
-
}
|
|
1665
|
-
};
|
|
1666
|
-
}
|
|
1667
|
-
function validateHyperliquidTpslGeometry(args) {
|
|
1668
|
-
const entry = Number.parseFloat(String(args.entryPxHuman).trim());
|
|
1669
|
-
const tp = args.takeProfitTriggerPxHuman?.trim() != null && args.takeProfitTriggerPxHuman.trim() !== "" ? Number.parseFloat(args.takeProfitTriggerPxHuman.trim()) : null;
|
|
1670
|
-
const sl = args.stopLossTriggerPxHuman?.trim() != null && args.stopLossTriggerPxHuman.trim() !== "" ? Number.parseFloat(args.stopLossTriggerPxHuman.trim()) : null;
|
|
1671
|
-
if (!Number.isFinite(entry)) throw new Error("Invalid entry limit price for TP/SL validation.");
|
|
1672
|
-
if (tp != null && !Number.isFinite(tp)) throw new Error("Invalid take-profit trigger price.");
|
|
1673
|
-
if (sl != null && !Number.isFinite(sl)) throw new Error("Invalid stop-loss trigger price.");
|
|
1674
|
-
if (args.isBuy) {
|
|
1675
|
-
if (sl != null && sl >= entry) {
|
|
1676
|
-
throw new Error("Long stop-loss must be below entry price.");
|
|
1677
|
-
}
|
|
1678
|
-
if (tp != null && tp <= entry) {
|
|
1679
|
-
throw new Error("Long take-profit must be above entry price.");
|
|
1680
|
-
}
|
|
1681
|
-
} else {
|
|
1682
|
-
if (sl != null && sl <= entry) {
|
|
1683
|
-
throw new Error("Short stop-loss must be above entry price.");
|
|
1684
|
-
}
|
|
1685
|
-
if (tp != null && tp >= entry) {
|
|
1686
|
-
throw new Error("Short take-profit must be below entry price.");
|
|
1687
|
-
}
|
|
1901
|
+
if (trailing && marketKind !== "perp") {
|
|
1902
|
+
throw new Error("Trailing stops are available for perp markets only.");
|
|
1688
1903
|
}
|
|
1689
|
-
}
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
takeProfitTriggerPxHuman: args.takeProfitTriggerPxHuman,
|
|
1695
|
-
stopLossTriggerPxHuman: args.stopLossTriggerPxHuman
|
|
1904
|
+
const { asset } = await hyperliquidResolveAsset({
|
|
1905
|
+
chainId: args.chainId,
|
|
1906
|
+
coin: args.coin,
|
|
1907
|
+
marketKind,
|
|
1908
|
+
dex: args.dex
|
|
1696
1909
|
});
|
|
1697
|
-
const
|
|
1910
|
+
const hasFixedTpsl = Boolean(tp || sl);
|
|
1911
|
+
const orderWires = hasFixedTpsl ? buildHyperliquidNormalTpslOrderWires({
|
|
1912
|
+
asset,
|
|
1913
|
+
isBuy: args.isBuy,
|
|
1914
|
+
limitPxHuman: args.limitPxHuman,
|
|
1915
|
+
szHuman: args.szHuman,
|
|
1916
|
+
tif: args.tif,
|
|
1917
|
+
takeProfitTriggerPxHuman: tp || void 0,
|
|
1918
|
+
stopLossTriggerPxHuman: sl || void 0,
|
|
1919
|
+
tpslExecMode: args.tpslExecMode
|
|
1920
|
+
}) : [
|
|
1698
1921
|
buildHyperliquidLimitOrderWire({
|
|
1699
|
-
asset
|
|
1922
|
+
asset,
|
|
1700
1923
|
isBuy: args.isBuy,
|
|
1701
1924
|
limitPxHuman: args.limitPxHuman,
|
|
1702
1925
|
szHuman: args.szHuman,
|
|
1703
1926
|
tif: args.tif
|
|
1704
1927
|
})
|
|
1705
1928
|
];
|
|
1706
|
-
const
|
|
1707
|
-
const
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
isBuy: closeIsBuy,
|
|
1929
|
+
const grouping = hasFixedTpsl ? "normalTpsl" : "na";
|
|
1930
|
+
const orderAction = buildHyperliquidOrderAction({
|
|
1931
|
+
orders: orderWires,
|
|
1932
|
+
grouping
|
|
1933
|
+
});
|
|
1934
|
+
const nonce = args.nonce ?? Date.now();
|
|
1935
|
+
const legs = [
|
|
1936
|
+
hyperliquidExchangeLeg({
|
|
1937
|
+
action: orderAction,
|
|
1938
|
+
nonce,
|
|
1939
|
+
chainId: args.chainId,
|
|
1940
|
+
audit: {
|
|
1941
|
+
protocol: "hyperliquid",
|
|
1942
|
+
action: hasFixedTpsl ? "limitOrderWithTpsl" : "limitOrderWithTrailingStop",
|
|
1943
|
+
coin: args.coin,
|
|
1944
|
+
marketKind,
|
|
1945
|
+
asset,
|
|
1946
|
+
isBuy: args.isBuy,
|
|
1947
|
+
limitPxHuman: args.limitPxHuman,
|
|
1726
1948
|
szHuman: args.szHuman,
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
tpslExecMode: args.tpslExecMode
|
|
1949
|
+
takeProfitTriggerPxHuman: tp ?? null,
|
|
1950
|
+
stopLossTriggerPxHuman: sl ?? null,
|
|
1951
|
+
tpslExecMode: hasFixedTpsl ? args.tpslExecMode ?? "limit_at_trigger" : null,
|
|
1952
|
+
grouping,
|
|
1953
|
+
trailingOffsetHuman: trailing?.offsetHuman ?? null,
|
|
1954
|
+
trailingOffsetType: trailing?.offsetType ?? null,
|
|
1955
|
+
trailingActivationPxHuman: trailing?.activationPxHuman ?? null
|
|
1956
|
+
}
|
|
1957
|
+
})
|
|
1958
|
+
];
|
|
1959
|
+
if (trailing) {
|
|
1960
|
+
const trailingAction = buildHyperliquidTrailingStopAction({
|
|
1961
|
+
asset,
|
|
1962
|
+
isBuy: !args.isBuy,
|
|
1963
|
+
szHuman: args.szHuman,
|
|
1964
|
+
reduceOnly: true,
|
|
1965
|
+
offsetType: trailing.offsetType,
|
|
1966
|
+
offsetHuman: trailing.offsetHuman,
|
|
1967
|
+
activationPxHuman: trailing.activationPxHuman
|
|
1968
|
+
});
|
|
1969
|
+
legs.push(
|
|
1970
|
+
hyperliquidExchangeLeg({
|
|
1971
|
+
action: trailingAction,
|
|
1972
|
+
nonce: nonce + 1,
|
|
1973
|
+
chainId: args.chainId,
|
|
1974
|
+
audit: {
|
|
1975
|
+
protocol: "hyperliquid",
|
|
1976
|
+
action: "trailingStop",
|
|
1977
|
+
coin: args.coin,
|
|
1978
|
+
marketKind,
|
|
1979
|
+
asset,
|
|
1980
|
+
isBuy: trailingAction.isBuy,
|
|
1981
|
+
szHuman: args.szHuman,
|
|
1982
|
+
reduceOnly: true,
|
|
1983
|
+
trailingOffsetHuman: trailing.offsetHuman,
|
|
1984
|
+
trailingOffsetType: trailing.offsetType,
|
|
1985
|
+
trailingActivationPxHuman: trailing.activationPxHuman ?? null
|
|
1986
|
+
}
|
|
1730
1987
|
})
|
|
1731
1988
|
);
|
|
1732
1989
|
}
|
|
1733
|
-
return
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
};
|
|
1990
|
+
return buildEip712Multisign({
|
|
1991
|
+
keyGen: args.keyGen,
|
|
1992
|
+
purposeText: args.purposeText,
|
|
1993
|
+
destinationChainID: String(args.chainId),
|
|
1994
|
+
destinationAddress: ZERO_ADDRESS,
|
|
1995
|
+
legs
|
|
1996
|
+
});
|
|
1741
1997
|
}
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1998
|
+
async function buildHyperliquidTrailingStopMultisign(args) {
|
|
1999
|
+
const trailing = parseHyperliquidTrailingStopParams({
|
|
2000
|
+
trailingOffsetHuman: args.trailingOffsetHuman,
|
|
2001
|
+
trailingOffsetType: args.trailingOffsetType,
|
|
2002
|
+
trailingActivationPxHuman: args.trailingActivationPxHuman
|
|
2003
|
+
});
|
|
2004
|
+
if (!trailing) {
|
|
2005
|
+
throw new Error("trailingOffsetHuman is required for a trailing stop.");
|
|
2006
|
+
}
|
|
1747
2007
|
const { asset } = await hyperliquidResolveAsset({
|
|
1748
2008
|
chainId: args.chainId,
|
|
1749
2009
|
coin: args.coin,
|
|
1750
|
-
marketKind,
|
|
2010
|
+
marketKind: "perp",
|
|
1751
2011
|
dex: args.dex
|
|
1752
2012
|
});
|
|
1753
|
-
const
|
|
1754
|
-
const sl = args.stopLossTriggerPxHuman?.trim();
|
|
1755
|
-
if (!tp && !sl) {
|
|
1756
|
-
throw new Error("At least one of takeProfitTriggerPxHuman or stopLossTriggerPxHuman is required for bracket orders.");
|
|
1757
|
-
}
|
|
1758
|
-
const orderWires = buildHyperliquidNormalTpslOrderWires({
|
|
2013
|
+
const action = buildHyperliquidTrailingStopAction({
|
|
1759
2014
|
asset,
|
|
1760
2015
|
isBuy: args.isBuy,
|
|
1761
|
-
limitPxHuman: args.limitPxHuman,
|
|
1762
2016
|
szHuman: args.szHuman,
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
});
|
|
1768
|
-
const action = buildHyperliquidOrderAction({
|
|
1769
|
-
orders: orderWires,
|
|
1770
|
-
grouping: "normalTpsl"
|
|
2017
|
+
reduceOnly: args.reduceOnly !== false,
|
|
2018
|
+
offsetType: trailing.offsetType,
|
|
2019
|
+
offsetHuman: trailing.offsetHuman,
|
|
2020
|
+
activationPxHuman: trailing.activationPxHuman
|
|
1771
2021
|
});
|
|
1772
2022
|
const nonce = args.nonce ?? Date.now();
|
|
1773
|
-
const isTestnet = args.chainId === 998;
|
|
1774
|
-
const typed = buildHyperliquidAgentTypedData({ action, nonce, isTestnet });
|
|
1775
2023
|
return buildEip712Multisign({
|
|
1776
2024
|
keyGen: args.keyGen,
|
|
1777
2025
|
purposeText: args.purposeText,
|
|
1778
2026
|
destinationChainID: String(args.chainId),
|
|
1779
2027
|
destinationAddress: ZERO_ADDRESS,
|
|
1780
2028
|
legs: [
|
|
1781
|
-
{
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
primaryType: typed.primaryType,
|
|
1786
|
-
message: typed.message
|
|
1787
|
-
},
|
|
1788
|
-
delivery: {
|
|
1789
|
-
kind: "hyperliquid_exchange",
|
|
1790
|
-
chainId: args.chainId,
|
|
1791
|
-
isTestnet,
|
|
1792
|
-
action,
|
|
1793
|
-
nonce
|
|
1794
|
-
},
|
|
2029
|
+
hyperliquidExchangeLeg({
|
|
2030
|
+
action,
|
|
2031
|
+
nonce,
|
|
2032
|
+
chainId: args.chainId,
|
|
1795
2033
|
audit: {
|
|
1796
2034
|
protocol: "hyperliquid",
|
|
1797
|
-
action: "
|
|
2035
|
+
action: "trailingStop",
|
|
1798
2036
|
coin: args.coin,
|
|
1799
|
-
marketKind,
|
|
2037
|
+
marketKind: "perp",
|
|
1800
2038
|
asset,
|
|
1801
|
-
isBuy:
|
|
1802
|
-
limitPxHuman: args.limitPxHuman,
|
|
2039
|
+
isBuy: action.isBuy,
|
|
1803
2040
|
szHuman: args.szHuman,
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
nonce,
|
|
1809
|
-
connectionId: typed.connectionId
|
|
2041
|
+
reduceOnly: action.reduceOnly,
|
|
2042
|
+
trailingOffsetHuman: trailing.offsetHuman,
|
|
2043
|
+
trailingOffsetType: trailing.offsetType,
|
|
2044
|
+
trailingActivationPxHuman: trailing.activationPxHuman ?? null
|
|
1810
2045
|
}
|
|
1811
|
-
}
|
|
2046
|
+
})
|
|
1812
2047
|
]
|
|
1813
2048
|
});
|
|
1814
2049
|
}
|
|
@@ -1917,7 +2152,9 @@ async function buildHyperliquidBorrowLendMultisign(args) {
|
|
|
1917
2152
|
|
|
1918
2153
|
// src/protocols/evm/hyperliquid/multisign.ts
|
|
1919
2154
|
function hasHyperliquidBracketTpsl(args) {
|
|
1920
|
-
return Boolean(
|
|
2155
|
+
return Boolean(
|
|
2156
|
+
args.takeProfitTriggerPxHuman?.trim() || args.stopLossTriggerPxHuman?.trim() || args.trailingOffsetHuman?.trim()
|
|
2157
|
+
);
|
|
1921
2158
|
}
|
|
1922
2159
|
async function buildCoreWriterMultisign(common, data, signatureMeta) {
|
|
1923
2160
|
const step = coreWriterStep(data);
|
|
@@ -1945,7 +2182,14 @@ async function buildCoreWriterMultisign(common, data, signatureMeta) {
|
|
|
1945
2182
|
async function buildEvmMultisignBodyHyperliquidLimitOrderBatch(args) {
|
|
1946
2183
|
if (hasHyperliquidBracketTpsl(args)) {
|
|
1947
2184
|
if (args.reduceOnly) {
|
|
1948
|
-
throw new Error("reduceOnly cannot be combined with takeProfitTriggerPxHuman or
|
|
2185
|
+
throw new Error("reduceOnly cannot be combined with takeProfitTriggerPxHuman, stopLossTriggerPxHuman, or a trailing stop.");
|
|
2186
|
+
}
|
|
2187
|
+
if (args.trailingOffsetHuman?.trim()) {
|
|
2188
|
+
parseHyperliquidTrailingStopParams({
|
|
2189
|
+
trailingOffsetHuman: args.trailingOffsetHuman,
|
|
2190
|
+
trailingOffsetType: args.trailingOffsetType,
|
|
2191
|
+
trailingActivationPxHuman: args.trailingActivationPxHuman
|
|
2192
|
+
});
|
|
1949
2193
|
}
|
|
1950
2194
|
return buildHyperliquidLimitOrderWithTpslMultisign({
|
|
1951
2195
|
keyGen: args.keyGen,
|
|
@@ -1960,7 +2204,10 @@ async function buildEvmMultisignBodyHyperliquidLimitOrderBatch(args) {
|
|
|
1960
2204
|
tif: args.tif,
|
|
1961
2205
|
takeProfitTriggerPxHuman: args.takeProfitTriggerPxHuman,
|
|
1962
2206
|
stopLossTriggerPxHuman: args.stopLossTriggerPxHuman,
|
|
1963
|
-
tpslExecMode: args.tpslExecMode
|
|
2207
|
+
tpslExecMode: args.tpslExecMode,
|
|
2208
|
+
trailingOffsetHuman: args.trailingOffsetHuman,
|
|
2209
|
+
trailingOffsetType: args.trailingOffsetType,
|
|
2210
|
+
trailingActivationPxHuman: args.trailingActivationPxHuman
|
|
1964
2211
|
});
|
|
1965
2212
|
}
|
|
1966
2213
|
const marketKind = args.marketKind ?? "perp";
|
|
@@ -2324,7 +2571,7 @@ function hyperliquidOrderClosesPosition(position, orderSide) {
|
|
|
2324
2571
|
return position.isLong ? side === "A" : side === "B";
|
|
2325
2572
|
}
|
|
2326
2573
|
function hyperliquidOrderCountsAsPendingClose(order) {
|
|
2327
|
-
return Boolean(order.reduceOnly) || Boolean(order.isTrigger);
|
|
2574
|
+
return Boolean(order.reduceOnly) || Boolean(order.isTrigger) || Boolean(order.trailingStop) || String(order.orderType ?? "").toLowerCase().includes("trailing");
|
|
2328
2575
|
}
|
|
2329
2576
|
function hyperliquidPendingCloseForPosition(args) {
|
|
2330
2577
|
const positionSize = parsePositiveSize(args.position.size);
|
|
@@ -2381,7 +2628,26 @@ var hyperliquidProtocolModule = {
|
|
|
2381
2628
|
dex: { type: "string", required: false, description: "HIP-3 dex name when applicable" },
|
|
2382
2629
|
takeProfitTriggerPxHuman: { type: "string", required: false, description: "TP trigger \u2014 enables L1 bracket with SL" },
|
|
2383
2630
|
stopLossTriggerPxHuman: { type: "string", required: false, description: "SL trigger \u2014 enables L1 bracket with TP" },
|
|
2384
|
-
tpslExecMode: { type: "string", required: false, description: "limit_at_trigger (default) or market" }
|
|
2631
|
+
tpslExecMode: { type: "string", required: false, description: "limit_at_trigger (default) or market" },
|
|
2632
|
+
trailingOffsetHuman: { type: "string", required: false, description: "Trailing retracement \u2014 EIP-712 trailingStop (cannot combine with SL)" },
|
|
2633
|
+
trailingOffsetType: { type: "string", required: false, description: "price or percentage" },
|
|
2634
|
+
trailingActivationPxHuman: { type: "string", required: false, description: "Optional activation mark price" }
|
|
2635
|
+
}
|
|
2636
|
+
},
|
|
2637
|
+
{
|
|
2638
|
+
id: "hyperliquid.trailingStop",
|
|
2639
|
+
protocolId: HYPERLIQUID_PROTOCOL_ID,
|
|
2640
|
+
chainCategory: "evm",
|
|
2641
|
+
description: "Place a Hyperliquid perp trailing stop via L1 trailingStop action (EIP-712 /exchange)",
|
|
2642
|
+
commonParams: ["keyGen", "purposeText"],
|
|
2643
|
+
params: {
|
|
2644
|
+
coin: { type: "string", required: true, description: "Perp coin" },
|
|
2645
|
+
isBuy: { type: "boolean", required: true, description: "false closes a long / opens a short" },
|
|
2646
|
+
szHuman: { type: "string", required: true, description: "Size in coin units" },
|
|
2647
|
+
trailingOffsetHuman: { type: "string", required: true, description: "Retracement distance or percent" },
|
|
2648
|
+
trailingOffsetType: { type: "string", required: false, description: "price or percentage (default)" },
|
|
2649
|
+
trailingActivationPxHuman: { type: "string", required: false, description: "Optional activation mark price" },
|
|
2650
|
+
reduceOnly: { type: "boolean", required: false, description: "true (default) reduces a position" }
|
|
2385
2651
|
}
|
|
2386
2652
|
},
|
|
2387
2653
|
{
|
|
@@ -2554,6 +2820,7 @@ exports.HYPERLIQUID_PROTOCOL_ID = HYPERLIQUID_PROTOCOL_ID;
|
|
|
2554
2820
|
exports.HYPERLIQUID_SPOT_ASSET_OFFSET = HYPERLIQUID_SPOT_ASSET_OFFSET;
|
|
2555
2821
|
exports.HYPERLIQUID_SUPPORTED_CHAIN_IDS = HYPERLIQUID_SUPPORTED_CHAIN_IDS;
|
|
2556
2822
|
exports.HYPERLIQUID_TIF = HYPERLIQUID_TIF;
|
|
2823
|
+
exports.HYPERLIQUID_TRAILING_ACTIVATION_PX_ERROR = HYPERLIQUID_TRAILING_ACTIVATION_PX_ERROR;
|
|
2557
2824
|
exports.HYPERLIQUID_USER_SIGNED_DOMAIN = HYPERLIQUID_USER_SIGNED_DOMAIN;
|
|
2558
2825
|
exports.HYPERLIQUID_USER_SIGNED_SIGNATURE_CHAIN_ID = HYPERLIQUID_USER_SIGNED_SIGNATURE_CHAIN_ID;
|
|
2559
2826
|
exports.HYPERLIQUID_WITHDRAW_SIGN_TYPES = HYPERLIQUID_WITHDRAW_SIGN_TYPES;
|
|
@@ -2585,6 +2852,9 @@ exports.buildHyperliquidLimitOrderWire = buildHyperliquidLimitOrderWire;
|
|
|
2585
2852
|
exports.buildHyperliquidLimitOrderWithTpslMultisign = buildHyperliquidLimitOrderWithTpslMultisign;
|
|
2586
2853
|
exports.buildHyperliquidNormalTpslOrderWires = buildHyperliquidNormalTpslOrderWires;
|
|
2587
2854
|
exports.buildHyperliquidOrderAction = buildHyperliquidOrderAction;
|
|
2855
|
+
exports.buildHyperliquidTrailingRetracement = buildHyperliquidTrailingRetracement;
|
|
2856
|
+
exports.buildHyperliquidTrailingStopAction = buildHyperliquidTrailingStopAction;
|
|
2857
|
+
exports.buildHyperliquidTrailingStopMultisign = buildHyperliquidTrailingStopMultisign;
|
|
2588
2858
|
exports.buildHyperliquidTriggerOrderWire = buildHyperliquidTriggerOrderWire;
|
|
2589
2859
|
exports.buildHyperliquidUpdateLeverageAction = buildHyperliquidUpdateLeverageAction;
|
|
2590
2860
|
exports.buildHyperliquidUpdateLeverageMultisign = buildHyperliquidUpdateLeverageMultisign;
|
|
@@ -2592,6 +2862,7 @@ exports.buildHyperliquidWithdraw3Action = buildHyperliquidWithdraw3Action;
|
|
|
2592
2862
|
exports.buildHyperliquidWithdraw3TypedData = buildHyperliquidWithdraw3TypedData;
|
|
2593
2863
|
exports.coreWriterStep = coreWriterStep;
|
|
2594
2864
|
exports.createHyperliquidL1ActionHash = createHyperliquidL1ActionHash;
|
|
2865
|
+
exports.enrichHyperliquidFrontendOpenOrder = enrichHyperliquidFrontendOpenOrder;
|
|
2595
2866
|
exports.hyperliquidApiBaseUrl = hyperliquidApiBaseUrl;
|
|
2596
2867
|
exports.hyperliquidBridgeArbitrumChainId = hyperliquidBridgeArbitrumChainId;
|
|
2597
2868
|
exports.hyperliquidBridgeConfig = hyperliquidBridgeConfig;
|
|
@@ -2666,15 +2937,22 @@ exports.hyperliquidResolveSpotToken = hyperliquidResolveSpotToken;
|
|
|
2666
2937
|
exports.hyperliquidResolveTif = hyperliquidResolveTif;
|
|
2667
2938
|
exports.hyperliquidSearchMarkets = hyperliquidSearchMarkets;
|
|
2668
2939
|
exports.hyperliquidSearchMarketsSummary = hyperliquidSearchMarketsSummary;
|
|
2940
|
+
exports.hyperliquidTrailingPercentToWire = hyperliquidTrailingPercentToWire;
|
|
2669
2941
|
exports.hyperliquidVaultStatsUrl = hyperliquidVaultStatsUrl;
|
|
2670
2942
|
exports.isHyperliquidBridgeArbitrumChainSupported = isHyperliquidBridgeArbitrumChainSupported;
|
|
2671
2943
|
exports.isHyperliquidBridgeArbitrumUsdcRow = isHyperliquidBridgeArbitrumUsdcRow;
|
|
2672
2944
|
exports.isHyperliquidChainSupported = isHyperliquidChainSupported;
|
|
2673
2945
|
exports.isHyperliquidHyperEvmUsdcRow = isHyperliquidHyperEvmUsdcRow;
|
|
2946
|
+
exports.isHyperliquidTrailingActivationPxHuman = isHyperliquidTrailingActivationPxHuman;
|
|
2674
2947
|
exports.mapHyperliquidLendMarketRows = mapHyperliquidLendMarketRows;
|
|
2675
2948
|
exports.parseHyperliquidBorrowLendAmount = parseHyperliquidBorrowLendAmount;
|
|
2676
2949
|
exports.parseHyperliquidBorrowLendReserveTuples = parseHyperliquidBorrowLendReserveTuples;
|
|
2677
2950
|
exports.parseHyperliquidBorrowLendUserState = parseHyperliquidBorrowLendUserState;
|
|
2951
|
+
exports.parseHyperliquidTrailingActivationPx = parseHyperliquidTrailingActivationPx;
|
|
2952
|
+
exports.parseHyperliquidTrailingOffsetType = parseHyperliquidTrailingOffsetType;
|
|
2953
|
+
exports.parseHyperliquidTrailingStopParams = parseHyperliquidTrailingStopParams;
|
|
2954
|
+
exports.parseHyperliquidTrailingTriggerCondition = parseHyperliquidTrailingTriggerCondition;
|
|
2678
2955
|
exports.validateHyperliquidTpslGeometry = validateHyperliquidTpslGeometry;
|
|
2956
|
+
exports.validateHyperliquidTrailingStopParams = validateHyperliquidTrailingStopParams;
|
|
2679
2957
|
//# sourceMappingURL=index.cjs.map
|
|
2680
2958
|
//# sourceMappingURL=index.cjs.map
|