tradingview-mcp-server 0.0.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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +267 -0
  3. package/dist/api/client.d.ts +11 -0
  4. package/dist/api/client.d.ts.map +1 -0
  5. package/dist/api/client.js +45 -0
  6. package/dist/api/client.js.map +1 -0
  7. package/dist/api/types.d.ts +68 -0
  8. package/dist/api/types.d.ts.map +1 -0
  9. package/dist/api/types.js +5 -0
  10. package/dist/api/types.js.map +1 -0
  11. package/dist/index.d.ts +7 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +265 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/resources/presets.d.ts +24 -0
  16. package/dist/resources/presets.d.ts.map +1 -0
  17. package/dist/resources/presets.js +85 -0
  18. package/dist/resources/presets.js.map +1 -0
  19. package/dist/tests/cache.test.d.ts +2 -0
  20. package/dist/tests/cache.test.d.ts.map +1 -0
  21. package/dist/tests/cache.test.js +41 -0
  22. package/dist/tests/cache.test.js.map +1 -0
  23. package/dist/tests/fields.test.d.ts +2 -0
  24. package/dist/tests/fields.test.d.ts.map +1 -0
  25. package/dist/tests/fields.test.js +56 -0
  26. package/dist/tests/fields.test.js.map +1 -0
  27. package/dist/tests/presets.test.d.ts +2 -0
  28. package/dist/tests/presets.test.d.ts.map +1 -0
  29. package/dist/tests/presets.test.js +59 -0
  30. package/dist/tests/presets.test.js.map +1 -0
  31. package/dist/tests/rateLimit.test.d.ts +2 -0
  32. package/dist/tests/rateLimit.test.d.ts.map +1 -0
  33. package/dist/tests/rateLimit.test.js +44 -0
  34. package/dist/tests/rateLimit.test.js.map +1 -0
  35. package/dist/tools/fields.d.ts +8 -0
  36. package/dist/tools/fields.d.ts.map +1 -0
  37. package/dist/tools/fields.js +229 -0
  38. package/dist/tools/fields.js.map +1 -0
  39. package/dist/tools/screen.d.ts +17 -0
  40. package/dist/tools/screen.d.ts.map +1 -0
  41. package/dist/tools/screen.js +171 -0
  42. package/dist/tools/screen.js.map +1 -0
  43. package/dist/utils/cache.d.ts +13 -0
  44. package/dist/utils/cache.d.ts.map +1 -0
  45. package/dist/utils/cache.js +45 -0
  46. package/dist/utils/cache.js.map +1 -0
  47. package/dist/utils/rateLimit.d.ts +11 -0
  48. package/dist/utils/rateLimit.d.ts.map +1 -0
  49. package/dist/utils/rateLimit.js +28 -0
  50. package/dist/utils/rateLimit.js.map +1 -0
  51. package/package.json +56 -0
