@yuants/vendor-hyperliquid 0.9.10 → 0.10.1

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 (52) hide show
  1. package/dist/api/client.js +36 -2
  2. package/dist/api/client.js.map +1 -1
  3. package/dist/api/private-api.js +52 -41
  4. package/dist/api/private-api.js.map +1 -1
  5. package/dist/api/public-api.js +22 -11
  6. package/dist/api/public-api.js.map +1 -1
  7. package/dist/api/rate-limit.js +205 -0
  8. package/dist/api/rate-limit.js.map +1 -0
  9. package/dist/api/rate-limit.test.js +129 -0
  10. package/dist/api/rate-limit.test.js.map +1 -0
  11. package/dist/index.js +0 -2
  12. package/dist/index.js.map +1 -1
  13. package/lib/api/client.d.ts.map +1 -1
  14. package/lib/api/client.js +35 -1
  15. package/lib/api/client.js.map +1 -1
  16. package/lib/api/private-api.d.ts +65 -1
  17. package/lib/api/private-api.d.ts.map +1 -1
  18. package/lib/api/private-api.js +59 -43
  19. package/lib/api/private-api.js.map +1 -1
  20. package/lib/api/public-api.d.ts +54 -1
  21. package/lib/api/public-api.d.ts.map +1 -1
  22. package/lib/api/public-api.js +33 -12
  23. package/lib/api/public-api.js.map +1 -1
  24. package/lib/api/rate-limit.d.ts +21 -0
  25. package/lib/api/rate-limit.d.ts.map +1 -0
  26. package/lib/api/rate-limit.js +214 -0
  27. package/lib/api/rate-limit.js.map +1 -0
  28. package/lib/api/rate-limit.test.d.ts +2 -0
  29. package/lib/api/rate-limit.test.d.ts.map +1 -0
  30. package/lib/api/rate-limit.test.js +131 -0
  31. package/lib/api/rate-limit.test.js.map +1 -0
  32. package/lib/index.d.ts +0 -2
  33. package/lib/index.d.ts.map +1 -1
  34. package/lib/index.js +0 -2
  35. package/lib/index.js.map +1 -1
  36. package/package.json +6 -6
  37. package/temp/build/typescript/ts_HOjXkPSo.json +1 -1
  38. package/temp/package-deps.json +11 -11
  39. package/temp/test/jest/haste-map-1a3370ad4952cc1cbecf8fc42c6e9732-7b2990dcc44090c4eba2c52e971c544c-6a2a6e27ca3579da37751287ea19ab4c +0 -0
  40. package/temp/test/jest/perf-cache-1a3370ad4952cc1cbecf8fc42c6e9732-da39a3ee5e6b4b0d3255bfef95601890 +1 -0
  41. package/dist/services/markets/interest-rate.js +0 -61
  42. package/dist/services/markets/interest-rate.js.map +0 -1
  43. package/dist/services/markets/ohlc.js +0 -111
  44. package/dist/services/markets/ohlc.js.map +0 -1
  45. package/lib/services/markets/interest-rate.d.ts +0 -2
  46. package/lib/services/markets/interest-rate.d.ts.map +0 -1
  47. package/lib/services/markets/interest-rate.js +0 -63
  48. package/lib/services/markets/interest-rate.js.map +0 -1
  49. package/lib/services/markets/ohlc.d.ts +0 -2
  50. package/lib/services/markets/ohlc.d.ts.map +0 -1
  51. package/lib/services/markets/ohlc.js +0 -113
  52. package/lib/services/markets/ohlc.js.map +0 -1
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.afterRestResponse = exports.beforeRestRequest = exports.acquireRestIpWeightSync = exports.getRestEstimatedExtraWeight = exports.getRestBaseWeight = exports.getRestRequestContext = void 0;
4
+ const utils_1 = require("@yuants/utils");
5
+ const REST_IP_BUCKET_ID = 'HYPERLIQUID_REST_IP_WEIGHT_1200_PER_MIN';
6
+ const REST_IP_BUCKET_CAPACITY = 1200;
7
+ const REST_IP_WEIGHT_MAX = REST_IP_BUCKET_CAPACITY * 10;
8
+ (0, utils_1.tokenBucket)(REST_IP_BUCKET_ID, {
9
+ capacity: REST_IP_BUCKET_CAPACITY,
10
+ refillInterval: 60000,
11
+ refillAmount: 1200,
12
+ });
13
+ const INFO_TYPE_TO_BASE_WEIGHT = {
14
+ l2Book: 2,
15
+ allMids: 2,
16
+ clearinghouseState: 2,
17
+ orderStatus: 2,
18
+ spotClearinghouseState: 2,
19
+ exchangeStatus: 2,
20
+ userRole: 60,
21
+ };
22
+ const INTERVAL_TO_MS = {
23
+ '1m': 60000,
24
+ '3m': 180000,
25
+ '5m': 300000,
26
+ '15m': 900000,
27
+ '30m': 1800000,
28
+ '1h': 3600000,
29
+ '2h': 7200000,
30
+ '4h': 14400000,
31
+ '8h': 28800000,
32
+ '12h': 43200000,
33
+ '1d': 86400000,
34
+ '3d': 259200000,
35
+ '1w': 604800000,
36
+ '1M': 2592000000,
37
+ };
38
+ const getObject = (value) => {
39
+ if (typeof value !== 'object' || value === null)
40
+ return;
41
+ return value;
42
+ };
43
+ const getString = (value) => {
44
+ if (typeof value !== 'string')
45
+ return;
46
+ return value;
47
+ };
48
+ const getNumber = (value) => {
49
+ if (typeof value !== 'number' || !Number.isFinite(value))
50
+ return;
51
+ return value;
52
+ };
53
+ const getArray = (value) => {
54
+ if (!Array.isArray(value))
55
+ return;
56
+ return value;
57
+ };
58
+ const getRestRequestContext = (method, path, body) => {
59
+ var _a, _b;
60
+ if (method === 'POST' && path === 'info') {
61
+ const obj = getObject(body);
62
+ const infoType = getString(obj === null || obj === void 0 ? void 0 : obj.type);
63
+ return { method, path, body, kind: 'info', infoType };
64
+ }
65
+ if (method === 'POST' && path === 'exchange') {
66
+ const obj = getObject(body);
67
+ const action = getObject(obj === null || obj === void 0 ? void 0 : obj.action);
68
+ const exchangeActionType = getString(action === null || action === void 0 ? void 0 : action.type);
69
+ const orders = getArray(action === null || action === void 0 ? void 0 : action.orders);
70
+ const cancels = getArray(action === null || action === void 0 ? void 0 : action.cancels);
71
+ const exchangeBatchLength = Math.max(1, (_b = (_a = orders === null || orders === void 0 ? void 0 : orders.length) !== null && _a !== void 0 ? _a : cancels === null || cancels === void 0 ? void 0 : cancels.length) !== null && _b !== void 0 ? _b : 1);
72
+ return { method, path, body, kind: 'exchange', exchangeActionType, exchangeBatchLength };
73
+ }
74
+ if (path.startsWith('explorer')) {
75
+ return { method, path, body, kind: 'explorer' };
76
+ }
77
+ return { method, path, body, kind: 'other' };
78
+ };
79
+ exports.getRestRequestContext = getRestRequestContext;
80
+ const getRestBaseWeight = (ctx) => {
81
+ var _a, _b, _c;
82
+ if (ctx.kind === 'exchange') {
83
+ const batchLength = Math.max(1, (_a = ctx.exchangeBatchLength) !== null && _a !== void 0 ? _a : 1);
84
+ return 1 + Math.floor(batchLength / 40);
85
+ }
86
+ if (ctx.kind === 'info') {
87
+ return (_c = INFO_TYPE_TO_BASE_WEIGHT[(_b = ctx.infoType) !== null && _b !== void 0 ? _b : '']) !== null && _c !== void 0 ? _c : 20;
88
+ }
89
+ if (ctx.kind === 'explorer') {
90
+ return 40;
91
+ }
92
+ return 20;
93
+ };
94
+ exports.getRestBaseWeight = getRestBaseWeight;
95
+ const estimateCandleSnapshotItems = (ctx) => {
96
+ var _a;
97
+ if (ctx.kind !== 'info' || ctx.infoType !== 'candleSnapshot')
98
+ return 0;
99
+ const bodyObj = getObject(ctx.body);
100
+ const reqObj = getObject(bodyObj === null || bodyObj === void 0 ? void 0 : bodyObj.req);
101
+ const interval = getString(reqObj === null || reqObj === void 0 ? void 0 : reqObj.interval);
102
+ const startTime = getNumber(reqObj === null || reqObj === void 0 ? void 0 : reqObj.startTime);
103
+ const endTime = getNumber(reqObj === null || reqObj === void 0 ? void 0 : reqObj.endTime);
104
+ if (!interval || startTime === undefined || endTime === undefined || endTime <= startTime)
105
+ return 0;
106
+ const intervalMs = (_a = INTERVAL_TO_MS[interval]) !== null && _a !== void 0 ? _a : 0;
107
+ if (!intervalMs)
108
+ return 0;
109
+ // Hyperliquid docs: Only the most recent 5000 candles are available
110
+ const estimated = Math.ceil((endTime - startTime) / intervalMs);
111
+ return Math.min(5000, Math.max(0, estimated));
112
+ };
113
+ const countArrayResponseItems = (response) => {
114
+ var _a;
115
+ const arr = getArray(response);
116
+ return (_a = arr === null || arr === void 0 ? void 0 : arr.length) !== null && _a !== void 0 ? _a : 0;
117
+ };
118
+ const countUserFillsItems = (response) => {
119
+ var _a;
120
+ const obj = getObject(response);
121
+ const fills = getArray(obj === null || obj === void 0 ? void 0 : obj.fills);
122
+ return (_a = fills === null || fills === void 0 ? void 0 : fills.length) !== null && _a !== void 0 ? _a : 0;
123
+ };
124
+ const extraWeighers = [
125
+ {
126
+ match: (ctx) => ctx.kind === 'info' && ctx.infoType === 'candleSnapshot',
127
+ divisor: 60,
128
+ estimateItems: estimateCandleSnapshotItems,
129
+ countItemsFromResponse: countArrayResponseItems,
130
+ },
131
+ {
132
+ match: (ctx) => ctx.kind === 'info' &&
133
+ (ctx.infoType === 'recentTrades' ||
134
+ ctx.infoType === 'historicalOrders' ||
135
+ ctx.infoType === 'userFills' ||
136
+ ctx.infoType === 'userFillsByTime' ||
137
+ ctx.infoType === 'fundingHistory' ||
138
+ ctx.infoType === 'userFunding' ||
139
+ ctx.infoType === 'nonUserFundingUpdates' ||
140
+ ctx.infoType === 'twapHistory' ||
141
+ ctx.infoType === 'userTwapSliceFills' ||
142
+ ctx.infoType === 'userTwapSliceFillsByTime' ||
143
+ ctx.infoType === 'delegatorHistory' ||
144
+ ctx.infoType === 'delegatorRewards' ||
145
+ ctx.infoType === 'validatorStats'),
146
+ divisor: 20,
147
+ countItemsFromResponse: (response) => countUserFillsItems(response) || countArrayResponseItems(response),
148
+ },
149
+ ];
150
+ const getRestEstimatedExtraWeight = (ctx) => {
151
+ var _a, _b;
152
+ for (const weigher of extraWeighers) {
153
+ if (!weigher.match(ctx))
154
+ continue;
155
+ const items = (_b = (_a = weigher.estimateItems) === null || _a === void 0 ? void 0 : _a.call(weigher, ctx)) !== null && _b !== void 0 ? _b : 0;
156
+ if (items <= 0)
157
+ return 0;
158
+ return Math.ceil(items / weigher.divisor);
159
+ }
160
+ return 0;
161
+ };
162
+ exports.getRestEstimatedExtraWeight = getRestEstimatedExtraWeight;
163
+ const normalizeRestWeight = (meta, weight) => {
164
+ if (!Number.isFinite(weight)) {
165
+ throw (0, utils_1.newError)('HYPERLIQUID_REST_WEIGHT_INVALID', Object.assign(Object.assign({}, meta), { weight }));
166
+ }
167
+ const normalized = Math.floor(weight);
168
+ if (normalized <= 0) {
169
+ throw (0, utils_1.newError)('HYPERLIQUID_REST_WEIGHT_INVALID', Object.assign(Object.assign({}, meta), { weight: normalized }));
170
+ }
171
+ if (normalized > REST_IP_WEIGHT_MAX) {
172
+ throw (0, utils_1.newError)('HYPERLIQUID_REST_WEIGHT_EXCESSIVE', Object.assign(Object.assign({}, meta), { weight: normalized, maxWeight: REST_IP_WEIGHT_MAX }));
173
+ }
174
+ return normalized;
175
+ };
176
+ const acquireRestIpWeightSync = (meta, weight) => {
177
+ const normalized = normalizeRestWeight(meta, weight);
178
+ (0, utils_1.scopeError)('HYPERLIQUID_API_RATE_LIMIT', Object.assign(Object.assign({}, meta), { bucketId: REST_IP_BUCKET_ID, weight: normalized }), () => (0, utils_1.tokenBucket)(REST_IP_BUCKET_ID).acquireSync(normalized));
179
+ };
180
+ exports.acquireRestIpWeightSync = acquireRestIpWeightSync;
181
+ const acquireRestIpWeight = async (meta, weight) => {
182
+ let remaining = normalizeRestWeight(meta, weight);
183
+ while (remaining > 0) {
184
+ const chunk = Math.min(REST_IP_BUCKET_CAPACITY, remaining);
185
+ await (0, utils_1.scopeError)('HYPERLIQUID_API_RATE_LIMIT', Object.assign(Object.assign({}, meta), { bucketId: REST_IP_BUCKET_ID, weight: chunk, remaining }), () => (0, utils_1.tokenBucket)(REST_IP_BUCKET_ID).acquire(chunk));
186
+ remaining -= chunk;
187
+ }
188
+ };
189
+ const beforeRestRequest = (meta, ctx) => {
190
+ const baseWeight = (0, exports.getRestBaseWeight)(ctx);
191
+ const estimatedExtraWeight = (0, exports.getRestEstimatedExtraWeight)(ctx);
192
+ (0, exports.acquireRestIpWeightSync)(meta, baseWeight + estimatedExtraWeight);
193
+ return { baseWeight, estimatedExtraWeight };
194
+ };
195
+ exports.beforeRestRequest = beforeRestRequest;
196
+ const afterRestResponse = async (meta, ctx, response, estimatedExtraWeight) => {
197
+ var _a, _b;
198
+ for (const weigher of extraWeighers) {
199
+ if (!weigher.match(ctx))
200
+ continue;
201
+ const items = (_b = (_a = weigher.countItemsFromResponse) === null || _a === void 0 ? void 0 : _a.call(weigher, response)) !== null && _b !== void 0 ? _b : 0;
202
+ if (items <= 0)
203
+ return;
204
+ const actualExtraWeight = Math.ceil(items / weigher.divisor);
205
+ const delta = actualExtraWeight - estimatedExtraWeight;
206
+ if (delta > 0) {
207
+ // 不使用 acquireSync:响应后只阻塞等待,不报错
208
+ await acquireRestIpWeight(meta, delta);
209
+ }
210
+ return;
211
+ }
212
+ };
213
+ exports.afterRestResponse = afterRestResponse;
214
+ //# sourceMappingURL=rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/api/rate-limit.ts"],"names":[],"mappings":";;;AAAA,yCAAkE;AAqBlE,MAAM,iBAAiB,GAAG,yCAAyC,CAAC;AACpE,MAAM,uBAAuB,GAAG,IAAI,CAAC;AACrC,MAAM,kBAAkB,GAAG,uBAAuB,GAAG,EAAE,CAAC;AAExD,IAAA,mBAAW,EAAC,iBAAiB,EAAE;IAC7B,QAAQ,EAAE,uBAAuB;IACjC,cAAc,EAAE,KAAM;IACtB,YAAY,EAAE,IAAI;CACnB,CAAC,CAAC;AAEH,MAAM,wBAAwB,GAAqC;IACjE,MAAM,EAAE,CAAC;IACT,OAAO,EAAE,CAAC;IACV,kBAAkB,EAAE,CAAC;IACrB,WAAW,EAAE,CAAC;IACd,sBAAsB,EAAE,CAAC;IACzB,cAAc,EAAE,CAAC;IACjB,QAAQ,EAAE,EAAE;CACb,CAAC;AAEF,MAAM,cAAc,GAAqC;IACvD,IAAI,EAAE,KAAM;IACZ,IAAI,EAAE,MAAO;IACb,IAAI,EAAE,MAAO;IACb,KAAK,EAAE,MAAO;IACd,KAAK,EAAE,OAAS;IAChB,IAAI,EAAE,OAAS;IACf,IAAI,EAAE,OAAS;IACf,IAAI,EAAE,QAAU;IAChB,IAAI,EAAE,QAAU;IAChB,KAAK,EAAE,QAAU;IACjB,IAAI,EAAE,QAAU;IAChB,IAAI,EAAE,SAAW;IACjB,IAAI,EAAE,SAAW;IACjB,IAAI,EAAE,UAAa;CACpB,CAAC;AAEF,MAAM,SAAS,GAAG,CAAC,KAAc,EAAuC,EAAE;IACxE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO;IACxD,OAAO,KAAgC,CAAC;AAC1C,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,CAAC,KAAc,EAAsB,EAAE;IACvD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO;IACtC,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,CAAC,KAAc,EAAsB,EAAE;IACvD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO;IACjE,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAyB,EAAE;IACzD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO;IAClC,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEK,MAAM,qBAAqB,GAAG,CACnC,MAAkB,EAClB,IAAY,EACZ,IAAc,EACM,EAAE;;IACtB,IAAI,MAAM,KAAK,MAAM,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC5B,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,IAAI,CAAC,CAAC;QACtC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IACxD,CAAC;IACD,IAAI,MAAM,KAAK,MAAM,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QAC7C,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC5B,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,MAAM,CAAC,CAAC;QACtC,MAAM,kBAAkB,GAAG,SAAS,CAAC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,OAAO,CAAC,CAAC;QAC1C,MAAM,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAA,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,mCAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,mCAAI,CAAC,CAAC,CAAC;QAChF,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,CAAC;IAC3F,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IAClD,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC/C,CAAC,CAAC;AAvBW,QAAA,qBAAqB,yBAuBhC;AAEK,MAAM,iBAAiB,GAAG,CAAC,GAAuB,EAAU,EAAE;;IACnE,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAA,GAAG,CAAC,mBAAmB,mCAAI,CAAC,CAAC,CAAC;QAC9D,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,EAAE,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO,MAAA,wBAAwB,CAAC,MAAA,GAAG,CAAC,QAAQ,mCAAI,EAAE,CAAC,mCAAI,EAAE,CAAC;IAC5D,CAAC;IACD,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC5B,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC,CAAC;AAZW,QAAA,iBAAiB,qBAY5B;AAEF,MAAM,2BAA2B,GAAG,CAAC,GAAuB,EAAU,EAAE;;IACtE,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,GAAG,CAAC,QAAQ,KAAK,gBAAgB;QAAE,OAAO,CAAC,CAAC;IACvE,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,GAAG,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,QAAQ,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,SAAS,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,OAAO,CAAC,CAAC;IAC3C,IAAI,CAAC,QAAQ,IAAI,SAAS,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,IAAI,SAAS;QAAE,OAAO,CAAC,CAAC;IAEpG,MAAM,UAAU,GAAG,MAAA,cAAc,CAAC,QAAQ,CAAC,mCAAI,CAAC,CAAC;IACjD,IAAI,CAAC,UAAU;QAAE,OAAO,CAAC,CAAC;IAE1B,oEAAoE;IACpE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,GAAG,SAAS,CAAC,GAAG,UAAU,CAAC,CAAC;IAChE,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;AAChD,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAAG,CAAC,QAAiB,EAAU,EAAE;;IAC5D,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC/B,OAAO,MAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,MAAM,mCAAI,CAAC,CAAC;AAC1B,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,QAAiB,EAAU,EAAE;;IACxD,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,KAAK,CAAC,CAAC;IACnC,OAAO,MAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,MAAM,mCAAI,CAAC,CAAC;AAC5B,CAAC,CAAC;AAEF,MAAM,aAAa,GAAgC;IACjD;QACE,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,GAAG,CAAC,QAAQ,KAAK,gBAAgB;QACxE,OAAO,EAAE,EAAE;QACX,aAAa,EAAE,2BAA2B;QAC1C,sBAAsB,EAAE,uBAAuB;KAChD;IACD;QACE,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CACb,GAAG,CAAC,IAAI,KAAK,MAAM;YACnB,CAAC,GAAG,CAAC,QAAQ,KAAK,cAAc;gBAC9B,GAAG,CAAC,QAAQ,KAAK,kBAAkB;gBACnC,GAAG,CAAC,QAAQ,KAAK,WAAW;gBAC5B,GAAG,CAAC,QAAQ,KAAK,iBAAiB;gBAClC,GAAG,CAAC,QAAQ,KAAK,gBAAgB;gBACjC,GAAG,CAAC,QAAQ,KAAK,aAAa;gBAC9B,GAAG,CAAC,QAAQ,KAAK,uBAAuB;gBACxC,GAAG,CAAC,QAAQ,KAAK,aAAa;gBAC9B,GAAG,CAAC,QAAQ,KAAK,oBAAoB;gBACrC,GAAG,CAAC,QAAQ,KAAK,0BAA0B;gBAC3C,GAAG,CAAC,QAAQ,KAAK,kBAAkB;gBACnC,GAAG,CAAC,QAAQ,KAAK,kBAAkB;gBACnC,GAAG,CAAC,QAAQ,KAAK,gBAAgB,CAAC;QACtC,OAAO,EAAE,EAAE;QACX,sBAAsB,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,mBAAmB,CAAC,QAAQ,CAAC,IAAI,uBAAuB,CAAC,QAAQ,CAAC;KACzG;CACF,CAAC;AAEK,MAAM,2BAA2B,GAAG,CAAC,GAAuB,EAAU,EAAE;;IAC7E,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;QACpC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;YAAE,SAAS;QAClC,MAAM,KAAK,GAAG,MAAA,MAAA,OAAO,CAAC,aAAa,wDAAG,GAAG,CAAC,mCAAI,CAAC,CAAC;QAChD,IAAI,KAAK,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC;QACzB,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AARW,QAAA,2BAA2B,+BAQtC;AAEF,MAAM,mBAAmB,GAAG,CAAC,IAA6B,EAAE,MAAc,EAAU,EAAE;IACpF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAA,gBAAQ,EAAC,iCAAiC,kCAAO,IAAI,KAAE,MAAM,IAAG,CAAC;IACzE,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACtC,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;QACpB,MAAM,IAAA,gBAAQ,EAAC,iCAAiC,kCAAO,IAAI,KAAE,MAAM,EAAE,UAAU,IAAG,CAAC;IACrF,CAAC;IACD,IAAI,UAAU,GAAG,kBAAkB,EAAE,CAAC;QACpC,MAAM,IAAA,gBAAQ,EAAC,mCAAmC,kCAC7C,IAAI,KACP,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,kBAAkB,IAC7B,CAAC;IACL,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC;AAEK,MAAM,uBAAuB,GAAG,CAAC,IAA6B,EAAE,MAAc,EAAE,EAAE;IACvF,MAAM,UAAU,GAAG,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrD,IAAA,kBAAU,EAAC,4BAA4B,kCAAO,IAAI,KAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,EAAE,UAAU,KAAI,GAAG,EAAE,CAC1G,IAAA,mBAAW,EAAC,iBAAiB,CAAC,CAAC,WAAW,CAAC,UAAU,CAAC,CACvD,CAAC;AACJ,CAAC,CAAC;AALW,QAAA,uBAAuB,2BAKlC;AAEF,MAAM,mBAAmB,GAAG,KAAK,EAAE,IAA6B,EAAE,MAAc,EAAE,EAAE;IAClF,IAAI,SAAS,GAAG,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAClD,OAAO,SAAS,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,uBAAuB,EAAE,SAAS,CAAC,CAAC;QAC3D,MAAM,IAAA,kBAAU,EACd,4BAA4B,kCACvB,IAAI,KAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,KAChE,GAAG,EAAE,CAAC,IAAA,mBAAW,EAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CACpD,CAAC;QACF,SAAS,IAAI,KAAK,CAAC;IACrB,CAAC;AACH,CAAC,CAAC;AAEK,MAAM,iBAAiB,GAAG,CAC/B,IAA6B,EAC7B,GAAuB,EACyC,EAAE;IAClE,MAAM,UAAU,GAAG,IAAA,yBAAiB,EAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,oBAAoB,GAAG,IAAA,mCAA2B,EAAC,GAAG,CAAC,CAAC;IAC9D,IAAA,+BAAuB,EAAC,IAAI,EAAE,UAAU,GAAG,oBAAoB,CAAC,CAAC;IACjE,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,CAAC;AAC9C,CAAC,CAAC;AARW,QAAA,iBAAiB,qBAQ5B;AAEK,MAAM,iBAAiB,GAAG,KAAK,EACpC,IAA6B,EAC7B,GAAuB,EACvB,QAAiB,EACjB,oBAA4B,EAC5B,EAAE;;IACF,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;QACpC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;YAAE,SAAS;QAClC,MAAM,KAAK,GAAG,MAAA,MAAA,OAAO,CAAC,sBAAsB,wDAAG,QAAQ,CAAC,mCAAI,CAAC,CAAC;QAC9D,IAAI,KAAK,IAAI,CAAC;YAAE,OAAO;QACvB,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7D,MAAM,KAAK,GAAG,iBAAiB,GAAG,oBAAoB,CAAC;QACvD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,+BAA+B;YAC/B,MAAM,mBAAmB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACzC,CAAC;QACD,OAAO;IACT,CAAC;AACH,CAAC,CAAC;AAlBW,QAAA,iBAAiB,qBAkB5B","sourcesContent":["import { newError, scopeError, tokenBucket } from '@yuants/utils';\n\ntype HttpMethod = 'GET' | 'POST';\n\ntype RestRequestContext = Readonly<{\n method: HttpMethod;\n path: string;\n body?: unknown;\n kind: 'info' | 'exchange' | 'explorer' | 'other';\n infoType?: string;\n exchangeActionType?: string;\n exchangeBatchLength?: number;\n}>;\n\ntype ExtraWeigher = Readonly<{\n match: (ctx: RestRequestContext) => boolean;\n divisor: 20 | 60;\n estimateItems?: (ctx: RestRequestContext) => number;\n countItemsFromResponse?: (response: unknown) => number;\n}>;\n\nconst REST_IP_BUCKET_ID = 'HYPERLIQUID_REST_IP_WEIGHT_1200_PER_MIN';\nconst REST_IP_BUCKET_CAPACITY = 1200;\nconst REST_IP_WEIGHT_MAX = REST_IP_BUCKET_CAPACITY * 10;\n\ntokenBucket(REST_IP_BUCKET_ID, {\n capacity: REST_IP_BUCKET_CAPACITY,\n refillInterval: 60_000,\n refillAmount: 1200,\n});\n\nconst INFO_TYPE_TO_BASE_WEIGHT: Readonly<Record<string, number>> = {\n l2Book: 2,\n allMids: 2,\n clearinghouseState: 2,\n orderStatus: 2,\n spotClearinghouseState: 2,\n exchangeStatus: 2,\n userRole: 60,\n};\n\nconst INTERVAL_TO_MS: Readonly<Record<string, number>> = {\n '1m': 60_000,\n '3m': 180_000,\n '5m': 300_000,\n '15m': 900_000,\n '30m': 1_800_000,\n '1h': 3_600_000,\n '2h': 7_200_000,\n '4h': 14_400_000,\n '8h': 28_800_000,\n '12h': 43_200_000,\n '1d': 86_400_000,\n '3d': 259_200_000,\n '1w': 604_800_000,\n '1M': 2_592_000_000,\n};\n\nconst getObject = (value: unknown): Record<string, unknown> | undefined => {\n if (typeof value !== 'object' || value === null) return;\n return value as Record<string, unknown>;\n};\n\nconst getString = (value: unknown): string | undefined => {\n if (typeof value !== 'string') return;\n return value;\n};\n\nconst getNumber = (value: unknown): number | undefined => {\n if (typeof value !== 'number' || !Number.isFinite(value)) return;\n return value;\n};\n\nconst getArray = (value: unknown): unknown[] | undefined => {\n if (!Array.isArray(value)) return;\n return value;\n};\n\nexport const getRestRequestContext = (\n method: HttpMethod,\n path: string,\n body?: unknown,\n): RestRequestContext => {\n if (method === 'POST' && path === 'info') {\n const obj = getObject(body);\n const infoType = getString(obj?.type);\n return { method, path, body, kind: 'info', infoType };\n }\n if (method === 'POST' && path === 'exchange') {\n const obj = getObject(body);\n const action = getObject(obj?.action);\n const exchangeActionType = getString(action?.type);\n const orders = getArray(action?.orders);\n const cancels = getArray(action?.cancels);\n const exchangeBatchLength = Math.max(1, orders?.length ?? cancels?.length ?? 1);\n return { method, path, body, kind: 'exchange', exchangeActionType, exchangeBatchLength };\n }\n if (path.startsWith('explorer')) {\n return { method, path, body, kind: 'explorer' };\n }\n return { method, path, body, kind: 'other' };\n};\n\nexport const getRestBaseWeight = (ctx: RestRequestContext): number => {\n if (ctx.kind === 'exchange') {\n const batchLength = Math.max(1, ctx.exchangeBatchLength ?? 1);\n return 1 + Math.floor(batchLength / 40);\n }\n if (ctx.kind === 'info') {\n return INFO_TYPE_TO_BASE_WEIGHT[ctx.infoType ?? ''] ?? 20;\n }\n if (ctx.kind === 'explorer') {\n return 40;\n }\n return 20;\n};\n\nconst estimateCandleSnapshotItems = (ctx: RestRequestContext): number => {\n if (ctx.kind !== 'info' || ctx.infoType !== 'candleSnapshot') return 0;\n const bodyObj = getObject(ctx.body);\n const reqObj = getObject(bodyObj?.req);\n const interval = getString(reqObj?.interval);\n const startTime = getNumber(reqObj?.startTime);\n const endTime = getNumber(reqObj?.endTime);\n if (!interval || startTime === undefined || endTime === undefined || endTime <= startTime) return 0;\n\n const intervalMs = INTERVAL_TO_MS[interval] ?? 0;\n if (!intervalMs) return 0;\n\n // Hyperliquid docs: Only the most recent 5000 candles are available\n const estimated = Math.ceil((endTime - startTime) / intervalMs);\n return Math.min(5000, Math.max(0, estimated));\n};\n\nconst countArrayResponseItems = (response: unknown): number => {\n const arr = getArray(response);\n return arr?.length ?? 0;\n};\n\nconst countUserFillsItems = (response: unknown): number => {\n const obj = getObject(response);\n const fills = getArray(obj?.fills);\n return fills?.length ?? 0;\n};\n\nconst extraWeighers: ReadonlyArray<ExtraWeigher> = [\n {\n match: (ctx) => ctx.kind === 'info' && ctx.infoType === 'candleSnapshot',\n divisor: 60,\n estimateItems: estimateCandleSnapshotItems,\n countItemsFromResponse: countArrayResponseItems,\n },\n {\n match: (ctx) =>\n ctx.kind === 'info' &&\n (ctx.infoType === 'recentTrades' ||\n ctx.infoType === 'historicalOrders' ||\n ctx.infoType === 'userFills' ||\n ctx.infoType === 'userFillsByTime' ||\n ctx.infoType === 'fundingHistory' ||\n ctx.infoType === 'userFunding' ||\n ctx.infoType === 'nonUserFundingUpdates' ||\n ctx.infoType === 'twapHistory' ||\n ctx.infoType === 'userTwapSliceFills' ||\n ctx.infoType === 'userTwapSliceFillsByTime' ||\n ctx.infoType === 'delegatorHistory' ||\n ctx.infoType === 'delegatorRewards' ||\n ctx.infoType === 'validatorStats'),\n divisor: 20,\n countItemsFromResponse: (response) => countUserFillsItems(response) || countArrayResponseItems(response),\n },\n];\n\nexport const getRestEstimatedExtraWeight = (ctx: RestRequestContext): number => {\n for (const weigher of extraWeighers) {\n if (!weigher.match(ctx)) continue;\n const items = weigher.estimateItems?.(ctx) ?? 0;\n if (items <= 0) return 0;\n return Math.ceil(items / weigher.divisor);\n }\n return 0;\n};\n\nconst normalizeRestWeight = (meta: Record<string, unknown>, weight: number): number => {\n if (!Number.isFinite(weight)) {\n throw newError('HYPERLIQUID_REST_WEIGHT_INVALID', { ...meta, weight });\n }\n const normalized = Math.floor(weight);\n if (normalized <= 0) {\n throw newError('HYPERLIQUID_REST_WEIGHT_INVALID', { ...meta, weight: normalized });\n }\n if (normalized > REST_IP_WEIGHT_MAX) {\n throw newError('HYPERLIQUID_REST_WEIGHT_EXCESSIVE', {\n ...meta,\n weight: normalized,\n maxWeight: REST_IP_WEIGHT_MAX,\n });\n }\n return normalized;\n};\n\nexport const acquireRestIpWeightSync = (meta: Record<string, unknown>, weight: number) => {\n const normalized = normalizeRestWeight(meta, weight);\n scopeError('HYPERLIQUID_API_RATE_LIMIT', { ...meta, bucketId: REST_IP_BUCKET_ID, weight: normalized }, () =>\n tokenBucket(REST_IP_BUCKET_ID).acquireSync(normalized),\n );\n};\n\nconst acquireRestIpWeight = async (meta: Record<string, unknown>, weight: number) => {\n let remaining = normalizeRestWeight(meta, weight);\n while (remaining > 0) {\n const chunk = Math.min(REST_IP_BUCKET_CAPACITY, remaining);\n await scopeError(\n 'HYPERLIQUID_API_RATE_LIMIT',\n { ...meta, bucketId: REST_IP_BUCKET_ID, weight: chunk, remaining },\n () => tokenBucket(REST_IP_BUCKET_ID).acquire(chunk),\n );\n remaining -= chunk;\n }\n};\n\nexport const beforeRestRequest = (\n meta: Record<string, unknown>,\n ctx: RestRequestContext,\n): Readonly<{ baseWeight: number; estimatedExtraWeight: number }> => {\n const baseWeight = getRestBaseWeight(ctx);\n const estimatedExtraWeight = getRestEstimatedExtraWeight(ctx);\n acquireRestIpWeightSync(meta, baseWeight + estimatedExtraWeight);\n return { baseWeight, estimatedExtraWeight };\n};\n\nexport const afterRestResponse = async (\n meta: Record<string, unknown>,\n ctx: RestRequestContext,\n response: unknown,\n estimatedExtraWeight: number,\n) => {\n for (const weigher of extraWeighers) {\n if (!weigher.match(ctx)) continue;\n const items = weigher.countItemsFromResponse?.(response) ?? 0;\n if (items <= 0) return;\n const actualExtraWeight = Math.ceil(items / weigher.divisor);\n const delta = actualExtraWeight - estimatedExtraWeight;\n if (delta > 0) {\n // 不使用 acquireSync:响应后只阻塞等待,不报错\n await acquireRestIpWeight(meta, delta);\n }\n return;\n }\n};\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=rate-limit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.test.d.ts","sourceRoot":"","sources":["../../src/api/rate-limit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("@yuants/utils");
4
+ const rate_limit_1 = require("./rate-limit");
5
+ describe('rate-limit', () => {
6
+ const bucketId = 'HYPERLIQUID_REST_IP_WEIGHT_1200_PER_MIN';
7
+ const readBucket = () => (0, utils_1.tokenBucket)(bucketId).read();
8
+ afterAll(() => {
9
+ const bucket = (0, utils_1.tokenBucket)(bucketId);
10
+ bucket[Symbol.dispose]();
11
+ });
12
+ it('parses rest request context', () => {
13
+ const infoCtx = (0, rate_limit_1.getRestRequestContext)('POST', 'info', { type: 'allMids' });
14
+ expect(infoCtx.kind).toBe('info');
15
+ expect(infoCtx.infoType).toBe('allMids');
16
+ const exchangeCtx = (0, rate_limit_1.getRestRequestContext)('POST', 'exchange', {
17
+ action: { type: 'order', orders: [{}, {}] },
18
+ });
19
+ expect(exchangeCtx.kind).toBe('exchange');
20
+ expect(exchangeCtx.exchangeActionType).toBe('order');
21
+ expect(exchangeCtx.exchangeBatchLength).toBe(2);
22
+ const explorerCtx = (0, rate_limit_1.getRestRequestContext)('GET', 'explorer/tx/0x', undefined);
23
+ expect(explorerCtx.kind).toBe('explorer');
24
+ });
25
+ it('calculates info base weight', () => {
26
+ const ctx = (0, rate_limit_1.getRestRequestContext)('POST', 'info', { type: 'allMids' });
27
+ expect((0, rate_limit_1.getRestBaseWeight)(ctx)).toBe(2);
28
+ });
29
+ it('defaults base weight for unknown info type', () => {
30
+ const ctx = (0, rate_limit_1.getRestRequestContext)('POST', 'info', { type: 'unknownType' });
31
+ expect((0, rate_limit_1.getRestBaseWeight)(ctx)).toBe(20);
32
+ });
33
+ it('assigns base weight for explorer and other requests', () => {
34
+ const explorerCtx = (0, rate_limit_1.getRestRequestContext)('GET', 'explorer/tx/0x', undefined);
35
+ expect((0, rate_limit_1.getRestBaseWeight)(explorerCtx)).toBe(40);
36
+ const otherCtx = (0, rate_limit_1.getRestRequestContext)('GET', 'status', undefined);
37
+ expect((0, rate_limit_1.getRestBaseWeight)(otherCtx)).toBe(20);
38
+ });
39
+ it('calculates exchange base weight across batch sizes', () => {
40
+ const cases = [
41
+ { batchLength: 0, expected: 1 },
42
+ { batchLength: 1, expected: 1 },
43
+ { batchLength: 40, expected: 2 },
44
+ { batchLength: 41, expected: 2 },
45
+ { batchLength: 80, expected: 3 },
46
+ ];
47
+ for (const { batchLength, expected } of cases) {
48
+ const ctx = (0, rate_limit_1.getRestRequestContext)('POST', 'exchange', {
49
+ action: { type: 'order', orders: new Array(batchLength).fill({}) },
50
+ });
51
+ expect((0, rate_limit_1.getRestBaseWeight)(ctx)).toBe(expected);
52
+ }
53
+ });
54
+ it('estimates candleSnapshot extra weight with 5000 cap', () => {
55
+ const intervalMs = 60000;
56
+ const candles = 10000;
57
+ const ctx = (0, rate_limit_1.getRestRequestContext)('POST', 'info', {
58
+ type: 'candleSnapshot',
59
+ req: { interval: '1m', startTime: 0, endTime: candles * intervalMs },
60
+ });
61
+ expect((0, rate_limit_1.getRestEstimatedExtraWeight)(ctx)).toBe(Math.ceil(5000 / 60));
62
+ });
63
+ it('returns zero extra weight for invalid candleSnapshot inputs', () => {
64
+ const invalidIntervalCtx = (0, rate_limit_1.getRestRequestContext)('POST', 'info', {
65
+ type: 'candleSnapshot',
66
+ req: { interval: '2m', startTime: 0, endTime: 60000 },
67
+ });
68
+ expect((0, rate_limit_1.getRestEstimatedExtraWeight)(invalidIntervalCtx)).toBe(0);
69
+ const sameTimeCtx = (0, rate_limit_1.getRestRequestContext)('POST', 'info', {
70
+ type: 'candleSnapshot',
71
+ req: { interval: '1m', startTime: 0, endTime: 0 },
72
+ });
73
+ expect((0, rate_limit_1.getRestEstimatedExtraWeight)(sameTimeCtx)).toBe(0);
74
+ const missingReqCtx = (0, rate_limit_1.getRestRequestContext)('POST', 'info', { type: 'candleSnapshot' });
75
+ expect((0, rate_limit_1.getRestEstimatedExtraWeight)(missingReqCtx)).toBe(0);
76
+ });
77
+ it('consumes base and estimated weight before request', () => {
78
+ const ctx = (0, rate_limit_1.getRestRequestContext)('POST', 'info', {
79
+ type: 'candleSnapshot',
80
+ req: { interval: '1m', startTime: 0, endTime: 120 * 60000 },
81
+ });
82
+ const before = readBucket();
83
+ const { baseWeight, estimatedExtraWeight } = (0, rate_limit_1.beforeRestRequest)({ requestKey: 'test' }, ctx);
84
+ const after = readBucket();
85
+ expect(baseWeight).toBe(20);
86
+ expect(estimatedExtraWeight).toBe(2);
87
+ expect(after).toBe(before - baseWeight - estimatedExtraWeight);
88
+ });
89
+ it('throws on invalid or excessive weights before request', () => {
90
+ const invalidCtx = {
91
+ method: 'POST',
92
+ path: 'exchange',
93
+ kind: 'exchange',
94
+ exchangeBatchLength: Number.NaN,
95
+ };
96
+ expect(() => (0, rate_limit_1.beforeRestRequest)({ requestKey: 'test' }, invalidCtx)).toThrow(/HYPERLIQUID_REST_WEIGHT_INVALID/);
97
+ const maxWeight = 1200 * 10;
98
+ const excessiveCtx = {
99
+ method: 'POST',
100
+ path: 'exchange',
101
+ kind: 'exchange',
102
+ exchangeBatchLength: (maxWeight + 1) * 40,
103
+ };
104
+ expect(() => (0, rate_limit_1.beforeRestRequest)({ requestKey: 'test' }, excessiveCtx)).toThrow(/HYPERLIQUID_REST_WEIGHT_EXCESSIVE/);
105
+ });
106
+ it('applies extra weight based on response size', async () => {
107
+ const ctx = (0, rate_limit_1.getRestRequestContext)('POST', 'info', { type: 'userFills' });
108
+ const response = { fills: new Array(41).fill({}) };
109
+ const before = readBucket();
110
+ await (0, rate_limit_1.afterRestResponse)({ requestKey: 'test' }, ctx, response, 0);
111
+ const after = readBucket();
112
+ expect(before - after).toBe(Math.ceil(41 / 20));
113
+ });
114
+ it('applies delta extra weight for candleSnapshot responses', async () => {
115
+ const ctx = (0, rate_limit_1.getRestRequestContext)('POST', 'info', { type: 'candleSnapshot' });
116
+ const response = new Array(120).fill({});
117
+ const before = readBucket();
118
+ await (0, rate_limit_1.afterRestResponse)({ requestKey: 'test' }, ctx, response, 1);
119
+ const after = readBucket();
120
+ expect(before - after).toBe(1);
121
+ });
122
+ it('skips extra acquire when response weight is within estimate', async () => {
123
+ const ctx = (0, rate_limit_1.getRestRequestContext)('POST', 'info', { type: 'userFills' });
124
+ const response = { fills: [{}] };
125
+ const before = readBucket();
126
+ await (0, rate_limit_1.afterRestResponse)({ requestKey: 'test' }, ctx, response, 1);
127
+ const after = readBucket();
128
+ expect(after).toBe(before);
129
+ });
130
+ });
131
+ //# sourceMappingURL=rate-limit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.test.js","sourceRoot":"","sources":["../../src/api/rate-limit.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { tokenBucket } from '@yuants/utils';\nimport {\n afterRestResponse,\n beforeRestRequest,\n getRestBaseWeight,\n getRestEstimatedExtraWeight,\n getRestRequestContext,\n} from './rate-limit';\n\ndescribe('rate-limit', () => {\n const bucketId = 'HYPERLIQUID_REST_IP_WEIGHT_1200_PER_MIN';\n const readBucket = () => tokenBucket(bucketId).read();\n\n afterAll(() => {\n const bucket = tokenBucket(bucketId);\n bucket[Symbol.dispose]();\n });\n\n it('parses rest request context', () => {\n const infoCtx = getRestRequestContext('POST', 'info', { type: 'allMids' });\n expect(infoCtx.kind).toBe('info');\n expect(infoCtx.infoType).toBe('allMids');\n\n const exchangeCtx = getRestRequestContext('POST', 'exchange', {\n action: { type: 'order', orders: [{}, {}] },\n });\n expect(exchangeCtx.kind).toBe('exchange');\n expect(exchangeCtx.exchangeActionType).toBe('order');\n expect(exchangeCtx.exchangeBatchLength).toBe(2);\n\n const explorerCtx = getRestRequestContext('GET', 'explorer/tx/0x', undefined);\n expect(explorerCtx.kind).toBe('explorer');\n });\n\n it('calculates info base weight', () => {\n const ctx = getRestRequestContext('POST', 'info', { type: 'allMids' });\n expect(getRestBaseWeight(ctx)).toBe(2);\n });\n\n it('defaults base weight for unknown info type', () => {\n const ctx = getRestRequestContext('POST', 'info', { type: 'unknownType' });\n expect(getRestBaseWeight(ctx)).toBe(20);\n });\n\n it('assigns base weight for explorer and other requests', () => {\n const explorerCtx = getRestRequestContext('GET', 'explorer/tx/0x', undefined);\n expect(getRestBaseWeight(explorerCtx)).toBe(40);\n\n const otherCtx = getRestRequestContext('GET', 'status', undefined);\n expect(getRestBaseWeight(otherCtx)).toBe(20);\n });\n\n it('calculates exchange base weight across batch sizes', () => {\n const cases = [\n { batchLength: 0, expected: 1 },\n { batchLength: 1, expected: 1 },\n { batchLength: 40, expected: 2 },\n { batchLength: 41, expected: 2 },\n { batchLength: 80, expected: 3 },\n ];\n\n for (const { batchLength, expected } of cases) {\n const ctx = getRestRequestContext('POST', 'exchange', {\n action: { type: 'order', orders: new Array(batchLength).fill({}) },\n });\n expect(getRestBaseWeight(ctx)).toBe(expected);\n }\n });\n\n it('estimates candleSnapshot extra weight with 5000 cap', () => {\n const intervalMs = 60_000;\n const candles = 10_000;\n const ctx = getRestRequestContext('POST', 'info', {\n type: 'candleSnapshot',\n req: { interval: '1m', startTime: 0, endTime: candles * intervalMs },\n });\n expect(getRestEstimatedExtraWeight(ctx)).toBe(Math.ceil(5000 / 60));\n });\n\n it('returns zero extra weight for invalid candleSnapshot inputs', () => {\n const invalidIntervalCtx = getRestRequestContext('POST', 'info', {\n type: 'candleSnapshot',\n req: { interval: '2m', startTime: 0, endTime: 60_000 },\n });\n expect(getRestEstimatedExtraWeight(invalidIntervalCtx)).toBe(0);\n\n const sameTimeCtx = getRestRequestContext('POST', 'info', {\n type: 'candleSnapshot',\n req: { interval: '1m', startTime: 0, endTime: 0 },\n });\n expect(getRestEstimatedExtraWeight(sameTimeCtx)).toBe(0);\n\n const missingReqCtx = getRestRequestContext('POST', 'info', { type: 'candleSnapshot' });\n expect(getRestEstimatedExtraWeight(missingReqCtx)).toBe(0);\n });\n\n it('consumes base and estimated weight before request', () => {\n const ctx = getRestRequestContext('POST', 'info', {\n type: 'candleSnapshot',\n req: { interval: '1m', startTime: 0, endTime: 120 * 60_000 },\n });\n const before = readBucket();\n const { baseWeight, estimatedExtraWeight } = beforeRestRequest({ requestKey: 'test' }, ctx);\n const after = readBucket();\n expect(baseWeight).toBe(20);\n expect(estimatedExtraWeight).toBe(2);\n expect(after).toBe(before - baseWeight - estimatedExtraWeight);\n });\n\n it('throws on invalid or excessive weights before request', () => {\n const invalidCtx = {\n method: 'POST',\n path: 'exchange',\n kind: 'exchange',\n exchangeBatchLength: Number.NaN,\n } as ReturnType<typeof getRestRequestContext>;\n expect(() => beforeRestRequest({ requestKey: 'test' }, invalidCtx)).toThrow(\n /HYPERLIQUID_REST_WEIGHT_INVALID/,\n );\n\n const maxWeight = 1200 * 10;\n const excessiveCtx = {\n method: 'POST',\n path: 'exchange',\n kind: 'exchange',\n exchangeBatchLength: (maxWeight + 1) * 40,\n } as ReturnType<typeof getRestRequestContext>;\n expect(() => beforeRestRequest({ requestKey: 'test' }, excessiveCtx)).toThrow(\n /HYPERLIQUID_REST_WEIGHT_EXCESSIVE/,\n );\n });\n\n it('applies extra weight based on response size', async () => {\n const ctx = getRestRequestContext('POST', 'info', { type: 'userFills' });\n const response = { fills: new Array(41).fill({}) };\n\n const before = readBucket();\n await afterRestResponse({ requestKey: 'test' }, ctx, response, 0);\n const after = readBucket();\n expect(before - after).toBe(Math.ceil(41 / 20));\n });\n\n it('applies delta extra weight for candleSnapshot responses', async () => {\n const ctx = getRestRequestContext('POST', 'info', { type: 'candleSnapshot' });\n const response = new Array(120).fill({});\n\n const before = readBucket();\n await afterRestResponse({ requestKey: 'test' }, ctx, response, 1);\n const after = readBucket();\n expect(before - after).toBe(1);\n });\n\n it('skips extra acquire when response weight is within estimate', async () => {\n const ctx = getRestRequestContext('POST', 'info', { type: 'userFills' });\n const response = { fills: [{}] };\n\n const before = readBucket();\n await afterRestResponse({ requestKey: 'test' }, ctx, response, 1);\n const after = readBucket();\n expect(after).toBe(before);\n });\n});\n"]}
package/lib/index.d.ts CHANGED
@@ -1,6 +1,4 @@
1
1
  import './services/exchange';
