@elizaos/plugin-hyperliquid-app 2.0.3-beta.5 → 2.0.3-beta.7

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 (79) hide show
  1. package/dist/HyperliquidAppView.d.ts +4 -0
  2. package/dist/HyperliquidAppView.d.ts.map +1 -0
  3. package/dist/HyperliquidAppView.interact.d.ts +10 -0
  4. package/dist/HyperliquidAppView.interact.d.ts.map +1 -0
  5. package/dist/HyperliquidAppView.interact.js +70 -0
  6. package/dist/HyperliquidAppView.interact.js.map +1 -0
  7. package/dist/HyperliquidAppView.js +199 -0
  8. package/dist/HyperliquidAppView.js.map +1 -0
  9. package/dist/HyperliquidPositionsPanel.d.ts +12 -0
  10. package/dist/HyperliquidPositionsPanel.d.ts.map +1 -0
  11. package/dist/HyperliquidPositionsPanel.js +194 -0
  12. package/dist/HyperliquidPositionsPanel.js.map +1 -0
  13. package/dist/HyperliquidView.d.ts +14 -0
  14. package/dist/HyperliquidView.d.ts.map +1 -0
  15. package/dist/HyperliquidView.js +56 -0
  16. package/dist/HyperliquidView.js.map +1 -0
  17. package/dist/__fixtures__/contract.d.ts +5 -0
  18. package/dist/__fixtures__/contract.d.ts.map +1 -0
  19. package/dist/__fixtures__/contract.js +87 -0
  20. package/dist/__fixtures__/contract.js.map +1 -0
  21. package/dist/actions/perpetual-market.d.ts +38 -0
  22. package/dist/actions/perpetual-market.d.ts.map +1 -0
  23. package/dist/actions/perpetual-market.js +653 -0
  24. package/dist/actions/perpetual-market.js.map +1 -0
  25. package/dist/client.d.ts +9 -0
  26. package/dist/client.d.ts.map +1 -0
  27. package/dist/client.js +15 -0
  28. package/dist/client.js.map +1 -0
  29. package/dist/components/HyperliquidSpatialView.d.ts +46 -0
  30. package/dist/components/HyperliquidSpatialView.d.ts.map +1 -0
  31. package/dist/components/HyperliquidSpatialView.js +214 -0
  32. package/dist/components/HyperliquidSpatialView.js.map +1 -0
  33. package/dist/hyperliquid-app-view-bundle.d.ts +3 -0
  34. package/dist/hyperliquid-app-view-bundle.d.ts.map +1 -0
  35. package/dist/hyperliquid-app-view-bundle.js +7 -0
  36. package/dist/hyperliquid-app-view-bundle.js.map +1 -0
  37. package/dist/hyperliquid-app.d.ts +4 -0
  38. package/dist/hyperliquid-app.d.ts.map +1 -0
  39. package/dist/hyperliquid-app.js +18 -0
  40. package/dist/hyperliquid-app.js.map +1 -0
  41. package/dist/hyperliquid-contracts.d.ts +152 -0
  42. package/dist/hyperliquid-contracts.d.ts.map +1 -0
  43. package/dist/hyperliquid-contracts.js +17 -0
  44. package/dist/hyperliquid-contracts.js.map +1 -0
  45. package/dist/index.d.ts +12 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +19 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/plugin.d.ts +3 -0
  50. package/dist/plugin.d.ts.map +1 -0
  51. package/dist/plugin.js +130 -0
  52. package/dist/plugin.js.map +1 -0
  53. package/dist/register-routes.d.ts +2 -0
  54. package/dist/register-routes.d.ts.map +1 -0
  55. package/dist/register-routes.js +6 -0
  56. package/dist/register-routes.js.map +1 -0
  57. package/dist/register-terminal-view.d.ts +15 -0
  58. package/dist/register-terminal-view.d.ts.map +1 -0
  59. package/dist/register-terminal-view.js +34 -0
  60. package/dist/register-terminal-view.js.map +1 -0
  61. package/dist/register.d.ts +2 -0
  62. package/dist/register.d.ts.map +1 -0
  63. package/dist/register.js +17 -0
  64. package/dist/register.js.map +1 -0
  65. package/dist/routes.d.ts +25 -0
  66. package/dist/routes.d.ts.map +1 -0
  67. package/dist/routes.js +485 -0
  68. package/dist/routes.js.map +1 -0
  69. package/dist/ui.d.ts +6 -0
  70. package/dist/ui.d.ts.map +1 -0
  71. package/dist/ui.js +12 -0
  72. package/dist/ui.js.map +1 -0
  73. package/dist/useHyperliquidState.d.ts +20 -0
  74. package/dist/useHyperliquidState.d.ts.map +1 -0
  75. package/dist/useHyperliquidState.js +72 -0
  76. package/dist/useHyperliquidState.js.map +1 -0
  77. package/dist/views/bundle.js +463 -0
  78. package/dist/views/bundle.js.map +1 -0
  79. package/package.json +6 -6
