@vtxmacro/cli 2026.9.55 → 2026.9.56
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/bin/vtx-service-bootstrap.js +23 -1
- package/bin/vtx-service-launcher.js +22 -0
- package/bin/vtx.js +344 -228
- package/package.json +1 -1
|
@@ -16,7 +16,7 @@ import { fileURLToPath } from "node:url";
|
|
|
16
16
|
// agent-cli-release.json
|
|
17
17
|
var agent_cli_release_default = {
|
|
18
18
|
package_name: "@vtxmacro/cli",
|
|
19
|
-
package_version: "2026.9.
|
|
19
|
+
package_version: "2026.9.56",
|
|
20
20
|
codex_package_name: "@openai/codex",
|
|
21
21
|
codex_version: "0.155.0",
|
|
22
22
|
copilot_sdk_package_name: "@github/copilot-sdk",
|
|
@@ -296,6 +296,28 @@ var runtime_policy_generated_default = {
|
|
|
296
296
|
apiWallets: 20
|
|
297
297
|
},
|
|
298
298
|
exchange_action_batch_size: 40
|
|
299
|
+
},
|
|
300
|
+
public_recovery: {
|
|
301
|
+
fallback_initial_seconds: 2,
|
|
302
|
+
fallback_max_seconds: 60,
|
|
303
|
+
permit_lease_seconds: 60,
|
|
304
|
+
recovery_initial_concurrency: 1,
|
|
305
|
+
recovery_max_concurrency: 8,
|
|
306
|
+
recovery_successes_per_step: 4,
|
|
307
|
+
recovery_min_spacing_ms: 100,
|
|
308
|
+
queue_poll_ms: 50,
|
|
309
|
+
recovery_queue_wait_seconds: 10,
|
|
310
|
+
recovery_quiet_seconds: 30
|
|
311
|
+
},
|
|
312
|
+
http: {
|
|
313
|
+
exchange: {
|
|
314
|
+
request_timeout_seconds: 10,
|
|
315
|
+
pool_timeout_seconds: 10
|
|
316
|
+
},
|
|
317
|
+
public_critical: {
|
|
318
|
+
request_timeout_seconds: 10,
|
|
319
|
+
pool_timeout_seconds: 5
|
|
320
|
+
}
|
|
299
321
|
}
|
|
300
322
|
}
|
|
301
323
|
}
|
|
@@ -179,6 +179,28 @@ var runtime_policy_generated_default = {
|
|
|
179
179
|
apiWallets: 20
|
|
180
180
|
},
|
|
181
181
|
exchange_action_batch_size: 40
|
|
182
|
+
},
|
|
183
|
+
public_recovery: {
|
|
184
|
+
fallback_initial_seconds: 2,
|
|
185
|
+
fallback_max_seconds: 60,
|
|
186
|
+
permit_lease_seconds: 60,
|
|
187
|
+
recovery_initial_concurrency: 1,
|
|
188
|
+
recovery_max_concurrency: 8,
|
|
189
|
+
recovery_successes_per_step: 4,
|
|
190
|
+
recovery_min_spacing_ms: 100,
|
|
191
|
+
queue_poll_ms: 50,
|
|
192
|
+
recovery_queue_wait_seconds: 10,
|
|
193
|
+
recovery_quiet_seconds: 30
|
|
194
|
+
},
|
|
195
|
+
http: {
|
|
196
|
+
exchange: {
|
|
197
|
+
request_timeout_seconds: 10,
|
|
198
|
+
pool_timeout_seconds: 10
|
|
199
|
+
},
|
|
200
|
+
public_critical: {
|
|
201
|
+
request_timeout_seconds: 10,
|
|
202
|
+
pool_timeout_seconds: 5
|
|
203
|
+
}
|
|
182
204
|
}
|
|
183
205
|
}
|
|
184
206
|
}
|
package/bin/vtx.js
CHANGED
|
@@ -77,7 +77,7 @@ var init_agent_cli_release = __esm({
|
|
|
77
77
|
"agent-cli-release.json"() {
|
|
78
78
|
agent_cli_release_default = {
|
|
79
79
|
package_name: "@vtxmacro/cli",
|
|
80
|
-
package_version: "2026.9.
|
|
80
|
+
package_version: "2026.9.56",
|
|
81
81
|
codex_package_name: "@openai/codex",
|
|
82
82
|
codex_version: "0.155.0",
|
|
83
83
|
copilot_sdk_package_name: "@github/copilot-sdk",
|
|
@@ -20637,6 +20637,28 @@ var init_runtime_policy_generated = __esm({
|
|
|
20637
20637
|
apiWallets: 20
|
|
20638
20638
|
},
|
|
20639
20639
|
exchange_action_batch_size: 40
|
|
20640
|
+
},
|
|
20641
|
+
public_recovery: {
|
|
20642
|
+
fallback_initial_seconds: 2,
|
|
20643
|
+
fallback_max_seconds: 60,
|
|
20644
|
+
permit_lease_seconds: 60,
|
|
20645
|
+
recovery_initial_concurrency: 1,
|
|
20646
|
+
recovery_max_concurrency: 8,
|
|
20647
|
+
recovery_successes_per_step: 4,
|
|
20648
|
+
recovery_min_spacing_ms: 100,
|
|
20649
|
+
queue_poll_ms: 50,
|
|
20650
|
+
recovery_queue_wait_seconds: 10,
|
|
20651
|
+
recovery_quiet_seconds: 30
|
|
20652
|
+
},
|
|
20653
|
+
http: {
|
|
20654
|
+
exchange: {
|
|
20655
|
+
request_timeout_seconds: 10,
|
|
20656
|
+
pool_timeout_seconds: 10
|
|
20657
|
+
},
|
|
20658
|
+
public_critical: {
|
|
20659
|
+
request_timeout_seconds: 10,
|
|
20660
|
+
pool_timeout_seconds: 5
|
|
20661
|
+
}
|
|
20640
20662
|
}
|
|
20641
20663
|
}
|
|
20642
20664
|
}
|
|
@@ -42675,6 +42697,28 @@ var init_runtime_policy_generated2 = __esm({
|
|
|
42675
42697
|
apiWallets: 20
|
|
42676
42698
|
},
|
|
42677
42699
|
exchange_action_batch_size: 40
|
|
42700
|
+
},
|
|
42701
|
+
public_recovery: {
|
|
42702
|
+
fallback_initial_seconds: 2,
|
|
42703
|
+
fallback_max_seconds: 60,
|
|
42704
|
+
permit_lease_seconds: 60,
|
|
42705
|
+
recovery_initial_concurrency: 1,
|
|
42706
|
+
recovery_max_concurrency: 8,
|
|
42707
|
+
recovery_successes_per_step: 4,
|
|
42708
|
+
recovery_min_spacing_ms: 100,
|
|
42709
|
+
queue_poll_ms: 50,
|
|
42710
|
+
recovery_queue_wait_seconds: 10,
|
|
42711
|
+
recovery_quiet_seconds: 30
|
|
42712
|
+
},
|
|
42713
|
+
http: {
|
|
42714
|
+
exchange: {
|
|
42715
|
+
request_timeout_seconds: 10,
|
|
42716
|
+
pool_timeout_seconds: 10
|
|
42717
|
+
},
|
|
42718
|
+
public_critical: {
|
|
42719
|
+
request_timeout_seconds: 10,
|
|
42720
|
+
pool_timeout_seconds: 5
|
|
42721
|
+
}
|
|
42678
42722
|
}
|
|
42679
42723
|
}
|
|
42680
42724
|
}
|
|
@@ -48616,7 +48660,7 @@ var init_runtime_redaction = __esm({
|
|
|
48616
48660
|
});
|
|
48617
48661
|
|
|
48618
48662
|
// lib/runtime/hyperliquid-public-read.ts
|
|
48619
|
-
var policy, weights, budgets, unpersistedBudgets, cache, pending2, PREFIX, abortError2, checkAbort, wait, storage, loadBudget, saveBudget, withBudgetLock, HyperliquidPublicReadError, cooldownError, admit, cooldown, cacheTtlMs, eligibleCache, reserveHyperliquidPublicReads, releaseHyperliquidPublicReadReservation, admitHyperliquidExchangeRequest, recordHyperliquidExchangeResponse, readHyperliquidPublicInfo;
|
|
48663
|
+
var policy, weights, recoveryPolicy, budgets, unpersistedBudgets, cache, pending2, PREFIX, abortError2, checkAbort, wait, storage, loadBudget, saveBudget, withBudgetLock, HyperliquidPublicReadError, getHyperliquidPublicReadBudget, cooldownError, recoveryWaitError, fallbackDelayMs, admit, cooldown, finishHyperliquidRecoveryRequest, assertHyperliquidRecoveryDispatch, cacheTtlMs, eligibleCache, reserveHyperliquidPublicReads, releaseHyperliquidPublicReadReservation, admitHyperliquidExchangeRequest, recordHyperliquidExchangeResponse, readHyperliquidPublicInfo;
|
|
48620
48664
|
var init_hyperliquid_public_read = __esm({
|
|
48621
48665
|
"lib/runtime/hyperliquid-public-read.ts"() {
|
|
48622
48666
|
"use strict";
|
|
@@ -48627,6 +48671,7 @@ var init_hyperliquid_public_read = __esm({
|
|
|
48627
48671
|
init_runtime_policy_generated();
|
|
48628
48672
|
policy = runtime_policy_generated_default.exchange.hyperliquid.client_public_read_budget;
|
|
48629
48673
|
weights = runtime_policy_generated_default.exchange.hyperliquid.read_budget.weights;
|
|
48674
|
+
recoveryPolicy = runtime_policy_generated_default.exchange.hyperliquid.public_recovery;
|
|
48630
48675
|
budgets = /* @__PURE__ */ new Map();
|
|
48631
48676
|
unpersistedBudgets = /* @__PURE__ */ new Set();
|
|
48632
48677
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -48684,7 +48729,15 @@ var init_hyperliquid_public_read = __esm({
|
|
|
48684
48729
|
withBudgetLock = async (key, signal, work) => {
|
|
48685
48730
|
checkAbort(signal);
|
|
48686
48731
|
if (typeof navigator !== "undefined" && navigator.locks?.request) {
|
|
48687
|
-
|
|
48732
|
+
const result2 = await navigator.locks.request(key, { ...signal ? { signal } : {} }, () => {
|
|
48733
|
+
try {
|
|
48734
|
+
return { ok: true, value: work() };
|
|
48735
|
+
} catch (error48) {
|
|
48736
|
+
return { ok: false, error: error48 };
|
|
48737
|
+
}
|
|
48738
|
+
});
|
|
48739
|
+
if (!result2.ok) throw result2.error;
|
|
48740
|
+
return result2.value;
|
|
48688
48741
|
}
|
|
48689
48742
|
return work();
|
|
48690
48743
|
};
|
|
@@ -48701,6 +48754,15 @@ var init_hyperliquid_public_read = __esm({
|
|
|
48701
48754
|
this.name = "HyperliquidPublicReadError";
|
|
48702
48755
|
}
|
|
48703
48756
|
};
|
|
48757
|
+
getHyperliquidPublicReadBudget = (endpoint) => {
|
|
48758
|
+
const budget = loadBudget(`${PREFIX}${endpoint.replace(/\/$/, "")}`);
|
|
48759
|
+
return {
|
|
48760
|
+
usedWeight: budget.reservations.filter((r) => r.at > Date.now() - policy.window_seconds * 1e3).reduce((sum, r) => sum + r.weight, 0),
|
|
48761
|
+
maxWeight: policy.max_weight,
|
|
48762
|
+
windowSeconds: policy.window_seconds,
|
|
48763
|
+
cooldownUntilMs: budget.cooldownUntil
|
|
48764
|
+
};
|
|
48765
|
+
};
|
|
48704
48766
|
cooldownError = (requestType, until) => new HyperliquidPublicReadError(
|
|
48705
48767
|
"public_cooldown_active",
|
|
48706
48768
|
"Hyperliquid public request cooldown is active.",
|
|
@@ -48708,48 +48770,129 @@ var init_hyperliquid_public_read = __esm({
|
|
|
48708
48770
|
void 0,
|
|
48709
48771
|
Math.max(0, until - Date.now())
|
|
48710
48772
|
);
|
|
48711
|
-
|
|
48773
|
+
recoveryWaitError = (requestType) => new HyperliquidPublicReadError(
|
|
48774
|
+
"public_recovery_wait",
|
|
48775
|
+
"Hyperliquid provider recovery could not dispatch before the request deadline.",
|
|
48776
|
+
requestType
|
|
48777
|
+
);
|
|
48778
|
+
fallbackDelayMs = (failures) => Math.min(
|
|
48779
|
+
recoveryPolicy.fallback_max_seconds * 1e3,
|
|
48780
|
+
recoveryPolicy.fallback_initial_seconds * 1e3 * 2 ** Math.min(30, Math.max(0, failures - 1)) * (0.5 + Math.random())
|
|
48781
|
+
);
|
|
48782
|
+
admit = async (apiUrl, requestType, signal, weightOverride, deadlineMs) => {
|
|
48712
48783
|
const key = `${PREFIX}${apiUrl}`;
|
|
48713
|
-
const weight =
|
|
48714
|
-
|
|
48715
|
-
|
|
48716
|
-
|
|
48717
|
-
|
|
48718
|
-
|
|
48719
|
-
|
|
48720
|
-
|
|
48721
|
-
|
|
48722
|
-
|
|
48723
|
-
|
|
48724
|
-
|
|
48725
|
-
|
|
48784
|
+
const weight = weightOverride ?? weights[requestType] ?? policy.default_request_weight;
|
|
48785
|
+
const ticket = crypto.randomUUID();
|
|
48786
|
+
const deadline = Math.min(deadlineMs ?? Infinity, Date.now() + recoveryPolicy.recovery_queue_wait_seconds * 1e3);
|
|
48787
|
+
let admitted = false;
|
|
48788
|
+
try {
|
|
48789
|
+
for (; ; ) {
|
|
48790
|
+
checkAbort(signal);
|
|
48791
|
+
if (deadlineMs != null && Date.now() >= deadlineMs) throw recoveryWaitError(requestType);
|
|
48792
|
+
const result2 = await withBudgetLock(key, signal, () => {
|
|
48793
|
+
const now = Date.now();
|
|
48794
|
+
const budget = loadBudget(key);
|
|
48795
|
+
if (budget.cooldownUntil > now) throw cooldownError(requestType, budget.cooldownUntil);
|
|
48796
|
+
const recovery = budget.recovery;
|
|
48797
|
+
let permit = null;
|
|
48798
|
+
if (recovery) {
|
|
48799
|
+
recovery.active = recovery.active.filter((entry) => entry.expiresAt > now);
|
|
48800
|
+
recovery.queue = recovery.queue.filter((entry) => entry.expiresAt > now);
|
|
48801
|
+
if (now >= deadline) throw recoveryWaitError(requestType);
|
|
48802
|
+
if (!recovery.queue.some((entry) => entry.id === ticket)) recovery.queue.push({ id: ticket, expiresAt: deadline });
|
|
48803
|
+
if (recovery.queue[0]?.id !== ticket || recovery.active.length >= recovery.concurrency || recovery.nextAt > now) {
|
|
48804
|
+
saveBudget(key, budget);
|
|
48805
|
+
return { ready: false, permit: null };
|
|
48806
|
+
}
|
|
48807
|
+
recovery.queue.shift();
|
|
48808
|
+
const expiresAt = now + recoveryPolicy.permit_lease_seconds * 1e3;
|
|
48809
|
+
recovery.active.push({ id: ticket, expiresAt });
|
|
48810
|
+
recovery.nextAt = now + recoveryPolicy.recovery_min_spacing_ms;
|
|
48811
|
+
permit = { endpoint: apiUrl, id: ticket, generation: recovery.generation, expiresAt };
|
|
48812
|
+
}
|
|
48813
|
+
budget.reservations = budget.reservations.filter((entry) => entry.at > now - policy.window_seconds * 1e3);
|
|
48814
|
+
budget.reservations.push({ at: now, weight });
|
|
48726
48815
|
saveBudget(key, budget);
|
|
48727
|
-
return {
|
|
48816
|
+
return { ready: true, permit };
|
|
48817
|
+
});
|
|
48818
|
+
if (result2.ready) {
|
|
48819
|
+
admitted = true;
|
|
48820
|
+
return result2.permit;
|
|
48728
48821
|
}
|
|
48729
|
-
|
|
48730
|
-
|
|
48731
|
-
|
|
48822
|
+
await wait(Math.min(recoveryPolicy.queue_poll_ms, Math.max(1, deadline - Date.now())), signal);
|
|
48823
|
+
}
|
|
48824
|
+
} finally {
|
|
48825
|
+
if (!admitted) await withBudgetLock(key, void 0, () => {
|
|
48826
|
+
const budget = loadBudget(key);
|
|
48827
|
+
if (budget.recovery) {
|
|
48828
|
+
budget.recovery.queue = budget.recovery.queue.filter((entry) => entry.id !== ticket);
|
|
48829
|
+
saveBudget(key, budget);
|
|
48732
48830
|
}
|
|
48733
|
-
throw new Error("Invalid Hyperliquid public read budget.");
|
|
48734
48831
|
});
|
|
48735
|
-
if (!delay2) return;
|
|
48736
|
-
if (bundleWeight != null || deadlineMs != null && Date.now() + delay2 >= deadlineMs) {
|
|
48737
|
-
throw new HyperliquidPublicReadError("public_budget_exhausted", "Hyperliquid local public request allowance is exhausted.", requestType, void 0, delay2, weight, usedWeight, policy.max_weight);
|
|
48738
|
-
}
|
|
48739
|
-
await wait(delay2, signal);
|
|
48740
48832
|
}
|
|
48741
48833
|
};
|
|
48742
48834
|
cooldown = async (apiUrl, retryAfter) => {
|
|
48743
48835
|
const key = `${PREFIX}${apiUrl}`;
|
|
48744
48836
|
await withBudgetLock(key, void 0, () => {
|
|
48745
48837
|
const now = Date.now();
|
|
48746
|
-
const seconds = retryAfter == null ? NaN : Number(retryAfter);
|
|
48747
|
-
const providerUntil = Number.isFinite(seconds) ? now + seconds * 1e3 : Date.parse(retryAfter ?? "");
|
|
48748
48838
|
const budget = loadBudget(key);
|
|
48749
|
-
budget.
|
|
48839
|
+
if (!budget.recovery && now - (budget.lastFailure ?? 0) >= recoveryPolicy.recovery_quiet_seconds * 1e3) budget.failures = 0;
|
|
48840
|
+
budget.failures = (budget.failures ?? 0) + 1;
|
|
48841
|
+
const trimmed = retryAfter?.trim() ?? "";
|
|
48842
|
+
const seconds = trimmed !== "" ? Number(trimmed) : NaN;
|
|
48843
|
+
const providerUntil = Number.isFinite(seconds) && seconds >= 0 ? now + seconds * 1e3 : trimmed && !Number.isFinite(seconds) ? Date.parse(trimmed) : NaN;
|
|
48844
|
+
const until = Number.isFinite(providerUntil) ? Math.max(now, Number(providerUntil)) : now + fallbackDelayMs(budget.failures);
|
|
48845
|
+
budget.cooldownUntil = Math.max(budget.cooldownUntil, until);
|
|
48846
|
+
budget.lastFailure = now;
|
|
48847
|
+
budget.recovery = {
|
|
48848
|
+
generation: crypto.randomUUID(),
|
|
48849
|
+
concurrency: recoveryPolicy.recovery_initial_concurrency,
|
|
48850
|
+
successes: 0,
|
|
48851
|
+
nextAt: budget.cooldownUntil,
|
|
48852
|
+
queue: budget.recovery?.queue ?? [],
|
|
48853
|
+
active: []
|
|
48854
|
+
};
|
|
48855
|
+
saveBudget(key, budget);
|
|
48856
|
+
});
|
|
48857
|
+
};
|
|
48858
|
+
finishHyperliquidRecoveryRequest = async (permit, outcome) => {
|
|
48859
|
+
if (!permit) return;
|
|
48860
|
+
const key = `${PREFIX}${permit.endpoint}`;
|
|
48861
|
+
await withBudgetLock(key, void 0, () => {
|
|
48862
|
+
const budget = loadBudget(key);
|
|
48863
|
+
const recovery = budget.recovery;
|
|
48864
|
+
if (!recovery || recovery.generation !== permit.generation) return;
|
|
48865
|
+
const now = Date.now();
|
|
48866
|
+
const member = recovery.active.find((entry) => entry.id === permit.id);
|
|
48867
|
+
recovery.active = recovery.active.filter((entry) => entry.id !== permit.id);
|
|
48868
|
+
if (member && member.expiresAt > now) {
|
|
48869
|
+
if (outcome === "success") {
|
|
48870
|
+
recovery.successes += 1;
|
|
48871
|
+
if (recovery.successes >= recoveryPolicy.recovery_successes_per_step) {
|
|
48872
|
+
if (recovery.concurrency >= recoveryPolicy.recovery_max_concurrency) {
|
|
48873
|
+
if (recovery.queue.length === 0 && recovery.active.length === 0) delete budget.recovery;
|
|
48874
|
+
} else {
|
|
48875
|
+
recovery.concurrency = Math.min(recoveryPolicy.recovery_max_concurrency, recovery.concurrency * 2);
|
|
48876
|
+
recovery.successes = 0;
|
|
48877
|
+
}
|
|
48878
|
+
}
|
|
48879
|
+
} else if (outcome === "failure") {
|
|
48880
|
+
recovery.successes = 0;
|
|
48881
|
+
recovery.concurrency = recoveryPolicy.recovery_initial_concurrency;
|
|
48882
|
+
recovery.nextAt = Math.max(recovery.nextAt, now + fallbackDelayMs(budget.failures ?? 1));
|
|
48883
|
+
}
|
|
48884
|
+
}
|
|
48750
48885
|
saveBudget(key, budget);
|
|
48751
48886
|
});
|
|
48752
48887
|
};
|
|
48888
|
+
assertHyperliquidRecoveryDispatch = (endpoint, permit, requestType) => {
|
|
48889
|
+
const budget = loadBudget(`${PREFIX}${endpoint.replace(/\/$/, "")}`);
|
|
48890
|
+
if (budget.cooldownUntil > Date.now()) throw cooldownError(requestType, budget.cooldownUntil);
|
|
48891
|
+
if (permit && (permit.expiresAt <= Date.now() || budget.recovery && (budget.recovery.generation !== permit.generation || !budget.recovery.active.some((entry) => entry.id === permit.id && entry.expiresAt > Date.now())))) {
|
|
48892
|
+
throw recoveryWaitError(requestType);
|
|
48893
|
+
}
|
|
48894
|
+
if (!permit && budget.recovery) throw recoveryWaitError(requestType);
|
|
48895
|
+
};
|
|
48753
48896
|
cacheTtlMs = (body, options) => {
|
|
48754
48897
|
const requestType = String(body.type);
|
|
48755
48898
|
return (["meta", "spotMeta", "perpDexs"].includes(requestType) ? policy.metadata_ttl_seconds : requestType === "userFees" ? policy.user_fees_ttl_seconds : options.cacheAccountMode && ["userAbstraction", "userDexAbstraction"].includes(requestType) ? policy.account_mode_ttl_seconds : 0) * 1e3;
|
|
@@ -48761,47 +48904,26 @@ var init_hyperliquid_public_read = __esm({
|
|
|
48761
48904
|
return ttl > 0 && existing && Date.now() >= existing.fetchedAtMs && horizon - existing.fetchedAtMs < ttl ? existing : void 0;
|
|
48762
48905
|
};
|
|
48763
48906
|
reserveHyperliquidPublicReads = async (endpoint, bodies, signal, options = {}) => {
|
|
48907
|
+
checkAbort(signal);
|
|
48764
48908
|
const apiUrl = endpoint.replace(/\/$/, "");
|
|
48765
48909
|
const cached2 = /* @__PURE__ */ new Map();
|
|
48766
|
-
const remaining = /* @__PURE__ */ new Map();
|
|
48767
|
-
let weight = 0;
|
|
48768
48910
|
for (const body of bodies) {
|
|
48769
|
-
const key = JSON.stringify(body);
|
|
48770
48911
|
const hit = eligibleCache(apiUrl, body, options);
|
|
48771
|
-
if (hit)
|
|
48772
|
-
cached2.set(key, hit);
|
|
48773
|
-
continue;
|
|
48774
|
-
}
|
|
48775
|
-
remaining.set(key, (remaining.get(key) ?? 0) + 1);
|
|
48776
|
-
weight += weights[String(body.type)] ?? policy.default_request_weight;
|
|
48912
|
+
if (hit) cached2.set(JSON.stringify(body), hit);
|
|
48777
48913
|
}
|
|
48778
|
-
|
|
48779
|
-
const admittedAtMs = Date.now();
|
|
48780
|
-
if (weight) await admit(apiUrl, "bundle", signal, weight, id2, options.cacheValidUntilMs);
|
|
48781
|
-
return { id: id2, closed: false, endpoint: apiUrl, expiresAtMs: admittedAtMs + policy.window_seconds * 1e3, remaining, cached: cached2, cacheValidUntilMs: options.cacheValidUntilMs };
|
|
48914
|
+
return { closed: false, endpoint: apiUrl, cached: cached2, cacheValidUntilMs: options.cacheValidUntilMs };
|
|
48782
48915
|
};
|
|
48783
48916
|
releaseHyperliquidPublicReadReservation = async (reservation) => {
|
|
48784
48917
|
reservation.closed = true;
|
|
48785
|
-
const key = `${PREFIX}${reservation.endpoint}`;
|
|
48786
|
-
await withBudgetLock(key, void 0, () => {
|
|
48787
|
-
const budget = loadBudget(key);
|
|
48788
|
-
const row = budget.reservations.find((entry) => entry.id === reservation.id);
|
|
48789
|
-
if (row) {
|
|
48790
|
-
const unused = [...reservation.remaining].reduce((sum, [body, count4]) => sum + (weights[String(JSON.parse(body).type)] ?? policy.default_request_weight) * count4, 0);
|
|
48791
|
-
row.weight = Math.max(0, row.weight - unused);
|
|
48792
|
-
budget.reservations = budget.reservations.filter((entry) => entry.weight > 0);
|
|
48793
|
-
saveBudget(key, budget);
|
|
48794
|
-
}
|
|
48795
|
-
reservation.remaining.clear();
|
|
48796
|
-
});
|
|
48797
48918
|
};
|
|
48798
48919
|
admitHyperliquidExchangeRequest = async (endpoint, action, signal) => {
|
|
48799
48920
|
const batchLength = Math.max(0, ...[action.orders, action.cancels, action.modifies].filter(Array.isArray).map((value) => value.length));
|
|
48800
48921
|
const weight = weights.exchange + Math.floor(batchLength / runtime_policy_generated_default.exchange.hyperliquid.read_budget.exchange_action_batch_size);
|
|
48801
|
-
|
|
48922
|
+
return admit(endpoint.replace(/\/$/, ""), "exchange", signal, weight);
|
|
48802
48923
|
};
|
|
48803
|
-
recordHyperliquidExchangeResponse = async (endpoint, response) => {
|
|
48924
|
+
recordHyperliquidExchangeResponse = async (endpoint, response, permit) => {
|
|
48804
48925
|
if (response.status === 429) await cooldown(endpoint.replace(/\/$/, ""), response.headers.get("Retry-After"));
|
|
48926
|
+
await finishHyperliquidRecoveryRequest(permit, response.status < 400 ? "success" : "failure");
|
|
48805
48927
|
};
|
|
48806
48928
|
readHyperliquidPublicInfo = async (endpoint, body, options = {}) => {
|
|
48807
48929
|
const apiUrl = endpoint.replace(/\/$/, "");
|
|
@@ -48810,71 +48932,101 @@ var init_hyperliquid_public_read = __esm({
|
|
|
48810
48932
|
const ttlMs = cacheTtlMs(body, cacheOptions);
|
|
48811
48933
|
const key = `${apiUrl}:${JSON.stringify(body)}`;
|
|
48812
48934
|
checkAbort(options.signal);
|
|
48813
|
-
|
|
48814
|
-
|
|
48815
|
-
|
|
48816
|
-
|
|
48817
|
-
|
|
48818
|
-
|
|
48819
|
-
|
|
48820
|
-
|
|
48821
|
-
|
|
48822
|
-
|
|
48823
|
-
|
|
48824
|
-
|
|
48825
|
-
|
|
48826
|
-
|
|
48827
|
-
|
|
48828
|
-
|
|
48829
|
-
|
|
48830
|
-
|
|
48831
|
-
|
|
48832
|
-
|
|
48935
|
+
const transportPolicy = runtime_policy_generated_default.exchange.hyperliquid.http.public_critical;
|
|
48936
|
+
const deadline = Math.min(
|
|
48937
|
+
Date.now() + (transportPolicy.request_timeout_seconds + transportPolicy.pool_timeout_seconds) * 1e3,
|
|
48938
|
+
options.deadlineMs ?? Infinity,
|
|
48939
|
+
options.reservation?.cacheValidUntilMs ?? Infinity
|
|
48940
|
+
);
|
|
48941
|
+
const controller = new AbortController();
|
|
48942
|
+
const signal = controller.signal;
|
|
48943
|
+
const callerAborted = () => controller.abort(abortError2(options.signal));
|
|
48944
|
+
options.signal?.addEventListener("abort", callerAborted, { once: true });
|
|
48945
|
+
let timer;
|
|
48946
|
+
const armDeadline = (until) => {
|
|
48947
|
+
clearTimeout(timer);
|
|
48948
|
+
const timeout = () => controller.abort(new DOMException("Hyperliquid public request timed out.", "TimeoutError"));
|
|
48949
|
+
if (until <= Date.now()) timeout();
|
|
48950
|
+
else timer = setTimeout(timeout, until - Date.now());
|
|
48951
|
+
};
|
|
48952
|
+
armDeadline(deadline);
|
|
48953
|
+
let permit = null;
|
|
48954
|
+
let outcome = "cancelled";
|
|
48833
48955
|
let settled;
|
|
48834
|
-
|
|
48835
|
-
settled = resolve13;
|
|
48836
|
-
}));
|
|
48956
|
+
let acquiring = false;
|
|
48837
48957
|
try {
|
|
48838
|
-
|
|
48839
|
-
|
|
48840
|
-
|
|
48841
|
-
|
|
48842
|
-
|
|
48843
|
-
|
|
48844
|
-
if (
|
|
48845
|
-
|
|
48846
|
-
|
|
48847
|
-
|
|
48848
|
-
|
|
48849
|
-
|
|
48850
|
-
|
|
48851
|
-
|
|
48958
|
+
checkAbort(signal);
|
|
48959
|
+
if (ttlMs) {
|
|
48960
|
+
for (; ; ) {
|
|
48961
|
+
const existing = options.reservation?.cached.get(JSON.stringify(body)) ?? eligibleCache(apiUrl, body, cacheOptions);
|
|
48962
|
+
if (existing) return existing;
|
|
48963
|
+
const running = pending2.get(key);
|
|
48964
|
+
if (!running) break;
|
|
48965
|
+
await new Promise((resolve13, reject) => {
|
|
48966
|
+
const aborted2 = () => {
|
|
48967
|
+
signal.removeEventListener("abort", aborted2);
|
|
48968
|
+
reject(abortError2(signal));
|
|
48969
|
+
};
|
|
48970
|
+
signal.addEventListener("abort", aborted2, { once: true });
|
|
48971
|
+
running.then(() => {
|
|
48972
|
+
signal.removeEventListener("abort", aborted2);
|
|
48973
|
+
resolve13();
|
|
48974
|
+
});
|
|
48975
|
+
});
|
|
48976
|
+
checkAbort(signal);
|
|
48977
|
+
}
|
|
48978
|
+
pending2.set(key, new Promise((resolve13) => {
|
|
48979
|
+
settled = resolve13;
|
|
48980
|
+
}));
|
|
48981
|
+
}
|
|
48982
|
+
if (options.reservation?.closed) throw new DOMException("Hyperliquid account read was cancelled.", "AbortError");
|
|
48983
|
+
acquiring = true;
|
|
48984
|
+
permit = await admit(apiUrl, requestType, signal, void 0, deadline);
|
|
48985
|
+
acquiring = false;
|
|
48986
|
+
armDeadline(Math.min(deadline, permit?.expiresAt ?? Infinity));
|
|
48987
|
+
checkAbort(signal);
|
|
48988
|
+
if (options.reservation?.closed) throw new DOMException("Hyperliquid account read was cancelled.", "AbortError");
|
|
48989
|
+
assertHyperliquidRecoveryDispatch(apiUrl, permit, requestType);
|
|
48990
|
+
outcome = "failure";
|
|
48991
|
+
let transportAborted;
|
|
48992
|
+
let response;
|
|
48993
|
+
let payload;
|
|
48994
|
+
try {
|
|
48995
|
+
const aborted2 = new Promise((_resolve, reject) => {
|
|
48996
|
+
transportAborted = () => reject(abortError2(signal));
|
|
48997
|
+
signal.addEventListener("abort", transportAborted, { once: true });
|
|
48852
48998
|
});
|
|
48853
|
-
|
|
48854
|
-
|
|
48855
|
-
|
|
48856
|
-
|
|
48857
|
-
|
|
48858
|
-
|
|
48859
|
-
|
|
48860
|
-
|
|
48861
|
-
|
|
48862
|
-
|
|
48863
|
-
|
|
48864
|
-
|
|
48865
|
-
|
|
48866
|
-
|
|
48867
|
-
|
|
48868
|
-
|
|
48869
|
-
|
|
48999
|
+
const transport = (async () => {
|
|
49000
|
+
const received = await fetch(`${apiUrl}/info`, {
|
|
49001
|
+
method: "POST",
|
|
49002
|
+
headers: { "Content-Type": "application/json" },
|
|
49003
|
+
body: JSON.stringify(body),
|
|
49004
|
+
signal
|
|
49005
|
+
});
|
|
49006
|
+
checkAbort(signal);
|
|
49007
|
+
if (received.status === 429) {
|
|
49008
|
+
await cooldown(apiUrl, received.headers.get("Retry-After"));
|
|
49009
|
+
throw new HyperliquidPublicReadError("public_rate_limited", "Hyperliquid public API returned HTTP 429.", requestType, 429);
|
|
49010
|
+
}
|
|
49011
|
+
const receivedPayload = await received.json().catch((error48) => {
|
|
49012
|
+
if (error48 instanceof SyntaxError) return {};
|
|
49013
|
+
throw error48;
|
|
49014
|
+
});
|
|
49015
|
+
checkAbort(signal);
|
|
49016
|
+
return { response: received, payload: receivedPayload };
|
|
49017
|
+
})();
|
|
49018
|
+
({ response, payload } = await Promise.race([transport, aborted2]));
|
|
49019
|
+
} finally {
|
|
49020
|
+
if (transportAborted) signal.removeEventListener("abort", transportAborted);
|
|
49021
|
+
}
|
|
48870
49022
|
if (!response.ok) {
|
|
48871
49023
|
const detail = sanitizeRuntimeDiagnosticValue(typeof payload?.response === "string" ? payload.response : typeof payload?.detail === "string" ? payload.detail : "");
|
|
48872
|
-
if (response.status === 429) throw new HyperliquidPublicReadError("public_rate_limited", "Hyperliquid public API returned HTTP 429.", requestType, 429);
|
|
48873
49024
|
throw Object.assign(new Error(`Hyperliquid info request failed (${response.status}) request_type=${requestType}.${detail ? ` ${detail}` : ""}`), {
|
|
48874
49025
|
status: response.status,
|
|
48875
49026
|
requestType
|
|
48876
49027
|
});
|
|
48877
49028
|
}
|
|
49029
|
+
outcome = "success";
|
|
48878
49030
|
const result2 = { payload, fetchedAtMs: Date.now() };
|
|
48879
49031
|
if (ttlMs) {
|
|
48880
49032
|
cache.set(key, result2);
|
|
@@ -48882,14 +49034,26 @@ var init_hyperliquid_public_read = __esm({
|
|
|
48882
49034
|
}
|
|
48883
49035
|
return result2;
|
|
48884
49036
|
} catch (error48) {
|
|
48885
|
-
if (options.signal?.aborted
|
|
49037
|
+
if (options.signal?.aborted) {
|
|
49038
|
+
outcome = "cancelled";
|
|
49039
|
+
throw abortError2(options.signal);
|
|
49040
|
+
}
|
|
49041
|
+
if (acquiring && signal.aborted && signal.reason?.name === "TimeoutError") throw recoveryWaitError(requestType);
|
|
49042
|
+
if (error48 instanceof HyperliquidPublicReadError) throw error48;
|
|
48886
49043
|
if (error48 instanceof TypeError) throw new HyperliquidPublicReadError("public_network_error", "Hyperliquid public request network failure.", requestType);
|
|
48887
49044
|
if (error48 instanceof Error && (error48.name === "TimeoutError" || error48.name === "AbortError")) throw new HyperliquidPublicReadError("public_timeout", "Hyperliquid public request timed out.", requestType);
|
|
48888
49045
|
throw error48;
|
|
48889
49046
|
} finally {
|
|
48890
|
-
|
|
48891
|
-
|
|
48892
|
-
|
|
49047
|
+
clearTimeout(timer);
|
|
49048
|
+
options.signal?.removeEventListener("abort", callerAborted);
|
|
49049
|
+
controller.abort();
|
|
49050
|
+
try {
|
|
49051
|
+
await finishHyperliquidRecoveryRequest(permit, outcome);
|
|
49052
|
+
} finally {
|
|
49053
|
+
if (settled) {
|
|
49054
|
+
pending2.delete(key);
|
|
49055
|
+
settled();
|
|
49056
|
+
}
|
|
48893
49057
|
}
|
|
48894
49058
|
}
|
|
48895
49059
|
};
|
|
@@ -49987,7 +50151,7 @@ var init_network_debug = __esm({
|
|
|
49987
50151
|
});
|
|
49988
50152
|
|
|
49989
50153
|
// lib/runtime/hyperliquid-account-state-adapter.ts
|
|
49990
|
-
var unsupportedUserActiveAssetCache, MAX_UNSUPPORTED_USER_ACTIVE_ASSET_CACHE_KEYS, UNSUPPORTED_USER_ACTIVE_ASSET_STORAGE_KEY, USER_FILLS_CACHE_STORAGE_PREFIX, ACCOUNT_STATE_CACHE_STORAGE_PREFIX,
|
|
50154
|
+
var unsupportedUserActiveAssetCache, MAX_UNSUPPORTED_USER_ACTIVE_ASSET_CACHE_KEYS, UNSUPPORTED_USER_ACTIVE_ASSET_STORAGE_KEY, USER_FILLS_CACHE_STORAGE_PREFIX, ACCOUNT_STATE_CACHE_STORAGE_PREFIX, browserUserFillsCache, browserUserFillsInFlight, HYPERLIQUID_USER_FILLS_PROVIDER_PAGE_CAP, browserAccountStateCache, browserAccountStateInFlight, UNSUPPORTED_USER_ACTIVE_ASSET_DETAIL_PATTERNS, unsupportedUserActiveAssetCacheHydrated, hydrateUnsupportedUserActiveAssetCache, persistUnsupportedUserActiveAssetCache, toPositiveFinite, toFinite, firstFiniteNumber, parseFundingUsdcFromInfoPosition, buildActiveAssetCacheKey, buildUserFillsCacheKey, buildUserFillsStorageKey, buildAccountStateCacheKey, buildAccountStateStorageKey, hasActiveInfoRateLimitCooldown, requireNonNegativeConfigSeconds, requireAccountStateCacheConfig, requireUserFillsCacheConfig, normalizeFillSymbol, buildSymbolFilter, filterFillsBySymbols, readBrowserUserFillsCache, writeBrowserUserFillsCache, cloneBrowserAccountStateResult, withAccountStateEvidence, readBrowserAccountStateCache, writeBrowserAccountStateCache, isRateLimitError, createAbortError, waitForSharedBrowserRequest, waitForSharedBrowserUserFills, getBrowserActiveAssetTypeCandidates, normalizeHyperliquidErrorDetail, isUnsupportedUserActiveAssetError, rememberUnsupportedUserActiveAssetKey, parseInfoPositions, requireFinitePromptMetric, requirePromptClearinghouseState, requirePromptSpotState, normalizePerpDexName, listConfiguredPerpDexs, listPerpDexsForAccountState, prefixHip3PositionCoins, aggregateClearinghouseResponses, hasCompletePerpDexAccountMetrics, normalizeBrowserFillToTradeHistory, isPerpFill, awaitAccountReads, fetchHyperliquidInfoPayload, requireHyperliquidApiUrl, requireWalletAddress, parseInfoPositionSnapshot, fetchBrowserAccountState, fetchBrowserAccountStateUncached, fetchBrowserUserFills, fetchBrowserPositionSnapshot;
|
|
49991
50155
|
var init_hyperliquid_account_state_adapter = __esm({
|
|
49992
50156
|
"lib/runtime/hyperliquid-account-state-adapter.ts"() {
|
|
49993
50157
|
"use strict";
|
|
@@ -50008,15 +50172,11 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
50008
50172
|
UNSUPPORTED_USER_ACTIVE_ASSET_STORAGE_KEY = "vtx:hyperliquid:unsupported-user-active-asset:v1";
|
|
50009
50173
|
USER_FILLS_CACHE_STORAGE_PREFIX = "vtx:hyperliquid:user-fills:v1:";
|
|
50010
50174
|
ACCOUNT_STATE_CACHE_STORAGE_PREFIX = "vtx:hyperliquid:account-state:v1:";
|
|
50011
|
-
INFO_RATE_LIMIT_COOLDOWN_STORAGE_PREFIX = "vtx:hyperliquid:info-rate-limit-cooldown:v1:";
|
|
50012
|
-
INFO_RATE_LIMIT_COOLDOWN_MIN_MS = 5e3;
|
|
50013
|
-
INFO_RATE_LIMIT_COOLDOWN_MAX_MS = 6e4;
|
|
50014
50175
|
browserUserFillsCache = /* @__PURE__ */ new Map();
|
|
50015
50176
|
browserUserFillsInFlight = /* @__PURE__ */ new Map();
|
|
50016
50177
|
HYPERLIQUID_USER_FILLS_PROVIDER_PAGE_CAP = 2e3;
|
|
50017
50178
|
browserAccountStateCache = /* @__PURE__ */ new Map();
|
|
50018
50179
|
browserAccountStateInFlight = /* @__PURE__ */ new Map();
|
|
50019
|
-
browserInfoRateLimitCooldowns = /* @__PURE__ */ new Map();
|
|
50020
50180
|
UNSUPPORTED_USER_ACTIVE_ASSET_DETAIL_PATTERNS = [
|
|
50021
50181
|
/unsupported/i,
|
|
50022
50182
|
/not\s+supported/i,
|
|
@@ -50134,93 +50294,7 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
50134
50294
|
buildAccountStateStorageKey = (cacheKey) => {
|
|
50135
50295
|
return `${ACCOUNT_STATE_CACHE_STORAGE_PREFIX}${cacheKey}`;
|
|
50136
50296
|
};
|
|
50137
|
-
|
|
50138
|
-
return String(apiUrl || "").trim().replace(/\/$/, "").toLowerCase();
|
|
50139
|
-
};
|
|
50140
|
-
normalizeInfoRequestType = (requestType) => {
|
|
50141
|
-
return String(requestType || "").trim() || "info";
|
|
50142
|
-
};
|
|
50143
|
-
buildInfoRateLimitCooldownKey = (apiUrl, requestType) => {
|
|
50144
|
-
return [
|
|
50145
|
-
normalizeInfoRateLimitApiUrl(apiUrl),
|
|
50146
|
-
normalizeInfoRequestType(requestType)
|
|
50147
|
-
].join("::");
|
|
50148
|
-
};
|
|
50149
|
-
buildInfoRateLimitCooldownStorageKey = (cooldownKey) => {
|
|
50150
|
-
return `${INFO_RATE_LIMIT_COOLDOWN_STORAGE_PREFIX}${encodeURIComponent(cooldownKey)}`;
|
|
50151
|
-
};
|
|
50152
|
-
readInfoRateLimitCooldownUntilMs = (apiUrl, requestType, nowMs = Date.now()) => {
|
|
50153
|
-
const cooldownKey = buildInfoRateLimitCooldownKey(apiUrl, requestType);
|
|
50154
|
-
const memoryValue = browserInfoRateLimitCooldowns.get(cooldownKey);
|
|
50155
|
-
if (Number.isFinite(memoryValue)) {
|
|
50156
|
-
if (Number(memoryValue) > nowMs) {
|
|
50157
|
-
return Number(memoryValue);
|
|
50158
|
-
}
|
|
50159
|
-
browserInfoRateLimitCooldowns.delete(cooldownKey);
|
|
50160
|
-
}
|
|
50161
|
-
if (typeof window === "undefined" || !window.localStorage) {
|
|
50162
|
-
return 0;
|
|
50163
|
-
}
|
|
50164
|
-
try {
|
|
50165
|
-
const storageKey = buildInfoRateLimitCooldownStorageKey(cooldownKey);
|
|
50166
|
-
const rawValue = window.localStorage.getItem(storageKey);
|
|
50167
|
-
if (!rawValue) {
|
|
50168
|
-
return 0;
|
|
50169
|
-
}
|
|
50170
|
-
const parsed = JSON.parse(rawValue);
|
|
50171
|
-
const untilMs = Number(parsed?.untilMs);
|
|
50172
|
-
if (!Number.isFinite(untilMs) || untilMs <= nowMs) {
|
|
50173
|
-
window.localStorage.removeItem(storageKey);
|
|
50174
|
-
return 0;
|
|
50175
|
-
}
|
|
50176
|
-
browserInfoRateLimitCooldowns.set(cooldownKey, untilMs);
|
|
50177
|
-
return untilMs;
|
|
50178
|
-
} catch {
|
|
50179
|
-
return 0;
|
|
50180
|
-
}
|
|
50181
|
-
};
|
|
50182
|
-
hasActiveInfoRateLimitCooldown = (apiUrl, requestTypes, nowMs = Date.now()) => requestTypes.some((requestType) => readInfoRateLimitCooldownUntilMs(apiUrl, requestType, nowMs) > nowMs);
|
|
50183
|
-
writeInfoRateLimitCooldown = (apiUrl, requestType, staleIf429MaxAgeMs, nowMs = Date.now()) => {
|
|
50184
|
-
if (!Number.isFinite(staleIf429MaxAgeMs) || staleIf429MaxAgeMs <= 0) {
|
|
50185
|
-
return;
|
|
50186
|
-
}
|
|
50187
|
-
const cooldownKey = buildInfoRateLimitCooldownKey(apiUrl, requestType);
|
|
50188
|
-
const cooldownMs = Math.max(
|
|
50189
|
-
INFO_RATE_LIMIT_COOLDOWN_MIN_MS,
|
|
50190
|
-
Math.min(INFO_RATE_LIMIT_COOLDOWN_MAX_MS, staleIf429MaxAgeMs)
|
|
50191
|
-
);
|
|
50192
|
-
const untilMs = nowMs + cooldownMs;
|
|
50193
|
-
browserInfoRateLimitCooldowns.set(cooldownKey, untilMs);
|
|
50194
|
-
if (typeof window === "undefined" || !window.localStorage) {
|
|
50195
|
-
return;
|
|
50196
|
-
}
|
|
50197
|
-
try {
|
|
50198
|
-
window.localStorage.setItem(
|
|
50199
|
-
buildInfoRateLimitCooldownStorageKey(cooldownKey),
|
|
50200
|
-
JSON.stringify({ untilMs })
|
|
50201
|
-
);
|
|
50202
|
-
} catch {
|
|
50203
|
-
}
|
|
50204
|
-
};
|
|
50205
|
-
extractInfoRequestTypeFromRateLimitError = (error48) => {
|
|
50206
|
-
const explicitType = normalizeInfoRequestType(error48?.requestType);
|
|
50207
|
-
if (explicitType !== "info") {
|
|
50208
|
-
return explicitType;
|
|
50209
|
-
}
|
|
50210
|
-
const detail = normalizeHyperliquidErrorDetail(error48);
|
|
50211
|
-
const match = /\brequest_type=([A-Za-z0-9_:-]+)/.exec(detail);
|
|
50212
|
-
return match?.[1] ? normalizeInfoRequestType(match[1]) : null;
|
|
50213
|
-
};
|
|
50214
|
-
recordInfoRateLimitCooldownFromError = (apiUrl, error48, staleIf429MaxAgeMs, nowMs = Date.now()) => {
|
|
50215
|
-
if (!isRateLimitError(error48)) {
|
|
50216
|
-
return;
|
|
50217
|
-
}
|
|
50218
|
-
const requestType = extractInfoRequestTypeFromRateLimitError(error48);
|
|
50219
|
-
if (!requestType) {
|
|
50220
|
-
return;
|
|
50221
|
-
}
|
|
50222
|
-
writeInfoRateLimitCooldown(apiUrl, requestType, staleIf429MaxAgeMs, nowMs);
|
|
50223
|
-
};
|
|
50297
|
+
hasActiveInfoRateLimitCooldown = (apiUrl, _requestTypes, nowMs = Date.now()) => getHyperliquidPublicReadBudget(apiUrl).cooldownUntilMs > nowMs;
|
|
50224
50298
|
requireNonNegativeConfigSeconds = (value, path) => {
|
|
50225
50299
|
const numeric2 = Number(value);
|
|
50226
50300
|
if (!Number.isFinite(numeric2) || numeric2 < 0) {
|
|
@@ -50744,6 +50818,19 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
50744
50818
|
}
|
|
50745
50819
|
return true;
|
|
50746
50820
|
};
|
|
50821
|
+
awaitAccountReads = async (reads) => {
|
|
50822
|
+
try {
|
|
50823
|
+
return await Promise.all(reads);
|
|
50824
|
+
} catch (error48) {
|
|
50825
|
+
if (error48 instanceof HyperliquidPublicReadError && error48.code === "public_cooldown_active") {
|
|
50826
|
+
const settled = await Promise.allSettled(reads);
|
|
50827
|
+
for (const result2 of settled) {
|
|
50828
|
+
if (result2.status === "rejected" && result2.reason instanceof HyperliquidPublicReadError && result2.reason.code === "public_rate_limited") throw result2.reason;
|
|
50829
|
+
}
|
|
50830
|
+
}
|
|
50831
|
+
throw error48;
|
|
50832
|
+
}
|
|
50833
|
+
};
|
|
50747
50834
|
fetchHyperliquidInfoPayload = async (apiUrl, body, signal, reservation) => {
|
|
50748
50835
|
const trace = startRuntimeNetworkDebugTrace({ kind: "exchange", label: `hyperliquid_info:${String(body.type)}`, method: "POST", url: `${apiUrl.replace(/\/$/, "")}/info` });
|
|
50749
50836
|
try {
|
|
@@ -50867,7 +50954,6 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
50867
50954
|
"Browser account state request aborted."
|
|
50868
50955
|
));
|
|
50869
50956
|
} catch (error48) {
|
|
50870
|
-
recordInfoRateLimitCooldownFromError(apiUrl, error48, staleIf429MaxAgeMs);
|
|
50871
50957
|
const staleCache = readBrowserAccountStateCache(cacheKey);
|
|
50872
50958
|
if (!input.forceRefresh && isRateLimitError(error48) && staleCache && Date.now() - staleCache.fetchedAtMs <= staleIf429MaxAgeMs) {
|
|
50873
50959
|
return withAccountStateEvidence(staleCache.result, "stale_if_429", staleCache.fetchedAtMs, staleIf429MaxAgeMs);
|
|
@@ -50927,10 +51013,10 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
50927
51013
|
capturedAt: new Date(capturedAtMs).toISOString()
|
|
50928
51014
|
};
|
|
50929
51015
|
})() : Promise.resolve(null);
|
|
50930
|
-
await
|
|
51016
|
+
await awaitAccountReads([userFeesPromise, exactAccountModePromise]);
|
|
50931
51017
|
const metadataByDex = /* @__PURE__ */ new Map();
|
|
50932
51018
|
if (input.includeEffectiveTakerRate === true) {
|
|
50933
|
-
await
|
|
51019
|
+
await awaitAccountReads(["", ...dexNames].map(async (dex) => {
|
|
50934
51020
|
try {
|
|
50935
51021
|
metadataByDex.set(dex, await fetchHyperliquidInfoPayload(apiUrl, { type: "meta", ...dex ? { dex } : {} }, input.signal, reservation));
|
|
50936
51022
|
} catch (error48) {
|
|
@@ -50949,7 +51035,7 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
50949
51035
|
if (input.includeEffectiveTakerRate === true) {
|
|
50950
51036
|
requirePromptClearinghouseState(defaultResponse, "default");
|
|
50951
51037
|
}
|
|
50952
|
-
const dexResponses = await
|
|
51038
|
+
const dexResponses = await awaitAccountReads(
|
|
50953
51039
|
dexNames.map(async (dexName) => {
|
|
50954
51040
|
const response = await fetchHyperliquidInfoPayload(
|
|
50955
51041
|
apiUrl,
|
|
@@ -50994,7 +51080,6 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
50994
51080
|
reservation
|
|
50995
51081
|
);
|
|
50996
51082
|
} catch (error48) {
|
|
50997
|
-
recordInfoRateLimitCooldownFromError(apiUrl, error48, staleIf429MaxAgeMs);
|
|
50998
51083
|
if (input.forceRefresh || input.includeEffectiveTakerRate === true) {
|
|
50999
51084
|
throw error48;
|
|
51000
51085
|
}
|
|
@@ -51015,7 +51100,6 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
51015
51100
|
return { payload, type: typeName };
|
|
51016
51101
|
} catch (error48) {
|
|
51017
51102
|
lastError = error48;
|
|
51018
|
-
recordInfoRateLimitCooldownFromError(apiUrl, error48, staleIf429MaxAgeMs);
|
|
51019
51103
|
if (isRateLimitError(error48)) throw error48;
|
|
51020
51104
|
if (typeName === "userActiveAssetData" && isUnsupportedUserActiveAssetError(error48)) {
|
|
51021
51105
|
rememberUnsupportedUserActiveAssetKey(activeAssetCacheKey);
|
|
@@ -51024,7 +51108,7 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
51024
51108
|
}
|
|
51025
51109
|
throw lastError instanceof Error ? lastError : new Error("Failed to fetch browser active asset data.");
|
|
51026
51110
|
})();
|
|
51027
|
-
const [perpsResult, spotResult, activeAssetResult, userFeesResult, exactAccountMode] = await
|
|
51111
|
+
const [perpsResult, spotResult, activeAssetResult, userFeesResult, exactAccountMode] = await awaitAccountReads([
|
|
51028
51112
|
perpsPromise,
|
|
51029
51113
|
spotPromise,
|
|
51030
51114
|
activeAssetPromise,
|
|
@@ -51050,7 +51134,7 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
51050
51134
|
...parseInfoPositions(perpsResponse).filter((position) => Number(position.size) !== 0).map((position) => position.symbol)
|
|
51051
51135
|
].map(normalizeHyperliquidMarketSymbol).filter(Boolean))].sort();
|
|
51052
51136
|
const feeDexes = [...new Set(feeSymbols.map(getHyperliquidMarketDex))];
|
|
51053
|
-
const metadata = await
|
|
51137
|
+
const metadata = await awaitAccountReads(feeDexes.map(async (dex) => {
|
|
51054
51138
|
try {
|
|
51055
51139
|
const payload = metadataByDex.get(dex) ?? null;
|
|
51056
51140
|
return [dex, payload];
|
|
@@ -51245,7 +51329,6 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
51245
51329
|
providerRowCount = liveResult.providerRowCount;
|
|
51246
51330
|
fetchedAtMs = liveResult.fetchedAtMs;
|
|
51247
51331
|
} catch (error48) {
|
|
51248
|
-
recordInfoRateLimitCooldownFromError(apiUrl, error48, staleIf429MaxAgeMs);
|
|
51249
51332
|
const staleCache = readBrowserUserFillsCache(cacheKey);
|
|
51250
51333
|
if (isRateLimitError(error48) && !input.forceRefresh) {
|
|
51251
51334
|
evidenceSource = "stale_if_429";
|
|
@@ -83844,6 +83927,7 @@ var init_hyperliquid_client = __esm({
|
|
|
83844
83927
|
init_define_VTX_EXO_POLICY();
|
|
83845
83928
|
init_define_VTX_GROK_POLICY();
|
|
83846
83929
|
init_define_VTX_PI_MODEL_POLICY();
|
|
83930
|
+
init_runtime_policy_generated();
|
|
83847
83931
|
init_hyperliquid_public_read();
|
|
83848
83932
|
init_api2();
|
|
83849
83933
|
init_abort();
|
|
@@ -85514,6 +85598,7 @@ var init_hyperliquid_client = __esm({
|
|
|
85514
85598
|
const serializedPayload = JSON.stringify(input.payload);
|
|
85515
85599
|
const durableMutation = input.durableMutation;
|
|
85516
85600
|
let exchangeDispatched = false;
|
|
85601
|
+
let recoveryPermit = null;
|
|
85517
85602
|
let settlementAttempted = false;
|
|
85518
85603
|
assertFreshPreparedExecutionContext(input.preparedContext);
|
|
85519
85604
|
const captureTimeoutMs = Number(
|
|
@@ -85670,8 +85755,9 @@ var init_hyperliquid_client = __esm({
|
|
|
85670
85755
|
}
|
|
85671
85756
|
}
|
|
85672
85757
|
try {
|
|
85673
|
-
await admitHyperliquidExchangeRequest(apiUrl, input.payload.action, input.signal);
|
|
85758
|
+
recoveryPermit = await admitHyperliquidExchangeRequest(apiUrl, input.payload.action, input.signal);
|
|
85674
85759
|
assertFreshPreparedExecutionContext(input.preparedContext);
|
|
85760
|
+
assertHyperliquidRecoveryDispatch(apiUrl, recoveryPermit, "exchange");
|
|
85675
85761
|
} catch (preparedContextError) {
|
|
85676
85762
|
await settleDurableMutation("rejected");
|
|
85677
85763
|
if (isAbortLikeError(preparedContextError) || preparedContextError instanceof HyperliquidPublicReadError) throw preparedContextError;
|
|
@@ -85699,16 +85785,44 @@ var init_hyperliquid_client = __esm({
|
|
|
85699
85785
|
}
|
|
85700
85786
|
}
|
|
85701
85787
|
exchangeDispatched = true;
|
|
85702
|
-
const
|
|
85703
|
-
|
|
85704
|
-
|
|
85705
|
-
|
|
85706
|
-
|
|
85707
|
-
|
|
85708
|
-
|
|
85709
|
-
|
|
85710
|
-
|
|
85711
|
-
|
|
85788
|
+
const transportController = new AbortController();
|
|
85789
|
+
const exchangeTimeout = runtime_policy_generated_default.exchange.hyperliquid.http.exchange;
|
|
85790
|
+
const transportTimeoutMs = Math.min(
|
|
85791
|
+
(exchangeTimeout.request_timeout_seconds + exchangeTimeout.pool_timeout_seconds) * 1e3,
|
|
85792
|
+
recoveryPermit ? Math.max(0, recoveryPermit.expiresAt - Date.now()) : Infinity
|
|
85793
|
+
);
|
|
85794
|
+
let transportTimer;
|
|
85795
|
+
let response;
|
|
85796
|
+
let payload;
|
|
85797
|
+
try {
|
|
85798
|
+
const transport = (async () => {
|
|
85799
|
+
const received = await fetch(requestUrl, {
|
|
85800
|
+
method: "POST",
|
|
85801
|
+
headers: { "Content-Type": "application/json" },
|
|
85802
|
+
body: serializedPayload,
|
|
85803
|
+
signal: transportController.signal
|
|
85804
|
+
});
|
|
85805
|
+
if (transportController.signal.aborted) throw transportController.signal.reason;
|
|
85806
|
+
responseStatus = received.status;
|
|
85807
|
+
await recordHyperliquidExchangeResponse(apiUrl, received);
|
|
85808
|
+
const body = await received.json().catch(() => ({}));
|
|
85809
|
+
if (transportController.signal.aborted) throw transportController.signal.reason;
|
|
85810
|
+
return { response: received, payload: body };
|
|
85811
|
+
})();
|
|
85812
|
+
const timeout = new Promise((_resolve, reject) => {
|
|
85813
|
+
transportTimer = globalThis.setTimeout(() => {
|
|
85814
|
+
const error48 = new DOMException("Hyperliquid exchange transport timed out.", "TimeoutError");
|
|
85815
|
+
transportController.abort(error48);
|
|
85816
|
+
reject(error48);
|
|
85817
|
+
}, transportTimeoutMs);
|
|
85818
|
+
});
|
|
85819
|
+
({ response, payload } = await Promise.race([transport, timeout]));
|
|
85820
|
+
} finally {
|
|
85821
|
+
globalThis.clearTimeout(transportTimer);
|
|
85822
|
+
transportController.abort();
|
|
85823
|
+
}
|
|
85824
|
+
await finishHyperliquidRecoveryRequest(recoveryPermit, response.status < 400 ? "success" : "failure").catch(() => void 0);
|
|
85825
|
+
recoveryPermit = null;
|
|
85712
85826
|
if (!response.ok) {
|
|
85713
85827
|
await settleDurableMutation("transport_ambiguous");
|
|
85714
85828
|
throw new RuntimeExecutionError(
|
|
@@ -85773,6 +85887,8 @@ var init_hyperliquid_client = __esm({
|
|
|
85773
85887
|
);
|
|
85774
85888
|
}
|
|
85775
85889
|
throw error48;
|
|
85890
|
+
} finally {
|
|
85891
|
+
await finishHyperliquidRecoveryRequest(recoveryPermit, exchangeDispatched ? "failure" : "cancelled").catch(() => void 0);
|
|
85776
85892
|
}
|
|
85777
85893
|
});
|
|
85778
85894
|
} catch (error48) {
|