2
- import './services/markets/interest-rate';
3
- import './services/markets/ohlc';
4
2
  import './services/markets/product';
5
3
  import './services/markets/quote';
6
4
  import './services/quotes';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAC7B,OAAO,kCAAkC,CAAC;AAC1C,OAAO,yBAAyB,CAAC;AACjC,OAAO,4BAA4B,CAAC;AACpC,OAAO,0BAA0B,CAAC;AAClC,OAAO,mBAAmB,CAAC;AAC3B,OAAO,yBAAyB,CAAC;AACjC,OAAO,kCAAkC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAC7B,OAAO,4BAA4B,CAAC;AACpC,OAAO,0BAA0B,CAAC;AAClC,OAAO,mBAAmB,CAAC;AAC3B,OAAO,yBAAyB,CAAC;AACjC,OAAO,kCAAkC,CAAC"}
package/lib/index.js CHANGED
@@ -1,8 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  require("./services/exchange");
4
- require("./services/markets/interest-rate");
5
- require("./services/markets/ohlc");
6
4
  require("./services/markets/product");
7
5
  require("./services/markets/quote");
8
6
  require("./services/quotes");
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,+BAA6B;AAC7B,4CAA0C;AAC1C,mCAAiC;AACjC,sCAAoC;AACpC,oCAAkC;AAClC,6BAA2B;AAC3B,mCAAiC;AACjC,4CAA0C","sourcesContent":["import './services/exchange';\nimport './services/markets/interest-rate';\nimport './services/markets/ohlc';\nimport './services/markets/product';\nimport './services/markets/quote';\nimport './services/quotes';\nimport './services/ohlc-service';\nimport './services/interest-rate-service';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,+BAA6B;AAC7B,sCAAoC;AACpC,oCAAkC;AAClC,6BAA2B;AAC3B,mCAAiC;AACjC,4CAA0C","sourcesContent":["import './services/exchange';\nimport './services/markets/product';\nimport './services/markets/quote';\nimport './services/quotes';\nimport './services/ohlc-service';\nimport './services/interest-rate-service';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuants/vendor-hyperliquid",
3
- "version": "0.9.10",
3
+ "version": "0.10.1",
4
4
  "main": "lib/index.js",