@@ -0,0 +1,44 @@
1
+ import { describe, it } from "node:test";
2
+ import assert from "node:assert";
3
+ import { RateLimiter } from "../utils/rateLimit.js";
4
+ describe("RateLimiter", () => {
5
+ it("should allow requests within limit", async () => {
6
+ const limiter = new RateLimiter(5); // 5 requests per minute
7
+ const start = Date.now();
8
+ // Should allow 5 requests immediately
9
+ for (let i = 0; i < 5; i++) {
10
+ await limiter.acquire();
11
+ }
12
+ const elapsed = Date.now() - start;
13
+ // Should complete quickly (within 100ms)
14
+ assert.ok(elapsed < 100, `Took too long: ${elapsed}ms`);
15
+ });
16
+ it("should throttle requests exceeding limit", async () => {
17
+ const limiter = new RateLimiter(2); // 2 requests per minute
18
+ const start = Date.now();
19
+ // First 2 requests should be fast
20
+ await limiter.acquire();
21
+ await limiter.acquire();
22
+ const afterTwo = Date.now() - start;
23
+ assert.ok(afterTwo < 100, "First two requests should be fast");
24
+ // Third request should be delayed
25
+ await limiter.acquire();
26
+ const afterThree = Date.now() - start;
27
+ // Should wait close to 60 seconds (allow some margin)
28
+ assert.ok(afterThree >= 59000, `Should wait ~60s, but only waited ${afterThree}ms`);
29
+ });
30
+ it("should handle multiple requests correctly", async () => {
31
+ const limiter = new RateLimiter(3);
32
+ // Fire 3 requests - should complete quickly
33
+ const promises = [
34
+ limiter.acquire(),
35
+ limiter.acquire(),
36
+ limiter.acquire(),
37
+ ];
38
+ const start = Date.now();
39
+ await Promise.all(promises);
40
+ const elapsed = Date.now() - start;
41
+ assert.ok(elapsed < 100, `Should complete quickly, took ${elapsed}ms`);
42
+ });
43
+ });
44
+ //# sourceMappingURL=rateLimit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rateLimit.test.js","sourceRoot":"","sources":["../../src/tests/rateLimit.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB;QAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEzB,sCAAsC;QACtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QAC1B,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QACnC,yCAAyC;QACzC,MAAM,CAAC,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE,kBAAkB,OAAO,IAAI,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB;QAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEzB,kCAAkC;QAClC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QACxB,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QAExB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QACpC,MAAM,CAAC,EAAE,CAAC,QAAQ,GAAG,GAAG,EAAE,mCAAmC,CAAC,CAAC;QAE/D,kCAAkC;QAClC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QAExB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QACtC,sDAAsD;QACtD,MAAM,CAAC,EAAE,CAAC,UAAU,IAAI,KAAK,EAAE,qCAAqC,UAAU,IAAI,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;QAEnC,4CAA4C;QAC5C,MAAM,QAAQ,GAAG;YACf,OAAO,CAAC,OAAO,EAAE;YACjB,OAAO,CAAC,OAAO,EAAE;YACjB,OAAO,CAAC,OAAO,EAAE;SAClB,CAAC;QAEF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QAEnC,MAAM,CAAC,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE,iCAAiC,OAAO,IAAI,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Field listing and metadata
3
+ */
4
+ import type { ListFieldsInput } from "../api/types.js";
5
+ export declare class FieldsTool {
6
+ listFields(input: ListFieldsInput): any;
7
+ }
8
+ //# sourceMappingURL=fields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/tools/fields.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAiB,eAAe,EAAE,MAAM,iBAAiB,CAAC;AA+MtE,qBAAa,UAAU;IACrB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,GAAG;CAyBxC"}
@@ -0,0 +1,229 @@
1
+ /**
2
+ * Field listing and metadata
3
+ */
4
+ // Common stock fields
5
+ const STOCK_FIELDS = [
6
+ // Fundamental
7
+ {
8
+ name: "market_cap_basic",
9
+ label: "Market Capitalization",
10
+ category: "fundamental",
11
+ type: "currency",
12
+ description: "Total market value of company",
13
+ },
14
+ {
15
+ name: "return_on_equity",
16
+ label: "Return on Equity (TTM)",
17
+ category: "fundamental",
18
+ type: "percent",
19
+ description: "Profitability relative to shareholder equity",
20
+ },
21
+ {
22
+ name: "price_earnings_ttm",
23
+ label: "P/E Ratio (TTM)",
24
+ category: "fundamental",
25
+ type: "number",
26
+ description: "Price to earnings ratio",
27
+ },
28
+ {
29
+ name: "price_book_fq",
30
+ label: "P/B Ratio",
31
+ category: "fundamental",
32
+ type: "number",
33
+ description: "Price to book value ratio",
34
+ },
35
+ {
36
+ name: "price_sales_ratio",
37
+ label: "P/S Ratio",
38
+ category: "fundamental",
39
+ type: "number",
40
+ description: "Price to sales ratio",
41
+ },
42
+ {
43
+ name: "debt_to_equity",
44
+ label: "Debt/Equity Ratio",
45
+ category: "fundamental",
46
+ type: "number",
47
+ description: "Total debt relative to shareholder equity",
48
+ },
49
+ {
50
+ name: "net_margin_ttm",
51
+ label: "Net Margin (TTM)",
52
+ category: "fundamental",
53
+ type: "percent",
54
+ description: "Net income as percentage of revenue",
55
+ },
56
+ {
57
+ name: "after_tax_margin",
58
+ label: "After-Tax Margin",
59
+ category: "fundamental",
60
+ type: "percent",
61
+ description: "Profit margin after taxes",
62
+ },
63
+ {
64
+ name: "operating_margin",
65
+ label: "Operating Margin",
66
+ category: "fundamental",
67
+ type: "percent",
68
+ description: "Operating income as percentage of revenue",
69
+ },
70
+ {
71
+ name: "dividend_yield_recent",
72
+ label: "Dividend Yield",
73
+ category: "fundamental",
74
+ type: "percent",
75
+ description: "Annual dividend as percentage of price",
76
+ },
77
+ {
78
+ name: "earnings_per_share_diluted_ttm",
79
+ label: "EPS (Diluted, TTM)",
80
+ category: "fundamental",
81
+ type: "currency",
82
+ description: "Earnings per share",
83
+ },
84
+ {
85
+ name: "total_revenue",
86
+ label: "Total Revenue",
87
+ category: "fundamental",
88
+ type: "currency",
89
+ description: "Total company revenue",
90
+ },
91
+ {
92
+ name: "net_income",
93
+ label: "Net Income",
94
+ category: "fundamental",
95
+ type: "currency",
96
+ description: "Total net profit",
97
+ },
98
+ // Technical
99
+ {
100
+ name: "RSI",
101
+ label: "RSI (14)",
102
+ category: "technical",
103
+ type: "number",
104
+ description: "Relative Strength Index momentum oscillator",
105
+ },
106
+ {
107
+ name: "SMA50",
108
+ label: "SMA 50",
109
+ category: "technical",
110
+ type: "number",
111
+ description: "50-day Simple Moving Average",
112
+ },
113
+ {
114
+ name: "SMA200",
115
+ label: "SMA 200",
116
+ category: "technical",
117
+ type: "number",
118
+ description: "200-day Simple Moving Average",
119
+ },
120
+ {
121
+ name: "EMA10",
122
+ label: "EMA 10",
123
+ category: "technical",
124
+ type: "number",
125
+ description: "10-day Exponential Moving Average",
126
+ },
127
+ {
128
+ name: "Volatility.M",
129
+ label: "Volatility (Monthly)",
130
+ category: "technical",
131
+ type: "percent",
132
+ description: "1-month price volatility",
133
+ },
134
+ {
135
+ name: "ATR",
136
+ label: "Average True Range",
137
+ category: "technical",
138
+ type: "number",
139
+ description: "Measure of volatility",
140
+ },
141
+ {
142
+ name: "ADX",
143
+ label: "ADX",
144
+ category: "technical",
145
+ type: "number",
146
+ description: "Average Directional Index",
147
+ },
148
+ // Performance
149
+ {
150
+ name: "close",
151
+ label: "Current Price",
152
+ category: "performance",
153
+ type: "currency",
154
+ description: "Current stock price",
155
+ },
156
+ {
157
+ name: "change",
158
+ label: "Change %",
159
+ category: "performance",
160
+ type: "percent",
161
+ description: "Daily price change percentage",
162
+ },
163
+ {
164
+ name: "volume",
165
+ label: "Volume",
166
+ category: "performance",
167
+ type: "number",
168
+ description: "Trading volume",
169
+ },
170
+ {
171
+ name: "Perf.W",
172
+ label: "Weekly Performance",
173
+ category: "performance",
174
+ type: "percent",
175
+ description: "1-week price change",
176
+ },
177
+ {
178
+ name: "Perf.1M",
179
+ label: "Monthly Performance",
180
+ category: "performance",
181
+ type: "percent",
182
+ description: "1-month price change",
183
+ },
184
+ {
185
+ name: "Perf.3M",
186
+ label: "3-Month Performance",
187
+ category: "performance",
188
+ type: "percent",
189
+ description: "3-month price change",
190
+ },
191
+ {
192
+ name: "Perf.Y",
193
+ label: "Yearly Performance",
194
+ category: "performance",
195
+ type: "percent",
196
+ description: "1-year price change",
197
+ },
198
+ {
199
+ name: "Perf.YTD",
200
+ label: "YTD Performance",
201
+ category: "performance",
202
+ type: "percent",
203
+ description: "Year-to-date price change",
204
+ },
205
+ ];
206
+ export class FieldsTool {
207
+ listFields(input) {
208
+ const { asset_type = "stock", category } = input;
209
+ // For MVP, only stock fields are implemented
210
+ if (asset_type !== "stock") {
211
+ return {
212
+ message: `Fields for ${asset_type} will be available in future versions`,
213
+ fields: [],
214
+ };
215
+ }
216
+ let fields = STOCK_FIELDS;
217
+ // Filter by category if specified
218
+ if (category) {
219
+ fields = fields.filter((f) => f.category === category);
220
+ }
221
+ return {
222
+ asset_type,
223
+ category: category || "all",
224
+ field_count: fields.length,
225
+ fields,
226
+ };
227
+ }
228
+ }
229
+ //# sourceMappingURL=fields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.js","sourceRoot":"","sources":["../../src/tools/fields.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Stock screening tool
3
+ */
4
+ import type { ScreenStocksInput } from "../api/types.js";
5
+ import type { TradingViewClient } from "../api/client.js";
6
+ import type { Cache } from "../utils/cache.js";
7
+ import type { RateLimiter } from "../utils/rateLimit.js";
8
+ export declare class ScreenTool {
9
+ private client;
10
+ private cache;
11
+ private rateLimiter;
12
+ constructor(client: TradingViewClient, cache: Cache, rateLimiter: RateLimiter);
13
+ screenStocks(input: ScreenStocksInput): Promise<any>;
14
+ screenForex(input: Omit<ScreenStocksInput, "markets">): Promise<any>;
15
+ screenCrypto(input: Omit<ScreenStocksInput, "markets">): Promise<any>;
16
+ }
17
+ //# sourceMappingURL=screen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../src/tools/screen.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,iBAAiB,EAIlB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AA4BzD,qBAAa,UAAU;IAEnB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,WAAW;gBAFX,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,WAAW;IAG5B,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC;IAoFpD,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IA+CpE,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;CA8C5E"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Stock screening tool
3
+ */
4
+ // Operator mapping from MCP to TradingView API
5
+ const OPERATOR_MAP = {
6
+ greater: "greater",
7
+ less: "less",
8
+ greater_or_equal: "egreater",
9
+ less_or_equal: "eless",
10
+ equal: "equal",
11
+ not_equal: "nequal",
12
+ in_range: "in_range",
13
+ not_in_range: "not_in_range",
14
+ crosses: "crosses",
15
+ crosses_above: "crosses_above",
16
+ crosses_below: "crosses_below",
17
+ match: "match",
18
+ };
19
+ // Common fields to include in response
20
+ const DEFAULT_COLUMNS = [
21
+ "name",
22
+ "close",
23
+ "market_cap_basic",
24
+ "return_on_equity",
25
+ "price_earnings_ttm",
26
+ "debt_to_equity",
27
+ ];
28
+ export class ScreenTool {
29
+ client;
30
+ cache;
31
+ rateLimiter;
32
+ constructor(client, cache, rateLimiter) {
33
+ this.client = client;
34
+ this.cache = cache;
35
+ this.rateLimiter = rateLimiter;
36
+ }
37
+ async screenStocks(input) {
38
+ const { filters, markets = ["america"], sort_by = "market_cap_basic", sort_order = "desc", limit = 20, } = input;
39
+ // Validate limit
40
+ if (limit < 1 || limit > 200) {
41
+ throw new Error("Limit must be between 1 and 200");
42
+ }
43
+ // Build cache key
44
+ const cacheKey = JSON.stringify({ filters, markets, sort_by, sort_order, limit });
45
+ // Check cache
46
+ const cached = this.cache.get(cacheKey);
47
+ if (cached) {
48
+ return cached;
49
+ }
50
+ // Convert filters to TradingView format
51
+ const tvFilters = filters.map((f) => {
52
+ const operation = OPERATOR_MAP[f.operator];
53
+ if (!operation) {
54
+ throw new Error(`Unknown operator: ${f.operator}`);
55
+ }
56
+ return {
57
+ left: f.field,
58
+ operation,
59
+ right: f.value,
60
+ };
61
+ });
62
+ // Extract unique fields from filters for columns
63
+ const filterFields = filters.map((f) => f.field);
64
+ const columns = [...new Set([...DEFAULT_COLUMNS, ...filterFields])];
65
+ // Build request
66
+ const request = {
67
+ filter: tvFilters,
68
+ columns,
69
+ sort: {
70
+ sortBy: sort_by,
71
+ sortOrder: sort_order,
72
+ },
73
+ range: [0, limit],
74
+ options: { lang: "en" },
75
+ symbols: {
76
+ query: { types: [] },
77
+ tickers: [],
78
+ },
79
+ markets,
80
+ };
81
+ // Rate limit
82
+ await this.rateLimiter.acquire();
83
+ // Make request
84
+ const response = await this.client.scanStocks(request);
85
+ // Format response
86
+ const result = {
87
+ total_count: response.totalCount,
88
+ stocks: response.data.map((item) => {
89
+ const stock = { symbol: item.s };
90
+ columns.forEach((col, idx) => {
91
+ stock[col] = item.d[idx];
92
+ });
93
+ return stock;
94
+ }),
95
+ };
96
+ // Cache result
97
+ this.cache.set(cacheKey, result);
98
+ return result;
99
+ }
100
+ async screenForex(input) {
101
+ // Similar to screenStocks but without markets
102
+ const { filters, sort_by = "volume", sort_order = "desc", limit = 20, } = input;
103
+ const cacheKey = JSON.stringify({ type: "forex", filters, sort_by, sort_order, limit });
104
+ const cached = this.cache.get(cacheKey);
105
+ if (cached)
106
+ return cached;
107
+ const tvFilters = filters.map((f) => ({
108
+ left: f.field,
109
+ operation: OPERATOR_MAP[f.operator] || "greater",
110
+ right: f.value,
111
+ }));
112
+ const filterFields = filters.map((f) => f.field);
113
+ const columns = [...new Set(["name", "close", "change", ...filterFields])];
114
+ const request = {
115
+ filter: tvFilters,
116
+ columns,
117
+ sort: { sortBy: sort_by, sortOrder: sort_order },
118
+ range: [0, limit],
119
+ options: { lang: "en" },
120
+ symbols: { query: { types: [] }, tickers: [] },
121
+ };
122
+ await this.rateLimiter.acquire();
123
+ const response = await this.client.scanForex(request);
124
+ const result = {
125
+ total_count: response.totalCount,
126
+ pairs: response.data.map((item) => {
127
+ const pair = { symbol: item.s };
128
+ columns.forEach((col, idx) => { pair[col] = item.d[idx]; });
129
+ return pair;
130
+ }),
131
+ };
132
+ this.cache.set(cacheKey, result);
133
+ return result;
134
+ }
135
+ async screenCrypto(input) {
136
+ // Similar to forex
137
+ const { filters, sort_by = "market_cap_basic", sort_order = "desc", limit = 20, } = input;
138
+ const cacheKey = JSON.stringify({ type: "crypto", filters, sort_by, sort_order, limit });
139
+ const cached = this.cache.get(cacheKey);
140
+ if (cached)
141
+ return cached;
142
+ const tvFilters = filters.map((f) => ({
143
+ left: f.field,
144
+ operation: OPERATOR_MAP[f.operator] || "greater",
145
+ right: f.value,
146
+ }));
147
+ const filterFields = filters.map((f) => f.field);
148
+ const columns = [...new Set(["name", "close", "market_cap_basic", "change", ...filterFields])];
149
+ const request = {
150
+ filter: tvFilters,
151
+ columns,
152
+ sort: { sortBy: sort_by, sortOrder: sort_order },
153
+ range: [0, limit],
154
+ options: { lang: "en" },
155
+ symbols: { query: { types: [] }, tickers: [] },
156
+ };
157
+ await this.rateLimiter.acquire();
158
+ const response = await this.client.scanCrypto(request);
159
+ const result = {
160
+ total_count: response.totalCount,
161
+ cryptocurrencies: response.data.map((item) => {
162
+ const crypto = { symbol: item.s };
163
+ columns.forEach((col, idx) => { crypto[col] = item.d[idx]; });
164
+ return crypto;
165
+ }),
166
+ };
167
+ this.cache.set(cacheKey, result);
168
+ return result;
169
+ }
170
+ }
171
+ //# sourceMappingURL=screen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screen.js","sourceRoot":"","sources":["../../src/tools/screen.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Simple in-memory cache with TTL
3
+ */
4
+ export declare class Cache {
5
+ private store;
6
+ private ttl;
7
+ constructor(ttlSeconds?: number);
8
+ get(key: string): any | null;
9
+ set(key: string, data: any): void;
10
+ clear(): void;
11
+ startCleanup(intervalMs?: number): NodeJS.Timeout;
12
+ }
13
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/utils/cache.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,qBAAa,KAAK;IAChB,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,GAAG,CAAS;gBAER,UAAU,GAAE,MAAY;IAIpC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;IAc5B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,IAAI;IASjC,KAAK,IAAI,IAAI;IAKb,YAAY,CAAC,UAAU,GAAE,MAAc,GAAG,MAAM,CAAC,OAAO;CAUzD"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Simple in-memory cache with TTL
3
+ */
4
+ export class Cache {
5
+ store = new Map();
6
+ ttl;
7
+ constructor(ttlSeconds = 300) {
8
+ this.ttl = ttlSeconds * 1000;
9
+ }
10
+ get(key) {
11
+ if (this.ttl === 0)
12
+ return null; // Caching disabled
13
+ const entry = this.store.get(key);
14
+ if (!entry)
15
+ return null;
16
+ if (Date.now() >= entry.expires) {
17
+ this.store.delete(key);
18
+ return null;
19
+ }
20
+ return entry.data;
21
+ }
22
+ set(key, data) {
23
+ if (this.ttl === 0)
24
+ return; // Caching disabled
25
+ this.store.set(key, {
26
+ data,
27
+ expires: Date.now() + this.ttl,
28
+ });
29
+ }
30
+ clear() {
31
+ this.store.clear();
32
+ }
33
+ // Periodic cleanup of expired entries
34
+ startCleanup(intervalMs = 60000) {
35
+ return setInterval(() => {
36
+ const now = Date.now();
37
+ for (const [key, entry] of this.store.entries()) {
38
+ if (now >= entry.expires) {
39
+ this.store.delete(key);
40
+ }
41
+ }
42
+ }, intervalMs);
43
+ }
44
+ }
45
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/utils/cache.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,MAAM,OAAO,KAAK;IACR,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;IACtC,GAAG,CAAS;IAEpB,YAAY,aAAqB,GAAG;QAClC,IAAI,CAAC,GAAG,GAAG,UAAU,GAAG,IAAI,CAAC;IAC/B,CAAC;IAED,GAAG,CAAC,GAAW;QACb,IAAI,IAAI,CAAC,GAAG,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,CAAC,mBAAmB;QAEpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QAExB,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAChC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,IAAS;QACxB,IAAI,IAAI,CAAC,GAAG,KAAK,CAAC;YAAE,OAAO,CAAC,mBAAmB;QAE/C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE;YAClB,IAAI;YACJ,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG;SAC/B,CAAC,CAAC;IACL,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,sCAAsC;IACtC,YAAY,CAAC,aAAqB,KAAK;QACrC,OAAO,WAAW,CAAC,GAAG,EAAE;YACtB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;gBAChD,IAAI,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;oBACzB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC;QACH,CAAC,EAAE,UAAU,CAAC,CAAC;IACjB,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Simple rate limiter
3
+ */
4
+ export declare class RateLimiter {
5
+ private requests;
6
+ private maxRequests;
7
+ private windowMs;
8
+ constructor(requestsPerMinute?: number);
9
+ acquire(): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=rateLimit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rateLimit.d.ts","sourceRoot":"","sources":["../../src/utils/rateLimit.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAS;gBAEb,iBAAiB,GAAE,MAAW;IAKpC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAmB/B"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Simple rate limiter
3
+ */
4
+ export class RateLimiter {
5
+ requests = [];
6
+ maxRequests;
7
+ windowMs;
8
+ constructor(requestsPerMinute = 10) {
9
+ this.maxRequests = requestsPerMinute;
10
+ this.windowMs = 60000; // 1 minute
11
+ }
12
+ async acquire() {
13
+ const now = Date.now();
14
+ // Clean up old requests outside the window
15
+ this.requests = this.requests.filter((time) => now - time < this.windowMs);
16
+ if (this.requests.length >= this.maxRequests) {
17
+ // Calculate how long to wait
18
+ const oldestRequest = this.requests[0];
19
+ const waitTime = this.windowMs - (now - oldestRequest);
20
+ if (waitTime > 0) {
21
+ await new Promise((resolve) => setTimeout(resolve, waitTime));
22
+ return this.acquire(); // Retry after waiting
23
+ }
24
+ }
25
+ this.requests.push(now);
26
+ }
27
+ }
28
+ //# sourceMappingURL=rateLimit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rateLimit.js","sourceRoot":"","sources":["../../src/utils/rateLimit.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,OAAO,WAAW;IACd,QAAQ,GAAa,EAAE,CAAC;IACxB,WAAW,CAAS;IACpB,QAAQ,CAAS;IAEzB,YAAY,oBAA4B,EAAE;QACxC,IAAI,CAAC,WAAW,GAAG,iBAAiB,CAAC;QACrC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,WAAW;IACpC,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,2CAA2C;QAC3C,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAE3E,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAC7C,6BAA6B;YAC7B,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,GAAG,aAAa,CAAC,CAAC;YAEvD,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;gBACjB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;gBAC9D,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,sBAAsB;YAC/C,CAAC;QACH,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;CACF"}