package/dist/routes.js ADDED
@@ -0,0 +1,485 @@
1
+ import { sendJson, sendJsonError } from "@elizaos/app-core/api/response";
2
+ import { logger } from "@elizaos/core";
3
+ import {
4
+ HYPERLIQUID_ACCOUNT_BLOCKED_REASON,
5
+ HYPERLIQUID_API_BASE,
6
+ HYPERLIQUID_API_WALLET_GUIDANCE,
7
+ HYPERLIQUID_EXECUTION_BLOCKED_REASON,
8
+ HYPERLIQUID_EXECUTION_NOT_IMPLEMENTED_REASON,
9
+ HYPERLIQUID_LOCAL_KEY_GUIDANCE,
10
+ HYPERLIQUID_VAULT_GUIDANCE
11
+ } from "./hyperliquid-contracts.js";
12
+ const HEX_ADDRESS_PATTERN = /^0x[a-fA-F0-9]{40}$/;
13
+ const HEX_PRIVATE_KEY_PATTERN = /^0x[a-fA-F0-9]{64}$/;
14
+ const STEWARD_EVM_ADDRESS_ENV_KEY = "STEWARD_EVM_ADDRESS";
15
+ const MANAGED_EVM_ADDRESS_ENV_KEY = "ELIZA_MANAGED_EVM_ADDRESS";
16
+ async function handleHyperliquidRoute(_req, res, pathname, method, state = {}) {
17
+ if (!pathname.startsWith("/api/hyperliquid")) return false;
18
+ const env = state.env ?? process.env;
19
+ const fetchImpl = state.fetchImpl ?? globalThis.fetch?.bind(globalThis);
20
+ const now = state.now ?? (() => /* @__PURE__ */ new Date());
21
+ const config = resolveHyperliquidConfig(env);
22
+ if (method !== "GET") {
23
+ const payload = {
24
+ executionReady: false,
25
+ executionBlockedReason: config.executionBlockedReason ?? HYPERLIQUID_EXECUTION_BLOCKED_REASON,
26
+ credentialMode: config.credentialMode
27
+ };
28
+ sendJson(res, 501, payload);
29
+ return true;
30
+ }
31
+ if (pathname === "/api/hyperliquid/status") {
32
+ const payload = {
33
+ publicReadReady: Boolean(fetchImpl),
34
+ signerReady: config.signerReady,
35
+ executionReady: config.executionReady,
36
+ executionBlockedReason: config.executionBlockedReason,
37
+ accountAddress: config.accountAddress,
38
+ apiBaseUrl: config.apiBaseUrl,
39
+ credentialMode: config.credentialMode,
40
+ readiness: {
41
+ publicReads: Boolean(fetchImpl),
42
+ accountReads: Boolean(config.accountAddress),
43
+ signer: config.signerReady,
44
+ execution: false
45
+ },
46
+ account: {
47
+ address: config.accountAddress,
48
+ source: config.accountSource,
49
+ guidance: config.accountBlockedReason
50
+ },
51
+ vault: {
52
+ ...config.vault,
53
+ guidance: HYPERLIQUID_VAULT_GUIDANCE
54
+ },
55
+ apiWallet: config.apiWallet
56
+ };
57
+ sendJson(res, 200, payload);
58
+ return true;
59
+ }
60
+ if (!fetchImpl) {
61
+ sendJsonError(res, 503, "Fetch API is unavailable for Hyperliquid reads");
62
+ return true;
63
+ }
64
+ const client = createHyperliquidInfoClient({
65
+ fetchImpl,
66
+ apiBaseUrl: config.apiBaseUrl
67
+ });
68
+ if (pathname === "/api/hyperliquid/markets") {
69
+ try {
70
+ const payload = {
71
+ markets: await client.getMarkets(),
72
+ source: "hyperliquid-info-meta",
73
+ fetchedAt: now().toISOString()
74
+ };
75
+ sendJson(res, 200, payload);
76
+ } catch (error) {
77
+ logger.error(
78
+ { error: describeError(error) },
79
+ "[HyperliquidRoutes] Market fetch failed"
80
+ );
81
+ sendJsonError(res, 502, "Hyperliquid market fetch failed");
82
+ }
83
+ return true;
84
+ }
85
+ if (pathname === "/api/hyperliquid/funding") {
86
+ try {
87
+ const payload = {
88
+ rates: await client.getFundingRates(),
89
+ source: "hyperliquid-info-meta-and-asset-ctxs",
90
+ fetchedAt: now().toISOString()
91
+ };
92
+ sendJson(res, 200, payload);
93
+ } catch (error) {
94
+ logger.error(
95
+ { error: describeError(error) },
96
+ "[HyperliquidRoutes] Funding-rate fetch failed"
97
+ );
98
+ sendJsonError(res, 502, "Hyperliquid funding-rate fetch failed");
99
+ }
100
+ return true;
101
+ }
102
+ if (pathname === "/api/hyperliquid/positions") {
103
+ if (!config.accountAddress) {
104
+ const payload = {
105
+ accountAddress: null,
106
+ positions: [],
107
+ summary: null,
108
+ readBlockedReason: config.accountBlockedReason,
109
+ fetchedAt: null
110
+ };
111
+ sendJson(res, 200, payload);
112
+ return true;
113
+ }
114
+ try {
115
+ const snapshot = await client.getPositions(config.accountAddress);
116
+ const payload = {
117
+ accountAddress: config.accountAddress,
118
+ positions: snapshot.positions,
119
+ summary: snapshot.summary,
120
+ readBlockedReason: null,
121
+ fetchedAt: now().toISOString()
122
+ };
123
+ sendJson(res, 200, payload);
124
+ } catch (error) {
125
+ logger.error(
126
+ { error: describeError(error), accountAddress: config.accountAddress },
127
+ "[HyperliquidRoutes] Position fetch failed"
128
+ );
129
+ sendJsonError(res, 502, "Hyperliquid position fetch failed");
130
+ }
131
+ return true;
132
+ }
133
+ if (pathname === "/api/hyperliquid/orders") {
134
+ if (!config.accountAddress) {
135
+ const payload = {
136
+ accountAddress: null,
137
+ orders: [],
138
+ readBlockedReason: config.accountBlockedReason,
139
+ fetchedAt: null
140
+ };
141
+ sendJson(res, 200, payload);
142
+ return true;
143
+ }
144
+ try {
145
+ const payload = {
146
+ accountAddress: config.accountAddress,
147
+ orders: await client.getOpenOrders(config.accountAddress),
148
+ readBlockedReason: null,
149
+ fetchedAt: now().toISOString()
150
+ };
151
+ sendJson(res, 200, payload);
152
+ } catch (error) {
153
+ logger.error(
154
+ { error: describeError(error), accountAddress: config.accountAddress },
155
+ "[HyperliquidRoutes] Order fetch failed"
156
+ );
157
+ sendJsonError(res, 502, "Hyperliquid order fetch failed");
158
+ }
159
+ return true;
160
+ }
161
+ return false;
162
+ }
163
+ function createHyperliquidInfoClient({
164
+ fetchImpl,
165
+ apiBaseUrl = HYPERLIQUID_API_BASE
166
+ }) {
167
+ async function infoRequest(body) {
168
+ const response = await fetchImpl(`${apiBaseUrl}/info`, {
169
+ method: "POST",
170
+ headers: { "Content-Type": "application/json" },
171
+ body: JSON.stringify(body)
172
+ });
173
+ if (!response.ok) {
174
+ const text = await response.text().catch(() => "");
175
+ throw new Error(
176
+ `Hyperliquid Info API ${response.status}: ${text.slice(0, 200)}`
177
+ );
178
+ }
179
+ return await response.json();
180
+ }
181
+ return {
182
+ async getMarkets() {
183
+ const meta = await infoRequest({ type: "meta" });
184
+ return parseMarkets(meta);
185
+ },
186
+ async getFundingRates() {
187
+ const metaAndCtxs = await infoRequest({
188
+ type: "metaAndAssetCtxs"
189
+ });
190
+ return parseFundingRates(metaAndCtxs);
191
+ },
192
+ async getPositions(accountAddress) {
193
+ const state = await infoRequest({
194
+ type: "clearinghouseState",
195
+ user: accountAddress
196
+ });
197
+ return parseClearinghouseState(state);
198
+ },
199
+ async getOpenOrders(accountAddress) {
200
+ const orders = await infoRequest({
201
+ type: "openOrders",
202
+ user: accountAddress
203
+ });
204
+ return parseOrders(orders);
205
+ }
206
+ };
207
+ }
208
+ function resolveHyperliquidConfig(env) {
209
+ const managedVaultAddress = readFirstValidAddress(env, [
210
+ STEWARD_EVM_ADDRESS_ENV_KEY,
211
+ MANAGED_EVM_ADDRESS_ENV_KEY
212
+ ]);
213
+ const managedVaultConfigured = Boolean(managedVaultAddress) || Boolean(readEnvString(env, "STEWARD_API_URL")) || readEnvString(env, "ELIZA_WALLET_BACKEND") === "steward";
214
+ const managedVaultReady = Boolean(managedVaultAddress);
215
+ const rawAccount = readEnvString(env, "HYPERLIQUID_ACCOUNT_ADDRESS") ?? readEnvString(env, "HL_ACCOUNT_ADDRESS");
216
+ const envAccountAddress = rawAccount && HEX_ADDRESS_PATTERN.test(rawAccount) ? rawAccount : null;
217
+ const accountAddress = managedVaultAddress ?? envAccountAddress;
218
+ const accountSource = managedVaultAddress ? "managed_vault" : envAccountAddress ? "env_account" : "none";
219
+ const accountBlockedReason = accountAddress ? null : rawAccount ? "HYPERLIQUID_ACCOUNT_ADDRESS / HL_ACCOUNT_ADDRESS must be a 0x-prefixed EVM address." : HYPERLIQUID_ACCOUNT_BLOCKED_REASON;
220
+ const privateKey = readFirstValidPrivateKey(env, [
221
+ "EVM_PRIVATE_KEY",
222
+ "HYPERLIQUID_PRIVATE_KEY",
223
+ "HL_PRIVATE_KEY"
224
+ ]);
225
+ const localKeyReady = Boolean(privateKey);
226
+ const signerReady = managedVaultReady || localKeyReady;
227
+ const credentialMode = resolveCredentialMode({
228
+ managedVaultReady,
229
+ localKeyReady
230
+ });
231
+ const apiWalletConfigured = Boolean(
232
+ readFirstValidPrivateKey(env, ["HYPERLIQUID_AGENT_KEY", "HL_AGENT_KEY"])
233
+ );
234
+ return {
235
+ apiBaseUrl: HYPERLIQUID_API_BASE,
236
+ accountAddress,
237
+ accountSource,
238
+ accountBlockedReason,
239
+ credentialMode,
240
+ signerReady,
241
+ executionReady: false,
242
+ executionBlockedReason: signerReady ? HYPERLIQUID_EXECUTION_NOT_IMPLEMENTED_REASON : HYPERLIQUID_EXECUTION_BLOCKED_REASON,
243
+ vault: {
244
+ configured: managedVaultConfigured,
245
+ ready: managedVaultReady,
246
+ address: managedVaultAddress
247
+ },
248
+ apiWallet: {
249
+ configured: apiWalletConfigured,
250
+ guidance: apiWalletConfigured ? HYPERLIQUID_API_WALLET_GUIDANCE : `${HYPERLIQUID_API_WALLET_GUIDANCE} ${HYPERLIQUID_LOCAL_KEY_GUIDANCE}`
251
+ }
252
+ };
253
+ }
254
+ function resolveCredentialMode({
255
+ managedVaultReady,
256
+ localKeyReady
257
+ }) {
258
+ if (managedVaultReady) return "managed_vault";
259
+ if (localKeyReady) return "local_key";
260
+ return "none";
261
+ }
262
+ function readFirstValidAddress(env, keys) {
263
+ for (const key of keys) {
264
+ const value = readEnvString(env, key);
265
+ if (value && HEX_ADDRESS_PATTERN.test(value)) return value;
266
+ }
267
+ return null;
268
+ }
269
+ function readFirstValidPrivateKey(env, keys) {
270
+ for (const key of keys) {
271
+ const value = readEnvString(env, key);
272
+ if (value && HEX_PRIVATE_KEY_PATTERN.test(value)) return value;
273
+ }
274
+ return null;
275
+ }
276
+ function readEnvString(env, key) {
277
+ const value = env[key]?.trim();
278
+ return value ? value : void 0;
279
+ }
280
+ function parseMarkets(value) {
281
+ const record = asRecord(value, "Hyperliquid meta response");
282
+ const universe = record.universe;
283
+ if (!Array.isArray(universe)) {
284
+ throw new Error("Hyperliquid meta response missing universe");
285
+ }
286
+ return universe.map((entry, index) => {
287
+ const item = asRecord(entry, "Hyperliquid universe entry");
288
+ return {
289
+ name: readRequiredString(item, "name"),
290
+ index,
291
+ szDecimals: readRequiredNumber(item, "szDecimals"),
292
+ maxLeverage: readOptionalNumber(item, "maxLeverage"),
293
+ onlyIsolated: readOptionalBoolean(item, "onlyIsolated") ?? false,
294
+ isDelisted: readOptionalBoolean(item, "isDelisted") ?? false
295
+ };
296
+ });
297
+ }
298
+ function parseFundingRates(value) {
299
+ if (!Array.isArray(value) || value.length < 2) {
300
+ throw new Error("Hyperliquid metaAndAssetCtxs response must be a pair");
301
+ }
302
+ const markets = parseMarkets(value[0]);
303
+ const contexts = value[1];
304
+ if (!Array.isArray(contexts)) {
305
+ throw new Error("Hyperliquid metaAndAssetCtxs response missing contexts");
306
+ }
307
+ return contexts.map((entry, index) => {
308
+ const context = asRecord(entry, "Hyperliquid asset context");
309
+ const market = markets[index];
310
+ if (!market) {
311
+ throw new Error(`Hyperliquid asset context ${index} has no market`);
312
+ }
313
+ return {
314
+ coin: market.name,
315
+ index,
316
+ funding: readRequiredString(context, "funding"),
317
+ premium: readOptionalString(context, "premium"),
318
+ markPx: readOptionalString(context, "markPx"),
319
+ oraclePx: readOptionalString(context, "oraclePx"),
320
+ openInterest: readOptionalString(context, "openInterest")
321
+ };
322
+ });
323
+ }
324
+ function parsePositions(assetPositions) {
325
+ return assetPositions.map((entry) => {
326
+ const item = asRecord(entry, "Hyperliquid asset position entry");
327
+ const position = asRecord(item.position, "Hyperliquid position");
328
+ const leverage = position.leverage === void 0 ? null : asRecord(position.leverage, "Hyperliquid leverage");
329
+ const size = readRequiredString(position, "szi");
330
+ const positionValue = readOptionalString(position, "positionValue");
331
+ const liquidationPx = readOptionalString(position, "liquidationPx");
332
+ const markPx = computeMarkPx(positionValue, size);
333
+ return {
334
+ coin: readRequiredString(position, "coin"),
335
+ size,
336
+ entryPx: readOptionalString(position, "entryPx"),
337
+ positionValue,
338
+ unrealizedPnl: readOptionalString(position, "unrealizedPnl"),
339
+ returnOnEquity: readOptionalString(position, "returnOnEquity"),
340
+ liquidationPx,
341
+ marginUsed: readOptionalString(position, "marginUsed"),
342
+ leverageType: leverage ? readOptionalString(leverage, "type") : null,
343
+ leverageValue: leverage ? readOptionalNumber(leverage, "value") : null,
344
+ markPx: markPx === null ? null : String(markPx),
345
+ distanceToLiquidationPct: computeDistanceToLiquidationPct(
346
+ markPx,
347
+ liquidationPx,
348
+ size
349
+ )
350
+ };
351
+ });
352
+ }
353
+ function computeMarkPx(positionValue, size) {
354
+ if (positionValue === null) return null;
355
+ const value = Number(positionValue);
356
+ const szi = Number(size);
357
+ if (!Number.isFinite(value) || !Number.isFinite(szi)) return null;
358
+ if (Math.abs(szi) < 1e-12) return null;
359
+ return Math.abs(value) / Math.abs(szi);
360
+ }
361
+ function computeDistanceToLiquidationPct(markPx, liquidationPx, size) {
362
+ if (markPx === null || liquidationPx === null) return null;
363
+ const liq = Number(liquidationPx);
364
+ const szi = Number(size);
365
+ if (!Number.isFinite(markPx) || !Number.isFinite(liq) || !Number.isFinite(szi) || markPx <= 0) {
366
+ return null;
367
+ }
368
+ const isLong = szi >= 0;
369
+ const distance = isLong ? (markPx - liq) / markPx : (liq - markPx) / markPx;
370
+ return distance * 100;
371
+ }
372
+ function sumUnrealizedPnl(positions) {
373
+ let total = 0;
374
+ let seen = false;
375
+ for (const position of positions) {
376
+ if (position.unrealizedPnl === null) continue;
377
+ const value = Number(position.unrealizedPnl);
378
+ if (!Number.isFinite(value)) continue;
379
+ total += value;
380
+ seen = true;
381
+ }
382
+ return seen ? total.toFixed(2) : null;
383
+ }
384
+ function parseAccountSummary(positions, marginSummary, withdrawable) {
385
+ const accountValue = marginSummary ? readOptionalString(marginSummary, "accountValue") : null;
386
+ const totalNotionalPosition = marginSummary ? readOptionalString(marginSummary, "totalNtlPos") : null;
387
+ return {
388
+ accountValue,
389
+ totalNotionalPosition,
390
+ totalMarginUsed: marginSummary ? readOptionalString(marginSummary, "totalMarginUsed") : null,
391
+ totalRawUsd: marginSummary ? readOptionalString(marginSummary, "totalRawUsd") : null,
392
+ withdrawable,
393
+ totalUnrealizedPnl: sumUnrealizedPnl(positions),
394
+ effectiveLeverage: computeEffectiveLeverage(
395
+ totalNotionalPosition,
396
+ accountValue
397
+ )
398
+ };
399
+ }
400
+ function computeEffectiveLeverage(totalNotionalPosition, accountValue) {
401
+ if (totalNotionalPosition === null || accountValue === null) return null;
402
+ const notional = Number(totalNotionalPosition);
403
+ const value = Number(accountValue);
404
+ if (!Number.isFinite(notional) || !Number.isFinite(value) || value <= 0) {
405
+ return null;
406
+ }
407
+ return notional / value;
408
+ }
409
+ function parseClearinghouseState(value) {
410
+ const record = asRecord(value, "Hyperliquid clearinghouseState response");
411
+ const assetPositions = record.assetPositions;
412
+ if (!Array.isArray(assetPositions)) {
413
+ throw new Error("Hyperliquid clearinghouseState missing assetPositions");
414
+ }
415
+ const positions = parsePositions(assetPositions);
416
+ const marginSummary = record.marginSummary === void 0 || record.marginSummary === null ? null : asRecord(record.marginSummary, "Hyperliquid marginSummary");
417
+ const withdrawable = readOptionalString(record, "withdrawable");
418
+ return {
419
+ positions,
420
+ summary: parseAccountSummary(positions, marginSummary, withdrawable)
421
+ };
422
+ }
423
+ function parseOrders(value) {
424
+ if (!Array.isArray(value)) {
425
+ throw new Error("Hyperliquid openOrders response must be an array");
426
+ }
427
+ return value.map((entry) => {
428
+ const item = asRecord(entry, "Hyperliquid open order");
429
+ return {
430
+ coin: readRequiredString(item, "coin"),
431
+ side: readRequiredString(item, "side"),
432
+ limitPx: readRequiredString(item, "limitPx"),
433
+ size: readRequiredString(item, "sz"),
434
+ oid: readRequiredNumber(item, "oid"),
435
+ timestamp: readRequiredNumber(item, "timestamp"),
436
+ reduceOnly: readOptionalBoolean(item, "reduceOnly") ?? false,
437
+ orderType: readOptionalString(item, "orderType"),
438
+ tif: readOptionalString(item, "tif"),
439
+ cloid: readOptionalString(item, "cloid")
440
+ };
441
+ });
442
+ }
443
+ function asRecord(value, label) {
444
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
445
+ throw new Error(`${label} must be an object`);
446
+ }
447
+ return value;
448
+ }
449
+ function readRequiredString(value, key) {
450
+ const field = value[key];
451
+ if (typeof field !== "string") {
452
+ throw new Error(`${key} must be a string`);
453
+ }
454
+ return field;
455
+ }
456
+ function readOptionalString(value, key) {
457
+ const field = value[key];
458
+ return typeof field === "string" ? field : null;
459
+ }
460
+ function readRequiredNumber(value, key) {
461
+ const field = value[key];
462
+ if (typeof field !== "number" || !Number.isFinite(field)) {
463
+ throw new Error(`${key} must be a finite number`);
464
+ }
465
+ return field;
466
+ }
467
+ function readOptionalNumber(value, key) {
468
+ const field = value[key];
469
+ return typeof field === "number" && Number.isFinite(field) ? field : null;
470
+ }
471
+ function readOptionalBoolean(value, key) {
472
+ const field = value[key];
473
+ return typeof field === "boolean" ? field : null;
474
+ }
475
+ function describeError(error) {
476
+ if (error instanceof Error) {
477
+ return { message: error.message };
478
+ }
479
+ return { message: String(error) };
480
+ }
481
+ export {
482
+ createHyperliquidInfoClient,
483
+ handleHyperliquidRoute
484
+ };
485
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/routes.ts"],"sourcesContent":["import type http from \"node:http\";\nimport { sendJson, sendJsonError } from \"@elizaos/app-core/api/response\";\nimport { logger } from \"@elizaos/core\";\nimport {\n HYPERLIQUID_ACCOUNT_BLOCKED_REASON,\n HYPERLIQUID_API_BASE,\n HYPERLIQUID_API_WALLET_GUIDANCE,\n HYPERLIQUID_EXECUTION_BLOCKED_REASON,\n HYPERLIQUID_EXECUTION_NOT_IMPLEMENTED_REASON,\n HYPERLIQUID_LOCAL_KEY_GUIDANCE,\n HYPERLIQUID_VAULT_GUIDANCE,\n type HyperliquidAccountSource,\n type HyperliquidAccountSummary,\n type HyperliquidApiWalletStatus,\n type HyperliquidCredentialMode,\n type HyperliquidExecutionDisabledResponse,\n type HyperliquidFundingRate,\n type HyperliquidFundingResponse,\n type HyperliquidMarket,\n type HyperliquidMarketsResponse,\n type HyperliquidOrder,\n type HyperliquidOrdersResponse,\n type HyperliquidPosition,\n type HyperliquidPositionsResponse,\n type HyperliquidStatusResponse,\n} from \"./hyperliquid-contracts.js\";\n\nexport type HyperliquidFetch = (\n input: string | URL | Request,\n init?: RequestInit,\n) => Promise<Response>;\n\nexport interface HyperliquidRouteState {\n fetchImpl?: HyperliquidFetch;\n env?: NodeJS.ProcessEnv;\n now?: () => Date;\n}\n\ninterface HyperliquidConfig {\n apiBaseUrl: string;\n accountAddress: string | null;\n accountSource: HyperliquidAccountSource;\n accountBlockedReason: string | null;\n credentialMode: HyperliquidCredentialMode;\n signerReady: boolean;\n executionReady: boolean;\n executionBlockedReason: string | null;\n vault: {\n configured: boolean;\n ready: boolean;\n address: string | null;\n };\n apiWallet: HyperliquidApiWalletStatus;\n}\n\ninterface HyperliquidClearinghouseSnapshot {\n positions: HyperliquidPosition[];\n summary: HyperliquidAccountSummary;\n}\n\ninterface HyperliquidInfoClient {\n getMarkets(): Promise<HyperliquidMarket[]>;\n getFundingRates(): Promise<HyperliquidFundingRate[]>;\n getPositions(\n accountAddress: string,\n ): Promise<HyperliquidClearinghouseSnapshot>;\n getOpenOrders(accountAddress: string): Promise<HyperliquidOrder[]>;\n}\n\nconst HEX_ADDRESS_PATTERN = /^0x[a-fA-F0-9]{40}$/;\nconst HEX_PRIVATE_KEY_PATTERN = /^0x[a-fA-F0-9]{64}$/;\nconst STEWARD_EVM_ADDRESS_ENV_KEY = \"STEWARD_EVM_ADDRESS\";\nconst MANAGED_EVM_ADDRESS_ENV_KEY = \"ELIZA_MANAGED_EVM_ADDRESS\";\n\nexport async function handleHyperliquidRoute(\n _req: http.IncomingMessage,\n res: http.ServerResponse,\n pathname: string,\n method: string,\n state: HyperliquidRouteState = {},\n): Promise<boolean> {\n if (!pathname.startsWith(\"/api/hyperliquid\")) return false;\n\n const env = state.env ?? process.env;\n const fetchImpl = state.fetchImpl ?? globalThis.fetch?.bind(globalThis);\n const now = state.now ?? (() => new Date());\n const config = resolveHyperliquidConfig(env);\n\n if (method !== \"GET\") {\n const payload: HyperliquidExecutionDisabledResponse = {\n executionReady: false,\n executionBlockedReason:\n config.executionBlockedReason ?? HYPERLIQUID_EXECUTION_BLOCKED_REASON,\n credentialMode: config.credentialMode,\n };\n sendJson(res, 501, payload);\n return true;\n }\n\n if (pathname === \"/api/hyperliquid/status\") {\n const payload: HyperliquidStatusResponse = {\n publicReadReady: Boolean(fetchImpl),\n signerReady: config.signerReady,\n executionReady: config.executionReady,\n executionBlockedReason: config.executionBlockedReason,\n accountAddress: config.accountAddress,\n apiBaseUrl: config.apiBaseUrl,\n credentialMode: config.credentialMode,\n readiness: {\n publicReads: Boolean(fetchImpl),\n accountReads: Boolean(config.accountAddress),\n signer: config.signerReady,\n execution: false,\n },\n account: {\n address: config.accountAddress,\n source: config.accountSource,\n guidance: config.accountBlockedReason,\n },\n vault: {\n ...config.vault,\n guidance: HYPERLIQUID_VAULT_GUIDANCE,\n },\n apiWallet: config.apiWallet,\n };\n sendJson(res, 200, payload);\n return true;\n }\n\n if (!fetchImpl) {\n sendJsonError(res, 503, \"Fetch API is unavailable for Hyperliquid reads\");\n return true;\n }\n\n const client = createHyperliquidInfoClient({\n fetchImpl,\n apiBaseUrl: config.apiBaseUrl,\n });\n\n if (pathname === \"/api/hyperliquid/markets\") {\n try {\n const payload: HyperliquidMarketsResponse = {\n markets: await client.getMarkets(),\n source: \"hyperliquid-info-meta\",\n fetchedAt: now().toISOString(),\n };\n sendJson(res, 200, payload);\n } catch (error) {\n logger.error(\n { error: describeError(error) },\n \"[HyperliquidRoutes] Market fetch failed\",\n );\n sendJsonError(res, 502, \"Hyperliquid market fetch failed\");\n }\n return true;\n }\n\n if (pathname === \"/api/hyperliquid/funding\") {\n try {\n const payload: HyperliquidFundingResponse = {\n rates: await client.getFundingRates(),\n source: \"hyperliquid-info-meta-and-asset-ctxs\",\n fetchedAt: now().toISOString(),\n };\n sendJson(res, 200, payload);\n } catch (error) {\n logger.error(\n { error: describeError(error) },\n \"[HyperliquidRoutes] Funding-rate fetch failed\",\n );\n sendJsonError(res, 502, \"Hyperliquid funding-rate fetch failed\");\n }\n return true;\n }\n\n if (pathname === \"/api/hyperliquid/positions\") {\n if (!config.accountAddress) {\n const payload: HyperliquidPositionsResponse = {\n accountAddress: null,\n positions: [],\n summary: null,\n readBlockedReason: config.accountBlockedReason,\n fetchedAt: null,\n };\n sendJson(res, 200, payload);\n return true;\n }\n\n try {\n const snapshot = await client.getPositions(config.accountAddress);\n const payload: HyperliquidPositionsResponse = {\n accountAddress: config.accountAddress,\n positions: snapshot.positions,\n summary: snapshot.summary,\n readBlockedReason: null,\n fetchedAt: now().toISOString(),\n };\n sendJson(res, 200, payload);\n } catch (error) {\n logger.error(\n { error: describeError(error), accountAddress: config.accountAddress },\n \"[HyperliquidRoutes] Position fetch failed\",\n );\n sendJsonError(res, 502, \"Hyperliquid position fetch failed\");\n }\n return true;\n }\n\n if (pathname === \"/api/hyperliquid/orders\") {\n if (!config.accountAddress) {\n const payload: HyperliquidOrdersResponse = {\n accountAddress: null,\n orders: [],\n readBlockedReason: config.accountBlockedReason,\n fetchedAt: null,\n };\n sendJson(res, 200, payload);\n return true;\n }\n\n try {\n const payload: HyperliquidOrdersResponse = {\n accountAddress: config.accountAddress,\n orders: await client.getOpenOrders(config.accountAddress),\n readBlockedReason: null,\n fetchedAt: now().toISOString(),\n };\n sendJson(res, 200, payload);\n } catch (error) {\n logger.error(\n { error: describeError(error), accountAddress: config.accountAddress },\n \"[HyperliquidRoutes] Order fetch failed\",\n );\n sendJsonError(res, 502, \"Hyperliquid order fetch failed\");\n }\n return true;\n }\n\n return false;\n}\n\nexport function createHyperliquidInfoClient({\n fetchImpl,\n apiBaseUrl = HYPERLIQUID_API_BASE,\n}: {\n fetchImpl: HyperliquidFetch;\n apiBaseUrl?: string;\n}): HyperliquidInfoClient {\n async function infoRequest<T>(body: Record<string, string>): Promise<T> {\n const response = await fetchImpl(`${apiBaseUrl}/info`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n throw new Error(\n `Hyperliquid Info API ${response.status}: ${text.slice(0, 200)}`,\n );\n }\n\n return (await response.json()) as T;\n }\n\n return {\n async getMarkets() {\n const meta = await infoRequest<unknown>({ type: \"meta\" });\n return parseMarkets(meta);\n },\n async getFundingRates() {\n const metaAndCtxs = await infoRequest<unknown>({\n type: \"metaAndAssetCtxs\",\n });\n return parseFundingRates(metaAndCtxs);\n },\n async getPositions(accountAddress) {\n const state = await infoRequest<unknown>({\n type: \"clearinghouseState\",\n user: accountAddress,\n });\n return parseClearinghouseState(state);\n },\n async getOpenOrders(accountAddress) {\n const orders = await infoRequest<unknown>({\n type: \"openOrders\",\n user: accountAddress,\n });\n return parseOrders(orders);\n },\n };\n}\n\nfunction resolveHyperliquidConfig(env: NodeJS.ProcessEnv): HyperliquidConfig {\n const managedVaultAddress = readFirstValidAddress(env, [\n STEWARD_EVM_ADDRESS_ENV_KEY,\n MANAGED_EVM_ADDRESS_ENV_KEY,\n ]);\n const managedVaultConfigured =\n Boolean(managedVaultAddress) ||\n Boolean(readEnvString(env, \"STEWARD_API_URL\")) ||\n readEnvString(env, \"ELIZA_WALLET_BACKEND\") === \"steward\";\n const managedVaultReady = Boolean(managedVaultAddress);\n const rawAccount =\n readEnvString(env, \"HYPERLIQUID_ACCOUNT_ADDRESS\") ??\n readEnvString(env, \"HL_ACCOUNT_ADDRESS\");\n const envAccountAddress =\n rawAccount && HEX_ADDRESS_PATTERN.test(rawAccount) ? rawAccount : null;\n const accountAddress = managedVaultAddress ?? envAccountAddress;\n const accountSource: HyperliquidAccountSource = managedVaultAddress\n ? \"managed_vault\"\n : envAccountAddress\n ? \"env_account\"\n : \"none\";\n const accountBlockedReason = accountAddress\n ? null\n : rawAccount\n ? \"HYPERLIQUID_ACCOUNT_ADDRESS / HL_ACCOUNT_ADDRESS must be a 0x-prefixed EVM address.\"\n : HYPERLIQUID_ACCOUNT_BLOCKED_REASON;\n const privateKey = readFirstValidPrivateKey(env, [\n \"EVM_PRIVATE_KEY\",\n \"HYPERLIQUID_PRIVATE_KEY\",\n \"HL_PRIVATE_KEY\",\n ]);\n const localKeyReady = Boolean(privateKey);\n const signerReady = managedVaultReady || localKeyReady;\n const credentialMode = resolveCredentialMode({\n managedVaultReady,\n localKeyReady,\n });\n const apiWalletConfigured = Boolean(\n readFirstValidPrivateKey(env, [\"HYPERLIQUID_AGENT_KEY\", \"HL_AGENT_KEY\"]),\n );\n\n return {\n apiBaseUrl: HYPERLIQUID_API_BASE,\n accountAddress,\n accountSource,\n accountBlockedReason,\n credentialMode,\n signerReady,\n executionReady: false,\n executionBlockedReason: signerReady\n ? HYPERLIQUID_EXECUTION_NOT_IMPLEMENTED_REASON\n : HYPERLIQUID_EXECUTION_BLOCKED_REASON,\n vault: {\n configured: managedVaultConfigured,\n ready: managedVaultReady,\n address: managedVaultAddress,\n },\n apiWallet: {\n configured: apiWalletConfigured,\n guidance: apiWalletConfigured\n ? HYPERLIQUID_API_WALLET_GUIDANCE\n : `${HYPERLIQUID_API_WALLET_GUIDANCE} ${HYPERLIQUID_LOCAL_KEY_GUIDANCE}`,\n },\n };\n}\n\nfunction resolveCredentialMode({\n managedVaultReady,\n localKeyReady,\n}: {\n managedVaultReady: boolean;\n localKeyReady: boolean;\n}): HyperliquidCredentialMode {\n if (managedVaultReady) return \"managed_vault\";\n if (localKeyReady) return \"local_key\";\n return \"none\";\n}\n\nfunction readFirstValidAddress(\n env: NodeJS.ProcessEnv,\n keys: string[],\n): string | null {\n for (const key of keys) {\n const value = readEnvString(env, key);\n if (value && HEX_ADDRESS_PATTERN.test(value)) return value;\n }\n return null;\n}\n\nfunction readFirstValidPrivateKey(\n env: NodeJS.ProcessEnv,\n keys: string[],\n): string | null {\n for (const key of keys) {\n const value = readEnvString(env, key);\n if (value && HEX_PRIVATE_KEY_PATTERN.test(value)) return value;\n }\n return null;\n}\n\nfunction readEnvString(\n env: NodeJS.ProcessEnv,\n key: string,\n): string | undefined {\n const value = env[key]?.trim();\n return value ? value : undefined;\n}\n\nfunction parseMarkets(value: unknown): HyperliquidMarket[] {\n const record = asRecord(value, \"Hyperliquid meta response\");\n const universe = record.universe;\n if (!Array.isArray(universe)) {\n throw new Error(\"Hyperliquid meta response missing universe\");\n }\n\n return universe.map((entry, index) => {\n const item = asRecord(entry, \"Hyperliquid universe entry\");\n return {\n name: readRequiredString(item, \"name\"),\n index,\n szDecimals: readRequiredNumber(item, \"szDecimals\"),\n maxLeverage: readOptionalNumber(item, \"maxLeverage\"),\n onlyIsolated: readOptionalBoolean(item, \"onlyIsolated\") ?? false,\n isDelisted: readOptionalBoolean(item, \"isDelisted\") ?? false,\n };\n });\n}\n\nfunction parseFundingRates(value: unknown): HyperliquidFundingRate[] {\n if (!Array.isArray(value) || value.length < 2) {\n throw new Error(\"Hyperliquid metaAndAssetCtxs response must be a pair\");\n }\n const markets = parseMarkets(value[0]);\n const contexts = value[1];\n if (!Array.isArray(contexts)) {\n throw new Error(\"Hyperliquid metaAndAssetCtxs response missing contexts\");\n }\n\n return contexts.map((entry, index) => {\n const context = asRecord(entry, \"Hyperliquid asset context\");\n const market = markets[index];\n if (!market) {\n throw new Error(`Hyperliquid asset context ${index} has no market`);\n }\n return {\n coin: market.name,\n index,\n funding: readRequiredString(context, \"funding\"),\n premium: readOptionalString(context, \"premium\"),\n markPx: readOptionalString(context, \"markPx\"),\n oraclePx: readOptionalString(context, \"oraclePx\"),\n openInterest: readOptionalString(context, \"openInterest\"),\n };\n });\n}\n\nfunction parsePositions(assetPositions: unknown[]): HyperliquidPosition[] {\n return assetPositions.map((entry) => {\n const item = asRecord(entry, \"Hyperliquid asset position entry\");\n const position = asRecord(item.position, \"Hyperliquid position\");\n const leverage =\n position.leverage === undefined\n ? null\n : asRecord(position.leverage, \"Hyperliquid leverage\");\n\n const size = readRequiredString(position, \"szi\");\n const positionValue = readOptionalString(position, \"positionValue\");\n const liquidationPx = readOptionalString(position, \"liquidationPx\");\n const markPx = computeMarkPx(positionValue, size);\n\n return {\n coin: readRequiredString(position, \"coin\"),\n size,\n entryPx: readOptionalString(position, \"entryPx\"),\n positionValue,\n unrealizedPnl: readOptionalString(position, \"unrealizedPnl\"),\n returnOnEquity: readOptionalString(position, \"returnOnEquity\"),\n liquidationPx,\n marginUsed: readOptionalString(position, \"marginUsed\"),\n leverageType: leverage ? readOptionalString(leverage, \"type\") : null,\n leverageValue: leverage ? readOptionalNumber(leverage, \"value\") : null,\n markPx: markPx === null ? null : String(markPx),\n distanceToLiquidationPct: computeDistanceToLiquidationPct(\n markPx,\n liquidationPx,\n size,\n ),\n };\n });\n}\n\n/**\n * Current mark price = |positionValue| / |size|. Hyperliquid's clearinghouse\n * snapshot already carries the live position value, so the mark is derivable\n * without a second markets fetch. Null when either input is unreadable or the\n * size is effectively zero.\n */\nfunction computeMarkPx(\n positionValue: string | null,\n size: string,\n): number | null {\n if (positionValue === null) return null;\n const value = Number(positionValue);\n const szi = Number(size);\n if (!Number.isFinite(value) || !Number.isFinite(szi)) return null;\n if (Math.abs(szi) < 1e-12) return null;\n return Math.abs(value) / Math.abs(szi);\n}\n\n/**\n * Distance from the current mark to the liquidation price as a percent of mark.\n * Longs liquidate below mark ((mark - liq) / mark); shorts above ((liq - mark)\n * / mark). The position side is read from `size` (negative szi = short). Uses\n * the real mark, not the entry price. Null when mark/liq are unreadable.\n */\nfunction computeDistanceToLiquidationPct(\n markPx: number | null,\n liquidationPx: string | null,\n size: string,\n): number | null {\n if (markPx === null || liquidationPx === null) return null;\n const liq = Number(liquidationPx);\n const szi = Number(size);\n if (\n !Number.isFinite(markPx) ||\n !Number.isFinite(liq) ||\n !Number.isFinite(szi) ||\n markPx <= 0\n ) {\n return null;\n }\n const isLong = szi >= 0;\n const distance = isLong ? (markPx - liq) / markPx : (liq - markPx) / markPx;\n return distance * 100;\n}\n\n/**\n * Sum each position's `unrealizedPnl` (stringified USD) into a single\n * aggregate, returned as a fixed-2 string so the AppView renders one honest\n * \"unrealized PnL\" hero stat. Returns null when no position carries a\n * parseable PnL (e.g. a freshly funded account with no open positions).\n */\nfunction sumUnrealizedPnl(positions: HyperliquidPosition[]): string | null {\n let total = 0;\n let seen = false;\n for (const position of positions) {\n if (position.unrealizedPnl === null) continue;\n const value = Number(position.unrealizedPnl);\n if (!Number.isFinite(value)) continue;\n total += value;\n seen = true;\n }\n return seen ? total.toFixed(2) : null;\n}\n\nfunction parseAccountSummary(\n positions: HyperliquidPosition[],\n marginSummary: Record<string, unknown> | null,\n withdrawable: string | null,\n): HyperliquidAccountSummary {\n const accountValue = marginSummary\n ? readOptionalString(marginSummary, \"accountValue\")\n : null;\n const totalNotionalPosition = marginSummary\n ? readOptionalString(marginSummary, \"totalNtlPos\")\n : null;\n return {\n accountValue,\n totalNotionalPosition,\n totalMarginUsed: marginSummary\n ? readOptionalString(marginSummary, \"totalMarginUsed\")\n : null,\n totalRawUsd: marginSummary\n ? readOptionalString(marginSummary, \"totalRawUsd\")\n : null,\n withdrawable,\n totalUnrealizedPnl: sumUnrealizedPnl(positions),\n effectiveLeverage: computeEffectiveLeverage(\n totalNotionalPosition,\n accountValue,\n ),\n };\n}\n\n/**\n * Effective account leverage = totalNotionalPosition / accountValue, computed\n * server-side so the view only renders the number. Null when either input is\n * unreadable or account value is non-positive.\n */\nfunction computeEffectiveLeverage(\n totalNotionalPosition: string | null,\n accountValue: string | null,\n): number | null {\n if (totalNotionalPosition === null || accountValue === null) return null;\n const notional = Number(totalNotionalPosition);\n const value = Number(accountValue);\n if (!Number.isFinite(notional) || !Number.isFinite(value) || value <= 0) {\n return null;\n }\n return notional / value;\n}\n\nfunction parseClearinghouseState(value: unknown): {\n positions: HyperliquidPosition[];\n summary: HyperliquidAccountSummary;\n} {\n const record = asRecord(value, \"Hyperliquid clearinghouseState response\");\n const assetPositions = record.assetPositions;\n if (!Array.isArray(assetPositions)) {\n throw new Error(\"Hyperliquid clearinghouseState missing assetPositions\");\n }\n\n const positions = parsePositions(assetPositions);\n const marginSummary =\n record.marginSummary === undefined || record.marginSummary === null\n ? null\n : asRecord(record.marginSummary, \"Hyperliquid marginSummary\");\n const withdrawable = readOptionalString(record, \"withdrawable\");\n\n return {\n positions,\n summary: parseAccountSummary(positions, marginSummary, withdrawable),\n };\n}\n\nfunction parseOrders(value: unknown): HyperliquidOrder[] {\n if (!Array.isArray(value)) {\n throw new Error(\"Hyperliquid openOrders response must be an array\");\n }\n\n return value.map((entry) => {\n const item = asRecord(entry, \"Hyperliquid open order\");\n return {\n coin: readRequiredString(item, \"coin\"),\n side: readRequiredString(item, \"side\"),\n limitPx: readRequiredString(item, \"limitPx\"),\n size: readRequiredString(item, \"sz\"),\n oid: readRequiredNumber(item, \"oid\"),\n timestamp: readRequiredNumber(item, \"timestamp\"),\n reduceOnly: readOptionalBoolean(item, \"reduceOnly\") ?? false,\n orderType: readOptionalString(item, \"orderType\"),\n tif: readOptionalString(item, \"tif\"),\n cloid: readOptionalString(item, \"cloid\"),\n };\n });\n}\n\nfunction asRecord(value: unknown, label: string): Record<string, unknown> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new Error(`${label} must be an object`);\n }\n return value as Record<string, unknown>;\n}\n\nfunction readRequiredString(\n value: Record<string, unknown>,\n key: string,\n): string {\n const field = value[key];\n if (typeof field !== \"string\") {\n throw new Error(`${key} must be a string`);\n }\n return field;\n}\n\nfunction readOptionalString(\n value: Record<string, unknown>,\n key: string,\n): string | null {\n const field = value[key];\n return typeof field === \"string\" ? field : null;\n}\n\nfunction readRequiredNumber(\n value: Record<string, unknown>,\n key: string,\n): number {\n const field = value[key];\n if (typeof field !== \"number\" || !Number.isFinite(field)) {\n throw new Error(`${key} must be a finite number`);\n }\n return field;\n}\n\nfunction readOptionalNumber(\n value: Record<string, unknown>,\n key: string,\n): number | null {\n const field = value[key];\n return typeof field === \"number\" && Number.isFinite(field) ? field : null;\n}\n\nfunction readOptionalBoolean(\n value: Record<string, unknown>,\n key: string,\n): boolean | null {\n const field = value[key];\n return typeof field === \"boolean\" ? field : null;\n}\n\nfunction describeError(error: unknown): { message: string } {\n if (error instanceof Error) {\n return { message: error.message };\n }\n return { message: String(error) };\n}\n"],"mappings":"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","names":[]}
package/dist/ui.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export { interact } from "./HyperliquidAppView.interact.ts";
2
+ export * from "./HyperliquidAppView.tsx";
3
+ export { HyperliquidView } from "./HyperliquidView.tsx";
4
+ export { HYPERLIQUID_APP_NAME, hyperliquidApp } from "./hyperliquid-app.ts";
5
+ export * from "./useHyperliquidState.ts";
6
+ //# sourceMappingURL=ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAC5D,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC5E,cAAc,0BAA0B,CAAC"}
package/dist/ui.js ADDED
@@ -0,0 +1,12 @@
1
+ import { interact } from "./HyperliquidAppView.interact.js";
2
+ export * from "./HyperliquidAppView.js";
3
+ import { HyperliquidView } from "./HyperliquidView.js";
4
+ import { HYPERLIQUID_APP_NAME, hyperliquidApp } from "./hyperliquid-app.js";
5
+ export * from "./useHyperliquidState.js";
6
+ export {
7
+ HYPERLIQUID_APP_NAME,
8
+ HyperliquidView,
9
+ hyperliquidApp,
10
+ interact
11
+ };
12
+ //# sourceMappingURL=ui.js.map
package/dist/ui.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui.ts"],"sourcesContent":["export { interact } from \"./HyperliquidAppView.interact.js\";\nexport * from \"./HyperliquidAppView.js\";\nexport { HyperliquidView } from \"./HyperliquidView.js\";\nexport { HYPERLIQUID_APP_NAME, hyperliquidApp } from \"./hyperliquid-app.js\";\nexport * from \"./useHyperliquidState.js\";\n"],"mappings":"AAAA,SAAS,gBAAgB;AACzB,cAAc;AACd,SAAS,uBAAuB;AAChC,SAAS,sBAAsB,sBAAsB;AACrD,cAAc;","names":[]}
@@ -0,0 +1,20 @@
1
+ import "./client";
2
+ import type { HyperliquidMarketsResponse, HyperliquidOrdersResponse, HyperliquidPositionsResponse, HyperliquidStatusResponse } from "./hyperliquid-contracts";
3
+ export interface HyperliquidState {
4
+ status: HyperliquidStatusResponse | null;
5
+ markets: HyperliquidMarketsResponse | null;
6
+ positions: HyperliquidPositionsResponse | null;
7
+ orders: HyperliquidOrdersResponse | null;
8
+ loading: boolean;
9
+ error: string | null;
10
+ /**
11
+ * True when the Hyperliquid app routes are not mounted on this surface (the
12
+ * read endpoints 404/503) — e.g. the mobile bundle that ships without the
13
+ * app-route plugin. The view degrades to a clean "unavailable" state instead
14
+ * of surfacing the raw fetch error.
15
+ */
16
+ unavailable: boolean;
17
+ refresh: () => Promise<void>;
18
+ }
19
+ export declare function useHyperliquidState(): HyperliquidState;
20
+ //# sourceMappingURL=useHyperliquidState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useHyperliquidState.d.ts","sourceRoot":"","sources":["../src/useHyperliquidState.ts"],"names":[],"mappings":"AAGA,OAAO,UAAU,CAAC;AAElB,OAAO,KAAK,EACV,0BAA0B,EAC1B,yBAAyB,EACzB,4BAA4B,EAC5B,yBAAyB,EAC1B,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,yBAAyB,GAAG,IAAI,CAAC;IACzC,OAAO,EAAE,0BAA0B,GAAG,IAAI,CAAC;IAC3C,SAAS,EAAE,4BAA4B,GAAG,IAAI,CAAC;IAC/C,MAAM,EAAE,yBAAyB,GAAG,IAAI,CAAC;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB;;;;;OAKG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,wBAAgB,mBAAmB,IAAI,gBAAgB,CA6EtD"}