5
5
  "files": [
6
6
  "dist",
@@ -12,18 +12,18 @@
12
12
  "hyperliquid": "~1.6.2",
13
13
  "ethers": "~6.13.5",
14
14
  "@msgpack/msgpack": "~3.1.2",
15
- "@yuants/protocol": "0.54.1",
16
- "@yuants/transfer": "0.2.48",
17
15
  "@yuants/cache": "0.3.12",
16
+ "@yuants/protocol": "0.54.1",
18
17
  "@yuants/data-account": "0.11.8",
19
18
  "@yuants/utils": "0.19.4",
20
- "@yuants/sql": "0.9.39",
19
+ "@yuants/transfer": "0.2.48",
21
20
  "@yuants/data-product": "0.5.9",
21
+ "@yuants/sql": "0.9.39",
22
22
  "@yuants/data-interest-rate": "0.2.8",
23
+ "@yuants/data-series": "0.3.61",
23
24
  "@yuants/data-order": "0.7.9",
25
+ "@yuants/exchange": "0.8.12",
24
26
  "@yuants/data-quote": "0.4.8",
25
- "@yuants/data-series": "0.3.61",
26
- "@yuants/exchange": "0.8.11",
27
27
  "@yuants/data-ohlc": "0.6.4"
28
28
  },
29
29
  "devDependencies": {