@3rd-eye-labs/openmm 0.1.5 → 0.1.6

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 (67) hide show
  1. package/README.md +2 -0
  2. package/dist/api/index.d.ts +3 -0
  3. package/dist/api/index.d.ts.map +1 -0
  4. package/dist/api/index.js +9 -0
  5. package/dist/api/index.js.map +1 -0
  6. package/dist/api/openapi.d.ts +3 -0
  7. package/dist/api/openapi.d.ts.map +1 -0
  8. package/dist/api/openapi.js +214 -0
  9. package/dist/api/openapi.js.map +1 -0
  10. package/dist/api/routes/balance.d.ts +3 -0
  11. package/dist/api/routes/balance.d.ts.map +1 -0
  12. package/dist/api/routes/balance.js +101 -0
  13. package/dist/api/routes/balance.js.map +1 -0
  14. package/dist/api/routes/cardano.d.ts +3 -0
  15. package/dist/api/routes/cardano.d.ts.map +1 -0
  16. package/dist/api/routes/cardano.js +177 -0
  17. package/dist/api/routes/cardano.js.map +1 -0
  18. package/dist/api/routes/health.d.ts +3 -0
  19. package/dist/api/routes/health.d.ts.map +1 -0
  20. package/dist/api/routes/health.js +115 -0
  21. package/dist/api/routes/health.js.map +1 -0
  22. package/dist/api/routes/index.d.ts +3 -0
  23. package/dist/api/routes/index.d.ts.map +1 -0
  24. package/dist/api/routes/index.js +39 -0
  25. package/dist/api/routes/index.js.map +1 -0
  26. package/dist/api/routes/orderbook.d.ts +3 -0
  27. package/dist/api/routes/orderbook.d.ts.map +1 -0
  28. package/dist/api/routes/orderbook.js +123 -0
  29. package/dist/api/routes/orderbook.js.map +1 -0
  30. package/dist/api/routes/orders.d.ts +3 -0
  31. package/dist/api/routes/orders.d.ts.map +1 -0
  32. package/dist/api/routes/orders.js +214 -0
  33. package/dist/api/routes/orders.js.map +1 -0
  34. package/dist/api/routes/price.d.ts +3 -0
  35. package/dist/api/routes/price.d.ts.map +1 -0
  36. package/dist/api/routes/price.js +124 -0
  37. package/dist/api/routes/price.js.map +1 -0
  38. package/dist/api/routes/strategy.d.ts +3 -0
  39. package/dist/api/routes/strategy.d.ts.map +1 -0
  40. package/dist/api/routes/strategy.js +345 -0
  41. package/dist/api/routes/strategy.js.map +1 -0
  42. package/dist/api/routes/ticker.d.ts +3 -0
  43. package/dist/api/routes/ticker.d.ts.map +1 -0
  44. package/dist/api/routes/ticker.js +91 -0
  45. package/dist/api/routes/ticker.js.map +1 -0
  46. package/dist/api/routes/trades.d.ts +3 -0
  47. package/dist/api/routes/trades.d.ts.map +1 -0
  48. package/dist/api/routes/trades.js +129 -0
  49. package/dist/api/routes/trades.js.map +1 -0
  50. package/dist/api/server.d.ts +11 -0
  51. package/dist/api/server.d.ts.map +1 -0
  52. package/dist/api/server.js +65 -0
  53. package/dist/api/server.js.map +1 -0
  54. package/dist/cli/cli.js +3 -1
  55. package/dist/cli/cli.js.map +1 -1
  56. package/dist/cli/commands/serve.d.ts +3 -0
  57. package/dist/cli/commands/serve.d.ts.map +1 -0
  58. package/dist/cli/commands/serve.js +53 -0
  59. package/dist/cli/commands/serve.js.map +1 -0
  60. package/dist/config/environment.d.ts.map +1 -1
  61. package/dist/config/environment.js +8 -1
  62. package/dist/config/environment.js.map +1 -1
  63. package/dist/index.d.ts +1 -0
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +2 -0
  66. package/dist/index.js.map +1 -1
  67. package/package.json +6 -2
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.priceRoutes = priceRoutes;
4
+ const exchange_factory_1 = require("../../cli/exchange-factory");
5
+ async function priceRoutes(app) {
6
+ // GET /price/compare - Cross-exchange price comparison (QBT-367)
7
+ app.get('/price/compare', {
8
+ schema: {
9
+ tags: ['Price'],
10
+ summary: 'Cross-exchange price comparison',
11
+ description: 'Compares prices across multiple exchanges and identifies arbitrage opportunities.',
12
+ querystring: {
13
+ type: 'object',
14
+ required: ['symbol'],
15
+ properties: {
16
+ symbol: { type: 'string', description: 'Trading pair', example: 'BTC/USDT' },
17
+ exchanges: {
18
+ type: 'string',
19
+ description: 'Comma-separated list of exchanges (default: all)',
20
+ example: 'mexc,gateio,bitget',
21
+ },
22
+ },
23
+ },
24
+ response: {
25
+ 200: {
26
+ type: 'object',
27
+ properties: {
28
+ symbol: { type: 'string' },
29
+ prices: {
30
+ type: 'array',
31
+ items: {
32
+ type: 'object',
33
+ properties: {
34
+ exchange: { type: 'string' },
35
+ bid: { type: 'number' },
36
+ ask: { type: 'number' },
37
+ last: { type: 'number' },
38
+ spread: { type: 'number' },
39
+ spreadPercent: { type: 'number' },
40
+ },
41
+ },
42
+ },
43
+ bestBid: {
44
+ type: 'object',
45
+ properties: {
46
+ exchange: { type: 'string' },
47
+ price: { type: 'number' },
48
+ },
49
+ },
50
+ bestAsk: {
51
+ type: 'object',
52
+ properties: {
53
+ exchange: { type: 'string' },
54
+ price: { type: 'number' },
55
+ },
56
+ },
57
+ arbitrageOpportunity: { type: 'number', description: 'Best bid - best ask (positive = arb exists)' },
58
+ arbitragePercent: { type: 'number', description: 'Arbitrage as percentage' },
59
+ timestamp: { type: 'number' },
60
+ },
61
+ },
62
+ 500: {
63
+ type: 'object',
64
+ properties: { error: { type: 'string' } },
65
+ },
66
+ },
67
+ },
68
+ }, async (request, reply) => {
69
+ const { symbol, exchanges: exchangesParam } = request.query;
70
+ const allExchanges = ['mexc', 'gateio', 'bitget', 'kraken'];
71
+ const targetExchanges = exchangesParam
72
+ ? exchangesParam.split(',').filter(e => allExchanges.includes(e))
73
+ : allExchanges;
74
+ const prices = [];
75
+ // Fetch prices from all exchanges in parallel
76
+ const results = await Promise.allSettled(targetExchanges.map(async (exchange) => {
77
+ try {
78
+ const connector = await exchange_factory_1.ExchangeFactory.getExchange(exchange);
79
+ const ticker = await connector.getTicker(symbol);
80
+ const spread = ticker.ask - ticker.bid;
81
+ const midPrice = (ticker.ask + ticker.bid) / 2;
82
+ const spreadPercent = midPrice > 0 ? (spread / midPrice) * 100 : 0;
83
+ return {
84
+ exchange,
85
+ bid: ticker.bid,
86
+ ask: ticker.ask,
87
+ last: ticker.last,
88
+ spread,
89
+ spreadPercent: Math.round(spreadPercent * 10000) / 10000,
90
+ };
91
+ }
92
+ catch {
93
+ return null;
94
+ }
95
+ }));
96
+ // Collect successful results
97
+ for (const result of results) {
98
+ if (result.status === 'fulfilled' && result.value) {
99
+ prices.push(result.value);
100
+ }
101
+ }
102
+ if (prices.length === 0) {
103
+ return reply.status(500).send({ error: 'Failed to fetch prices from any exchange' });
104
+ }
105
+ // Find best bid and ask
106
+ const bestBidPrice = prices.reduce((max, p) => p.bid > max.bid ? p : max, prices[0]);
107
+ const bestAskPrice = prices.reduce((min, p) => p.ask < min.ask ? p : min, prices[0]);
108
+ // Calculate arbitrage opportunity
109
+ const arbitrageOpportunity = bestBidPrice.bid - bestAskPrice.ask;
110
+ const arbitragePercent = bestAskPrice.ask > 0
111
+ ? (arbitrageOpportunity / bestAskPrice.ask) * 100
112
+ : 0;
113
+ return {
114
+ symbol,
115
+ prices,
116
+ bestBid: { exchange: bestBidPrice.exchange, price: bestBidPrice.bid },
117
+ bestAsk: { exchange: bestAskPrice.exchange, price: bestAskPrice.ask },
118
+ arbitrageOpportunity: Math.round(arbitrageOpportunity * 100000000) / 100000000,
119
+ arbitragePercent: Math.round(arbitragePercent * 10000) / 10000,
120
+ timestamp: Date.now(),
121
+ };
122
+ });
123
+ }
124
+ //# sourceMappingURL=price.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"price.js","sourceRoot":"","sources":["../../../src/api/routes/price.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { FastifyInstance } from 'fastify';
2
+ export declare function strategyRoutes(app: FastifyInstance): Promise<void>;
3
+ //# sourceMappingURL=strategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy.d.ts","sourceRoot":"","sources":["../../../src/api/routes/strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAoDxE,wBAAsB,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAiVxE"}
@@ -0,0 +1,345 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.strategyRoutes = strategyRoutes;
4
+ const grid_strategy_1 = require("../../strategies/grid/grid-strategy");
5
+ const exchange_factory_1 = require("../../cli/exchange-factory");
6
+ const utils_1 = require("../../utils");
7
+ const logger = (0, utils_1.createLogger)('strategy-api');
8
+ // In-memory strategy store (for demo - production would use persistent storage)
9
+ const activeStrategies = new Map();
10
+ async function strategyRoutes(app) {
11
+ // POST /strategy/grid - Start a grid strategy (QBT-362)
12
+ app.post('/strategy/grid', {
13
+ schema: {
14
+ tags: ['Strategy'],
15
+ summary: 'Start a grid trading strategy',
16
+ description: 'Creates and starts a new grid trading strategy with the specified parameters.',
17
+ body: {
18
+ type: 'object',
19
+ required: ['exchange', 'symbol', 'lowerPrice', 'upperPrice', 'gridLevels', 'orderSize'],
20
+ properties: {
21
+ exchange: { type: 'string', enum: ['mexc', 'gateio', 'bitget', 'kraken'] },
22
+ symbol: { type: 'string', description: 'Trading pair', example: 'BTC/USDT' },
23
+ lowerPrice: { type: 'number', minimum: 0, description: 'Lower price bound' },
24
+ upperPrice: { type: 'number', minimum: 0, description: 'Upper price bound' },
25
+ gridLevels: { type: 'integer', minimum: 2, maximum: 100, description: 'Number of grid levels' },
26
+ orderSize: { type: 'number', minimum: 0, description: 'Size per order in quote currency' },
27
+ gridSpacing: { type: 'number', minimum: 0, description: 'Custom spacing (default: auto-calculated)' },
28
+ },
29
+ },
30
+ response: {
31
+ 200: {
32
+ type: 'object',
33
+ properties: {
34
+ id: { type: 'string' },
35
+ status: { type: 'string' },
36
+ message: { type: 'string' },
37
+ config: {
38
+ type: 'object',
39
+ properties: {
40
+ exchange: { type: 'string' },
41
+ symbol: { type: 'string' },
42
+ lowerPrice: { type: 'number' },
43
+ upperPrice: { type: 'number' },
44
+ gridLevels: { type: 'number' },
45
+ orderSize: { type: 'number' },
46
+ gridSpacing: { type: 'number' },
47
+ },
48
+ },
49
+ },
50
+ },
51
+ 400: {
52
+ type: 'object',
53
+ properties: { error: { type: 'string' } },
54
+ },
55
+ 500: {
56
+ type: 'object',
57
+ properties: { error: { type: 'string' } },
58
+ },
59
+ },
60
+ },
61
+ }, async (request, reply) => {
62
+ const { exchange, symbol, lowerPrice, upperPrice, gridLevels, orderSize, gridSpacing } = request.body;
63
+ // Validate price range
64
+ if (lowerPrice >= upperPrice) {
65
+ return reply.status(400).send({ error: 'lowerPrice must be less than upperPrice' });
66
+ }
67
+ // Calculate grid spacing if not provided
68
+ const calculatedSpacing = gridSpacing ?? (upperPrice - lowerPrice) / gridLevels;
69
+ // Generate unique strategy ID
70
+ const strategyId = `grid-${exchange}-${symbol.replace('/', '-')}-${Date.now()}`;
71
+ try {
72
+ // Get exchange connector
73
+ const connector = await exchange_factory_1.ExchangeFactory.getExchange(exchange);
74
+ // Create strategy config
75
+ const config = {
76
+ id: strategyId,
77
+ type: 'grid',
78
+ symbol,
79
+ exchange,
80
+ accountId: 'default',
81
+ enabled: true,
82
+ gridConfig: {
83
+ symbol,
84
+ gridLevels,
85
+ gridSpacing: calculatedSpacing,
86
+ orderSize,
87
+ minConfidence: 0.6,
88
+ priceDeviationThreshold: 0.015,
89
+ adjustmentDebounce: 2000,
90
+ },
91
+ parameters: {
92
+ gridLevels,
93
+ gridSpacing: calculatedSpacing,
94
+ orderSize,
95
+ upperPrice,
96
+ lowerPrice,
97
+ },
98
+ };
99
+ // Create and initialize strategy
100
+ const strategy = new grid_strategy_1.GridStrategy(strategyId);
101
+ strategy.setExchangeConnector(connector);
102
+ await strategy.initialize(config);
103
+ // Store strategy reference
104
+ activeStrategies.set(strategyId, {
105
+ strategy,
106
+ config,
107
+ startedAt: Date.now(),
108
+ filledOrders: 0,
109
+ profit: 0,
110
+ });
111
+ // Start strategy (async - don't await)
112
+ strategy.start().catch((err) => {
113
+ logger.error(`Strategy ${strategyId} failed: ${err instanceof Error ? err.message : String(err)}`);
114
+ const stored = activeStrategies.get(strategyId);
115
+ if (stored) {
116
+ stored.strategy.stop();
117
+ }
118
+ });
119
+ logger.info(`Started grid strategy: ${strategyId}`);
120
+ return {
121
+ id: strategyId,
122
+ status: 'running',
123
+ message: 'Grid strategy started successfully',
124
+ config: {
125
+ exchange,
126
+ symbol,
127
+ lowerPrice,
128
+ upperPrice,
129
+ gridLevels,
130
+ orderSize,
131
+ gridSpacing: calculatedSpacing,
132
+ },
133
+ };
134
+ }
135
+ catch (error) {
136
+ const message = error instanceof Error ? error.message : 'Unknown error';
137
+ logger.error(`Failed to start grid strategy: ${message}`);
138
+ return reply.status(500).send({ error: `Failed to start strategy: ${message}` });
139
+ }
140
+ });
141
+ // DELETE /strategy/grid - Stop a grid strategy (QBT-363)
142
+ app.delete('/strategy/grid', {
143
+ schema: {
144
+ tags: ['Strategy'],
145
+ summary: 'Stop a grid trading strategy',
146
+ description: 'Stops a running grid strategy and optionally cancels all open orders.',
147
+ body: {
148
+ type: 'object',
149
+ required: ['id'],
150
+ properties: {
151
+ id: { type: 'string', description: 'Strategy ID to stop' },
152
+ cancelOrders: { type: 'boolean', default: true, description: 'Cancel all open orders' },
153
+ },
154
+ },
155
+ response: {
156
+ 200: {
157
+ type: 'object',
158
+ properties: {
159
+ success: { type: 'boolean' },
160
+ id: { type: 'string' },
161
+ message: { type: 'string' },
162
+ summary: {
163
+ type: 'object',
164
+ properties: {
165
+ runningTime: { type: 'number', description: 'Running time in ms' },
166
+ filledOrders: { type: 'number' },
167
+ profit: { type: 'number' },
168
+ },
169
+ },
170
+ },
171
+ },
172
+ 404: {
173
+ type: 'object',
174
+ properties: { error: { type: 'string' } },
175
+ },
176
+ 500: {
177
+ type: 'object',
178
+ properties: { error: { type: 'string' } },
179
+ },
180
+ },
181
+ },
182
+ }, async (request, reply) => {
183
+ const { id, cancelOrders = true } = request.body;
184
+ const stored = activeStrategies.get(id);
185
+ if (!stored) {
186
+ return reply.status(404).send({ error: `Strategy not found: ${id}` });
187
+ }
188
+ try {
189
+ // Stop the strategy
190
+ await stored.strategy.stop();
191
+ // Calculate summary
192
+ const runningTime = Date.now() - stored.startedAt;
193
+ const summary = {
194
+ runningTime,
195
+ filledOrders: stored.filledOrders,
196
+ profit: stored.profit,
197
+ };
198
+ // Remove from active strategies
199
+ activeStrategies.delete(id);
200
+ logger.info(`Stopped grid strategy: ${id}`);
201
+ return {
202
+ success: true,
203
+ id,
204
+ message: `Strategy stopped${cancelOrders ? ' and orders cancelled' : ''}`,
205
+ summary,
206
+ };
207
+ }
208
+ catch (error) {
209
+ const message = error instanceof Error ? error.message : 'Unknown error';
210
+ logger.error(`Failed to stop grid strategy: ${message}`);
211
+ return reply.status(500).send({ error: `Failed to stop strategy: ${message}` });
212
+ }
213
+ });
214
+ // GET /strategy/grid/status - Get grid strategy status (QBT-364)
215
+ app.get('/strategy/grid/status', {
216
+ schema: {
217
+ tags: ['Strategy'],
218
+ summary: 'Get grid strategy status',
219
+ description: 'Returns the status of a specific strategy or all active strategies.',
220
+ querystring: {
221
+ type: 'object',
222
+ properties: {
223
+ id: { type: 'string', description: 'Strategy ID (optional, returns all if omitted)' },
224
+ },
225
+ },
226
+ response: {
227
+ 200: {
228
+ type: 'object',
229
+ properties: {
230
+ strategies: {
231
+ type: 'array',
232
+ items: {
233
+ type: 'object',
234
+ properties: {
235
+ id: { type: 'string' },
236
+ status: { type: 'string' },
237
+ exchange: { type: 'string' },
238
+ symbol: { type: 'string' },
239
+ lowerPrice: { type: 'number' },
240
+ upperPrice: { type: 'number' },
241
+ gridLevels: { type: 'number' },
242
+ orderSize: { type: 'number' },
243
+ openOrders: { type: 'number' },
244
+ filledOrders: { type: 'number' },
245
+ profit: { type: 'number' },
246
+ startedAt: { type: 'number' },
247
+ runningTime: { type: 'number' },
248
+ },
249
+ },
250
+ },
251
+ count: { type: 'number' },
252
+ },
253
+ },
254
+ 404: {
255
+ type: 'object',
256
+ properties: { error: { type: 'string' } },
257
+ },
258
+ },
259
+ },
260
+ }, async (request, reply) => {
261
+ const { id } = request.query;
262
+ // If specific ID requested
263
+ if (id) {
264
+ const stored = activeStrategies.get(id);
265
+ if (!stored) {
266
+ return reply.status(404).send({ error: `Strategy not found: ${id}` });
267
+ }
268
+ const status = buildStrategyStatus(id, stored);
269
+ return {
270
+ strategies: [status],
271
+ count: 1,
272
+ };
273
+ }
274
+ // Return all active strategies
275
+ const strategies = [];
276
+ for (const [strategyId, stored] of activeStrategies.entries()) {
277
+ strategies.push(buildStrategyStatus(strategyId, stored));
278
+ }
279
+ return {
280
+ strategies,
281
+ count: strategies.length,
282
+ };
283
+ });
284
+ // GET /strategy/grid/list - List all active grid strategies
285
+ app.get('/strategy/grid/list', {
286
+ schema: {
287
+ tags: ['Strategy'],
288
+ summary: 'List all active grid strategies',
289
+ description: 'Returns a list of all currently running grid strategies.',
290
+ response: {
291
+ 200: {
292
+ type: 'object',
293
+ properties: {
294
+ strategies: {
295
+ type: 'array',
296
+ items: {
297
+ type: 'object',
298
+ properties: {
299
+ id: { type: 'string' },
300
+ exchange: { type: 'string' },
301
+ symbol: { type: 'string' },
302
+ status: { type: 'string' },
303
+ startedAt: { type: 'number' },
304
+ },
305
+ },
306
+ },
307
+ count: { type: 'number' },
308
+ },
309
+ },
310
+ },
311
+ },
312
+ }, async () => {
313
+ const strategies = Array.from(activeStrategies.entries()).map(([id, stored]) => ({
314
+ id,
315
+ exchange: stored.config.exchange,
316
+ symbol: stored.config.symbol,
317
+ status: stored.strategy.currentStatus,
318
+ startedAt: stored.startedAt,
319
+ }));
320
+ return {
321
+ strategies,
322
+ count: strategies.length,
323
+ };
324
+ });
325
+ }
326
+ // Helper function to build status response
327
+ function buildStrategyStatus(id, stored) {
328
+ const now = Date.now();
329
+ return {
330
+ id,
331
+ status: stored.strategy.currentStatus,
332
+ exchange: stored.config.exchange,
333
+ symbol: stored.config.symbol,
334
+ lowerPrice: stored.config.parameters.lowerPrice,
335
+ upperPrice: stored.config.parameters.upperPrice,
336
+ gridLevels: stored.config.parameters.gridLevels,
337
+ orderSize: stored.config.parameters.orderSize,
338
+ openOrders: 0, // TODO: Implement getOpenOrders in GridStrategy
339
+ filledOrders: stored.filledOrders,
340
+ profit: stored.profit,
341
+ startedAt: stored.startedAt,
342
+ runningTime: now - stored.startedAt,
343
+ };
344
+ }
345
+ //# sourceMappingURL=strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy.js","sourceRoot":"","sources":["../../../src/api/routes/strategy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { FastifyInstance } from 'fastify';
2
+ export declare function tickerRoutes(app: FastifyInstance): Promise<void>;
3
+ //# sourceMappingURL=ticker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ticker.d.ts","sourceRoot":"","sources":["../../../src/api/routes/ticker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAsBxE,wBAAsB,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAyFtE"}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tickerRoutes = tickerRoutes;
4
+ const exchange_factory_1 = require("../../cli/exchange-factory");
5
+ async function tickerRoutes(app) {
6
+ app.get('/ticker', {
7
+ schema: {
8
+ tags: ['Market Data'],
9
+ summary: 'Get ticker data for a trading pair',
10
+ description: 'Returns current price, bid/ask, spread, and 24h statistics for a trading pair on a specific exchange.',
11
+ querystring: {
12
+ type: 'object',
13
+ required: ['exchange', 'symbol'],
14
+ properties: {
15
+ exchange: {
16
+ type: 'string',
17
+ enum: ['mexc', 'gateio', 'bitget', 'kraken'],
18
+ description: 'Exchange to query',
19
+ },
20
+ symbol: {
21
+ type: 'string',
22
+ description: 'Trading pair (e.g., BTC/USDT, ETH/USDT)',
23
+ example: 'BTC/USDT',
24
+ },
25
+ },
26
+ },
27
+ response: {
28
+ 200: {
29
+ type: 'object',
30
+ properties: {
31
+ exchange: { type: 'string' },
32
+ symbol: { type: 'string' },
33
+ last: { type: 'number', description: 'Last traded price' },
34
+ bid: { type: 'number', description: 'Best bid price' },
35
+ ask: { type: 'number', description: 'Best ask price' },
36
+ spread: { type: 'number', description: 'Absolute spread (ask - bid)' },
37
+ spreadPercent: { type: 'number', description: 'Spread as percentage of mid price' },
38
+ baseVolume: { type: 'number', description: '24h volume in base currency' },
39
+ quoteVolume: { type: 'number', description: '24h volume in quote currency' },
40
+ timestamp: { type: 'number', description: 'Data timestamp (ms)' },
41
+ },
42
+ },
43
+ 400: {
44
+ type: 'object',
45
+ properties: {
46
+ error: { type: 'string' },
47
+ },
48
+ },
49
+ 500: {
50
+ type: 'object',
51
+ properties: {
52
+ error: { type: 'string' },
53
+ },
54
+ },
55
+ },
56
+ },
57
+ }, async (request, reply) => {
58
+ const { exchange, symbol } = request.query;
59
+ if (!exchange || !symbol) {
60
+ return reply.status(400).send({ error: 'Missing required parameters: exchange and symbol' });
61
+ }
62
+ const validExchanges = ['mexc', 'gateio', 'bitget', 'kraken'];
63
+ if (!validExchanges.includes(exchange)) {
64
+ return reply.status(400).send({ error: `Invalid exchange. Must be one of: ${validExchanges.join(', ')}` });
65
+ }
66
+ try {
67
+ const connector = await exchange_factory_1.ExchangeFactory.getExchange(exchange);
68
+ const ticker = await connector.getTicker(symbol);
69
+ const spread = ticker.ask - ticker.bid;
70
+ const midPrice = (ticker.ask + ticker.bid) / 2;
71
+ const spreadPercent = midPrice > 0 ? (spread / midPrice) * 100 : 0;
72
+ return {
73
+ exchange,
74
+ symbol: ticker.symbol,
75
+ last: ticker.last,
76
+ bid: ticker.bid,
77
+ ask: ticker.ask,
78
+ spread,
79
+ spreadPercent: Math.round(spreadPercent * 10000) / 10000, // 4 decimal places
80
+ baseVolume: ticker.baseVolume,
81
+ quoteVolume: ticker.quoteVolume,
82
+ timestamp: ticker.timestamp || Date.now(),
83
+ };
84
+ }
85
+ catch (error) {
86
+ const message = error instanceof Error ? error.message : 'Unknown error';
87
+ return reply.status(500).send({ error: `Failed to fetch ticker: ${message}` });
88
+ }
89
+ });
90
+ }
91
+ //# sourceMappingURL=ticker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ticker.js","sourceRoot":"","sources":["../../../src/api/routes/ticker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { FastifyInstance } from 'fastify';
2
+ export declare function tradesRoutes(app: FastifyInstance): Promise<void>;
3
+ //# sourceMappingURL=trades.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trades.d.ts","sourceRoot":"","sources":["../../../src/api/routes/trades.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAkCxE,wBAAsB,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAgItE"}