@lightconexyz/lightcone-sdk 0.1.0

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 (158) hide show
  1. package/README.md +232 -0
  2. package/dist/api/client.d.ts +225 -0
  3. package/dist/api/client.d.ts.map +1 -0
  4. package/dist/api/client.js +452 -0
  5. package/dist/api/client.js.map +1 -0
  6. package/dist/api/error.d.ts +58 -0
  7. package/dist/api/error.d.ts.map +1 -0
  8. package/dist/api/error.js +98 -0
  9. package/dist/api/error.js.map +1 -0
  10. package/dist/api/index.d.ts +23 -0
  11. package/dist/api/index.d.ts.map +1 -0
  12. package/dist/api/index.js +51 -0
  13. package/dist/api/index.js.map +1 -0
  14. package/dist/api/types/admin.d.ts +49 -0
  15. package/dist/api/types/admin.d.ts.map +1 -0
  16. package/dist/api/types/admin.js +13 -0
  17. package/dist/api/types/admin.js.map +1 -0
  18. package/dist/api/types/index.d.ts +14 -0
  19. package/dist/api/types/index.d.ts.map +1 -0
  20. package/dist/api/types/index.js +13 -0
  21. package/dist/api/types/index.js.map +1 -0
  22. package/dist/api/types/market.d.ts +186 -0
  23. package/dist/api/types/market.d.ts.map +1 -0
  24. package/dist/api/types/market.js +6 -0
  25. package/dist/api/types/market.js.map +1 -0
  26. package/dist/api/types/order.d.ts +190 -0
  27. package/dist/api/types/order.d.ts.map +1 -0
  28. package/dist/api/types/order.js +6 -0
  29. package/dist/api/types/order.js.map +1 -0
  30. package/dist/api/types/orderbook.d.ts +36 -0
  31. package/dist/api/types/orderbook.d.ts.map +1 -0
  32. package/dist/api/types/orderbook.js +6 -0
  33. package/dist/api/types/orderbook.js.map +1 -0
  34. package/dist/api/types/position.d.ts +60 -0
  35. package/dist/api/types/position.d.ts.map +1 -0
  36. package/dist/api/types/position.js +6 -0
  37. package/dist/api/types/position.js.map +1 -0
  38. package/dist/api/types/price_history.d.ts +68 -0
  39. package/dist/api/types/price_history.d.ts.map +1 -0
  40. package/dist/api/types/price_history.js +13 -0
  41. package/dist/api/types/price_history.js.map +1 -0
  42. package/dist/api/types/trade.d.ts +67 -0
  43. package/dist/api/types/trade.d.ts.map +1 -0
  44. package/dist/api/types/trade.js +13 -0
  45. package/dist/api/types/trade.js.map +1 -0
  46. package/dist/api/validation.d.ts +24 -0
  47. package/dist/api/validation.d.ts.map +1 -0
  48. package/dist/api/validation.js +53 -0
  49. package/dist/api/validation.js.map +1 -0
  50. package/dist/auth.d.ts +80 -0
  51. package/dist/auth.d.ts.map +1 -0
  52. package/dist/auth.js +149 -0
  53. package/dist/auth.js.map +1 -0
  54. package/dist/index.d.ts +55 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +107 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/network.d.ts +5 -0
  59. package/dist/network.d.ts.map +1 -0
  60. package/dist/network.js +8 -0
  61. package/dist/network.js.map +1 -0
  62. package/dist/program/accounts.d.ts +98 -0
  63. package/dist/program/accounts.d.ts.map +1 -0
  64. package/dist/program/accounts.js +319 -0
  65. package/dist/program/accounts.js.map +1 -0
  66. package/dist/program/builder.d.ts +94 -0
  67. package/dist/program/builder.d.ts.map +1 -0
  68. package/dist/program/builder.js +175 -0
  69. package/dist/program/builder.js.map +1 -0
  70. package/dist/program/client.d.ts +56 -0
  71. package/dist/program/client.d.ts.map +1 -0
  72. package/dist/program/client.js +288 -0
  73. package/dist/program/client.js.map +1 -0
  74. package/dist/program/constants.d.ts +108 -0
  75. package/dist/program/constants.d.ts.map +1 -0
  76. package/dist/program/constants.js +112 -0
  77. package/dist/program/constants.js.map +1 -0
  78. package/dist/program/index.d.ts +14 -0
  79. package/dist/program/index.d.ts.map +1 -0
  80. package/dist/program/index.js +149 -0
  81. package/dist/program/index.js.map +1 -0
  82. package/dist/program/instructions.d.ts +248 -0
  83. package/dist/program/instructions.d.ts.map +1 -0
  84. package/dist/program/instructions.js +692 -0
  85. package/dist/program/instructions.js.map +1 -0
  86. package/dist/program/orders.d.ts +151 -0
  87. package/dist/program/orders.d.ts.map +1 -0
  88. package/dist/program/orders.js +417 -0
  89. package/dist/program/orders.js.map +1 -0
  90. package/dist/program/pda.d.ts +73 -0
  91. package/dist/program/pda.d.ts.map +1 -0
  92. package/dist/program/pda.js +131 -0
  93. package/dist/program/pda.js.map +1 -0
  94. package/dist/program/types.d.ts +380 -0
  95. package/dist/program/types.d.ts.map +1 -0
  96. package/dist/program/types.js +27 -0
  97. package/dist/program/types.js.map +1 -0
  98. package/dist/program/utils.d.ts +91 -0
  99. package/dist/program/utils.d.ts.map +1 -0
  100. package/dist/program/utils.js +219 -0
  101. package/dist/program/utils.js.map +1 -0
  102. package/dist/shared/index.d.ts +8 -0
  103. package/dist/shared/index.d.ts.map +1 -0
  104. package/dist/shared/index.js +18 -0
  105. package/dist/shared/index.js.map +1 -0
  106. package/dist/shared/price.d.ts +41 -0
  107. package/dist/shared/price.d.ts.map +1 -0
  108. package/dist/shared/price.js +57 -0
  109. package/dist/shared/price.js.map +1 -0
  110. package/dist/shared/scaling.d.ts +45 -0
  111. package/dist/shared/scaling.d.ts.map +1 -0
  112. package/dist/shared/scaling.js +84 -0
  113. package/dist/shared/scaling.js.map +1 -0
  114. package/dist/shared/types.d.ts +19 -0
  115. package/dist/shared/types.d.ts.map +1 -0
  116. package/dist/shared/types.js +23 -0
  117. package/dist/shared/types.js.map +1 -0
  118. package/dist/websocket/client.d.ts +238 -0
  119. package/dist/websocket/client.d.ts.map +1 -0
  120. package/dist/websocket/client.js +580 -0
  121. package/dist/websocket/client.js.map +1 -0
  122. package/dist/websocket/error.d.ts +47 -0
  123. package/dist/websocket/error.d.ts.map +1 -0
  124. package/dist/websocket/error.js +83 -0
  125. package/dist/websocket/error.js.map +1 -0
  126. package/dist/websocket/handlers.d.ts +97 -0
  127. package/dist/websocket/handlers.d.ts.map +1 -0
  128. package/dist/websocket/handlers.js +277 -0
  129. package/dist/websocket/handlers.js.map +1 -0
  130. package/dist/websocket/index.d.ts +38 -0
  131. package/dist/websocket/index.d.ts.map +1 -0
  132. package/dist/websocket/index.js +75 -0
  133. package/dist/websocket/index.js.map +1 -0
  134. package/dist/websocket/state/index.d.ts +7 -0
  135. package/dist/websocket/state/index.d.ts.map +1 -0
  136. package/dist/websocket/state/index.js +14 -0
  137. package/dist/websocket/state/index.js.map +1 -0
  138. package/dist/websocket/state/orderbook.d.ts +107 -0
  139. package/dist/websocket/state/orderbook.d.ts.map +1 -0
  140. package/dist/websocket/state/orderbook.js +293 -0
  141. package/dist/websocket/state/orderbook.js.map +1 -0
  142. package/dist/websocket/state/price.d.ts +108 -0
  143. package/dist/websocket/state/price.d.ts.map +1 -0
  144. package/dist/websocket/state/price.js +243 -0
  145. package/dist/websocket/state/price.js.map +1 -0
  146. package/dist/websocket/state/user.d.ts +83 -0
  147. package/dist/websocket/state/user.d.ts.map +1 -0
  148. package/dist/websocket/state/user.js +228 -0
  149. package/dist/websocket/state/user.js.map +1 -0
  150. package/dist/websocket/subscriptions.d.ts +143 -0
  151. package/dist/websocket/subscriptions.d.ts.map +1 -0
  152. package/dist/websocket/subscriptions.js +244 -0
  153. package/dist/websocket/subscriptions.js.map +1 -0
  154. package/dist/websocket/types.d.ts +417 -0
  155. package/dist/websocket/types.d.ts.map +1 -0
  156. package/dist/websocket/types.js +195 -0
  157. package/dist/websocket/types.js.map +1 -0
  158. package/package.json +75 -0
@@ -0,0 +1,452 @@
1
+ "use strict";
2
+ /**
3
+ * REST API client for Lightcone.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LightconeApiClient = exports.DEFAULT_RETRY_CONFIG = exports.DEFAULT_API_URL = void 0;
7
+ const orders_1 = require("../program/orders");
8
+ const error_1 = require("./error");
9
+ const validation_1 = require("./validation");
10
+ const auth_1 = require("../auth");
11
+ /**
12
+ * Convert a typed params object to query string record.
13
+ */
14
+ function toQueryParams(params) {
15
+ const result = {};
16
+ for (const [key, value] of Object.entries(params)) {
17
+ if (value !== undefined && value !== null) {
18
+ result[key] = String(value);
19
+ }
20
+ }
21
+ return result;
22
+ }
23
+ const network_1 = require("../network");
24
+ var network_2 = require("../network");
25
+ Object.defineProperty(exports, "DEFAULT_API_URL", { enumerable: true, get: function () { return network_2.DEFAULT_API_URL; } });
26
+ /** Default retry configuration (disabled) */
27
+ exports.DEFAULT_RETRY_CONFIG = {
28
+ maxRetries: 0,
29
+ baseDelayMs: 100,
30
+ maxDelayMs: 10000,
31
+ };
32
+ /**
33
+ * Calculate delay with exponential backoff and jitter.
34
+ * Jitter: 75-100% of calculated delay (prevents thundering herd)
35
+ */
36
+ function calculateRetryDelay(attempt, config) {
37
+ const expDelay = config.baseDelayMs * Math.pow(2, Math.min(attempt, 10));
38
+ const cappedDelay = Math.min(expDelay, config.maxDelayMs);
39
+ const jitterRange = cappedDelay * 0.25;
40
+ const jitter = Math.random() * jitterRange;
41
+ return cappedDelay - jitterRange + jitter;
42
+ }
43
+ /**
44
+ * Check if error is retryable.
45
+ */
46
+ function isRetryable(error) {
47
+ if (error.variant === "ServerError")
48
+ return true;
49
+ if (error.variant === "RateLimited")
50
+ return true;
51
+ if (error.variant === "Http")
52
+ return true; // Network errors
53
+ return false;
54
+ }
55
+ /**
56
+ * Sleep for a duration.
57
+ */
58
+ function sleep(ms) {
59
+ return new Promise((resolve) => setTimeout(resolve, ms));
60
+ }
61
+ /**
62
+ * REST API client for the Lightcone platform.
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * import { LightconeApiClient } from "@lightcone/sdk/api";
67
+ *
68
+ * const client = new LightconeApiClient();
69
+ *
70
+ * // Get all markets
71
+ * const markets = await client.getMarkets();
72
+ *
73
+ * // Get orderbook
74
+ * const orderbook = await client.getOrderbook("market1:ob1");
75
+ * ```
76
+ */
77
+ class LightconeApiClient {
78
+ baseUrl;
79
+ timeout;
80
+ headers;
81
+ retryConfig;
82
+ authToken;
83
+ constructor(config = {}) {
84
+ this.baseUrl = config.baseUrl || network_1.DEFAULT_API_URL;
85
+ this.timeout = config.timeout || validation_1.DEFAULT_TIMEOUT_MS;
86
+ this.headers = {
87
+ "Content-Type": "application/json",
88
+ ...config.headers,
89
+ };
90
+ this.retryConfig = {
91
+ ...exports.DEFAULT_RETRY_CONFIG,
92
+ ...config.retry,
93
+ };
94
+ this.authToken = config.authToken;
95
+ }
96
+ // ============================================================================
97
+ // AUTHENTICATION
98
+ // ============================================================================
99
+ /**
100
+ * Log in with a Solana keypair. Stores the auth token for subsequent requests.
101
+ *
102
+ * @param keypair - The Solana Keypair for authentication
103
+ * @returns AuthCredentials containing the auth token and user info
104
+ */
105
+ async login(keypair) {
106
+ const credentials = await (0, auth_1.authenticate)(keypair);
107
+ this.authToken = credentials.authToken;
108
+ return credentials;
109
+ }
110
+ /**
111
+ * Set the authentication token manually.
112
+ */
113
+ setAuthToken(token) {
114
+ this.authToken = token;
115
+ }
116
+ /**
117
+ * Clear the authentication token.
118
+ */
119
+ clearAuthToken() {
120
+ this.authToken = undefined;
121
+ }
122
+ /**
123
+ * Check if the client has an authentication token.
124
+ */
125
+ hasAuthToken() {
126
+ return this.authToken !== undefined;
127
+ }
128
+ // ============================================================================
129
+ // PRIVATE HELPERS
130
+ // ============================================================================
131
+ /**
132
+ * Make an HTTP request with retry support.
133
+ */
134
+ async request(method, path, body, queryParams, authenticated) {
135
+ let url = `${this.baseUrl}${path}`;
136
+ // Add query parameters
137
+ if (queryParams && Object.keys(queryParams).length > 0) {
138
+ const params = new URLSearchParams(queryParams);
139
+ url += `?${params.toString()}`;
140
+ }
141
+ // Build headers, adding auth cookie if needed
142
+ const requestHeaders = { ...this.headers };
143
+ if (authenticated && this.authToken) {
144
+ requestHeaders["Cookie"] = `auth_token=${this.authToken}`;
145
+ }
146
+ let lastError;
147
+ for (let attempt = 0; attempt <= this.retryConfig.maxRetries; attempt++) {
148
+ // Delay before retry (not on first attempt)
149
+ if (attempt > 0) {
150
+ const delay = calculateRetryDelay(attempt - 1, this.retryConfig);
151
+ await sleep(delay);
152
+ }
153
+ const controller = new AbortController();
154
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
155
+ try {
156
+ const response = await fetch(url, {
157
+ method,
158
+ headers: requestHeaders,
159
+ body: body ? JSON.stringify(body) : undefined,
160
+ signal: controller.signal,
161
+ });
162
+ clearTimeout(timeoutId);
163
+ if (!response.ok) {
164
+ let errorMessage = `HTTP ${response.status}`;
165
+ try {
166
+ const errorData = (await response.json());
167
+ errorMessage = (0, error_1.getErrorMessage)(errorData);
168
+ }
169
+ catch (parseError) {
170
+ console.warn(`Failed to parse error response: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
171
+ }
172
+ const error = error_1.ApiError.fromStatus(response.status, errorMessage);
173
+ // Check if retryable
174
+ if (isRetryable(error) && attempt < this.retryConfig.maxRetries) {
175
+ lastError = error;
176
+ continue;
177
+ }
178
+ throw error;
179
+ }
180
+ const data = (await response.json());
181
+ return data;
182
+ }
183
+ catch (error) {
184
+ clearTimeout(timeoutId);
185
+ if (error instanceof error_1.ApiError) {
186
+ // Already an ApiError - check if retryable
187
+ if (isRetryable(error) && attempt < this.retryConfig.maxRetries) {
188
+ lastError = error;
189
+ continue;
190
+ }
191
+ throw error;
192
+ }
193
+ let apiError;
194
+ if (error instanceof Error) {
195
+ if (error.name === "AbortError") {
196
+ apiError = error_1.ApiError.http("Request timeout");
197
+ }
198
+ else {
199
+ apiError = error_1.ApiError.http(error.message);
200
+ }
201
+ }
202
+ else {
203
+ apiError = error_1.ApiError.http("Unknown error");
204
+ }
205
+ // Network errors are retryable
206
+ if (isRetryable(apiError) && attempt < this.retryConfig.maxRetries) {
207
+ lastError = apiError;
208
+ continue;
209
+ }
210
+ throw apiError;
211
+ }
212
+ }
213
+ // Should not reach here, but throw last error if we do
214
+ throw lastError || error_1.ApiError.http("Unknown error");
215
+ }
216
+ // ============================================================================
217
+ // HEALTH CHECK
218
+ // ============================================================================
219
+ /**
220
+ * Check if the API is healthy.
221
+ *
222
+ * @throws {ApiError} If the health check fails
223
+ */
224
+ async healthCheck() {
225
+ await this.request("GET", "/health");
226
+ }
227
+ // ============================================================================
228
+ // MARKETS
229
+ // ============================================================================
230
+ /**
231
+ * Get all available markets.
232
+ *
233
+ * @returns List of markets
234
+ */
235
+ async getMarkets() {
236
+ return this.request("GET", "/markets");
237
+ }
238
+ /**
239
+ * Get market information by pubkey.
240
+ *
241
+ * @param marketPubkey - Market PDA address (Base58)
242
+ * @returns Market details
243
+ * @throws {ApiError} If marketPubkey is invalid
244
+ */
245
+ async getMarket(marketPubkey) {
246
+ (0, validation_1.validatePubkey)(marketPubkey, "marketPubkey");
247
+ return this.request("GET", `/markets/${encodeURIComponent(marketPubkey)}`);
248
+ }
249
+ /**
250
+ * Get market information by slug.
251
+ *
252
+ * @param slug - URL-friendly market slug
253
+ * @returns Market details
254
+ */
255
+ async getMarketBySlug(slug) {
256
+ return this.request("GET", `/markets/by-slug/${encodeURIComponent(slug)}`);
257
+ }
258
+ /**
259
+ * Get deposit assets for a market.
260
+ *
261
+ * @param marketPubkey - Market PDA address (Base58)
262
+ * @returns Deposit assets
263
+ * @throws {ApiError} If marketPubkey is invalid
264
+ */
265
+ async getDepositAssets(marketPubkey) {
266
+ (0, validation_1.validatePubkey)(marketPubkey, "marketPubkey");
267
+ return this.request("GET", `/markets/${encodeURIComponent(marketPubkey)}/deposit-assets`);
268
+ }
269
+ // ============================================================================
270
+ // ORDERBOOK
271
+ // ============================================================================
272
+ /**
273
+ * Get orderbook snapshot.
274
+ *
275
+ * @param orderbookId - Orderbook identifier
276
+ * @param depth - Number of levels (default: 20)
277
+ * @returns Orderbook snapshot
278
+ */
279
+ async getOrderbook(orderbookId, depth) {
280
+ return this.request("GET", `/orderbook/${encodeURIComponent(orderbookId)}`, undefined, toQueryParams({ depth }));
281
+ }
282
+ // ============================================================================
283
+ // ORDERS
284
+ // ============================================================================
285
+ /**
286
+ * Submit a new order.
287
+ *
288
+ * @param request - Order details
289
+ * @returns Order response with hash and fill info
290
+ * @throws {ApiError} If any pubkey or signature is invalid
291
+ */
292
+ async submitOrder(request) {
293
+ (0, validation_1.validatePubkey)(request.maker, "maker");
294
+ (0, validation_1.validatePubkey)(request.market_pubkey, "market_pubkey");
295
+ (0, validation_1.validatePubkey)(request.base_token, "base_token");
296
+ (0, validation_1.validatePubkey)(request.quote_token, "quote_token");
297
+ (0, validation_1.validateSignature)(request.signature);
298
+ return this.request("POST", "/orders/submit", request);
299
+ }
300
+ /**
301
+ * Cancel an order with a pre-computed signature.
302
+ *
303
+ * @param orderHash - Hash of the order to cancel (hex)
304
+ * @param maker - Order creator's pubkey (Base58)
305
+ * @param signature - Ed25519 signature over the order hash (hex, 128 chars)
306
+ * @returns Cancel response
307
+ * @throws {ApiError} If maker pubkey or signature is invalid
308
+ */
309
+ async cancelOrderWithSignature(orderHash, maker, signature) {
310
+ (0, validation_1.validatePubkey)(maker, "maker");
311
+ (0, validation_1.validateSignature)(signature);
312
+ const request = { order_hash: orderHash, maker, signature };
313
+ return this.request("POST", "/orders/cancel", request);
314
+ }
315
+ /**
316
+ * Cancel an order, auto-signing with the given keypair.
317
+ *
318
+ * @param orderHash - Hash of the order to cancel (hex)
319
+ * @param signer - Keypair to sign the cancellation
320
+ * @returns Cancel response
321
+ */
322
+ async cancelOrder(orderHash, signer) {
323
+ const maker = signer.publicKey.toBase58();
324
+ const signature = (0, orders_1.signCancelOrder)(orderHash, signer);
325
+ return this.cancelOrderWithSignature(orderHash, maker, signature);
326
+ }
327
+ /**
328
+ * Cancel all orders for a user with a pre-computed signature.
329
+ *
330
+ * @param userPubkey - User's public key (Base58)
331
+ * @param signature - Ed25519 signature over "cancel_all:{pubkey}:{timestamp}" (hex, 128 chars)
332
+ * @param timestamp - Unix timestamp used in the signed message
333
+ * @param orderbookId - Optional orderbook filter
334
+ * @returns Cancel all response
335
+ * @throws {ApiError} If any pubkey or signature is invalid
336
+ */
337
+ async cancelAllOrdersWithSignature(userPubkey, signature, timestamp, orderbookId) {
338
+ (0, validation_1.validatePubkey)(userPubkey, "userPubkey");
339
+ (0, validation_1.validateSignature)(signature);
340
+ const request = {
341
+ user_pubkey: userPubkey,
342
+ orderbook_id: orderbookId,
343
+ signature,
344
+ timestamp,
345
+ };
346
+ return this.request("POST", "/orders/cancel-all", request);
347
+ }
348
+ /**
349
+ * Cancel all orders for a user, auto-signing with the given keypair.
350
+ *
351
+ * @param signer - Keypair to sign the cancellation
352
+ * @param orderbookId - Optional orderbook filter
353
+ * @returns Cancel all response
354
+ */
355
+ async cancelAllOrders(signer, orderbookId) {
356
+ const userPubkey = signer.publicKey.toBase58();
357
+ const timestamp = Math.floor(Date.now() / 1000);
358
+ const signature = (0, orders_1.signCancelAll)(userPubkey, timestamp, signer);
359
+ return this.cancelAllOrdersWithSignature(userPubkey, signature, timestamp, orderbookId);
360
+ }
361
+ // ============================================================================
362
+ // USER POSITIONS
363
+ // ============================================================================
364
+ /**
365
+ * Get user positions across all markets.
366
+ *
367
+ * @param userPubkey - User's public key (Base58)
368
+ * @returns User positions
369
+ * @throws {ApiError} If userPubkey is invalid
370
+ */
371
+ async getUserPositions(userPubkey) {
372
+ (0, validation_1.validatePubkey)(userPubkey, "userPubkey");
373
+ return this.request("GET", `/users/${encodeURIComponent(userPubkey)}/positions`);
374
+ }
375
+ /**
376
+ * Get user positions in a specific market.
377
+ *
378
+ * @param userPubkey - User's public key (Base58)
379
+ * @param marketPubkey - Market PDA address (Base58)
380
+ * @returns Market positions
381
+ * @throws {ApiError} If any pubkey is invalid
382
+ */
383
+ async getUserMarketPositions(userPubkey, marketPubkey) {
384
+ (0, validation_1.validatePubkey)(userPubkey, "userPubkey");
385
+ (0, validation_1.validatePubkey)(marketPubkey, "marketPubkey");
386
+ return this.request("GET", `/users/${encodeURIComponent(userPubkey)}/markets/${encodeURIComponent(marketPubkey)}/positions`);
387
+ }
388
+ // ============================================================================
389
+ // USER ORDERS
390
+ // ============================================================================
391
+ /**
392
+ * Get user's open orders.
393
+ *
394
+ * @param userPubkey - User's public key (Base58)
395
+ * @returns User orders and balances
396
+ * @throws {ApiError} If userPubkey is invalid
397
+ */
398
+ async getUserOrders(userPubkey) {
399
+ (0, validation_1.validatePubkey)(userPubkey, "userPubkey");
400
+ return this.request("POST", "/users/orders", { user_pubkey: userPubkey }, undefined, true);
401
+ }
402
+ // ============================================================================
403
+ // PRICE HISTORY
404
+ // ============================================================================
405
+ /**
406
+ * Get historical price data.
407
+ *
408
+ * @param params - Query parameters
409
+ * @returns Price history data
410
+ * @throws {ApiError} If limit is out of bounds (1-500)
411
+ */
412
+ async getPriceHistory(params) {
413
+ (0, validation_1.validateLimit)(params.limit);
414
+ return this.request("GET", "/price-history", undefined, toQueryParams(params));
415
+ }
416
+ // ============================================================================
417
+ // TRADES
418
+ // ============================================================================
419
+ /**
420
+ * Get recent trades.
421
+ *
422
+ * @param params - Query parameters
423
+ * @returns Trade history
424
+ * @throws {ApiError} If limit is out of bounds (1-500)
425
+ */
426
+ async getTrades(params) {
427
+ (0, validation_1.validateLimit)(params.limit);
428
+ return this.request("GET", "/trades", undefined, toQueryParams(params));
429
+ }
430
+ // ============================================================================
431
+ // ADMIN
432
+ // ============================================================================
433
+ /**
434
+ * Admin health check.
435
+ *
436
+ * @returns Admin status
437
+ */
438
+ async adminHealthCheck() {
439
+ return this.request("GET", "/admin/test");
440
+ }
441
+ /**
442
+ * Create a new orderbook (admin only).
443
+ *
444
+ * @param request - Orderbook creation request
445
+ * @returns Created orderbook info
446
+ */
447
+ async createOrderbook(request) {
448
+ return this.request("POST", "/admin/create-orderbook", request);
449
+ }
450
+ }
451
+ exports.LightconeApiClient = LightconeApiClient;
452
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * REST API client for Lightcone.\n */\n\nimport { Keypair } from \"@solana/web3.js\";\nimport { signCancelOrder, signCancelAll } from \"../program/orders\";\nimport { ApiError, getErrorMessage, type ErrorResponse } from \"./error\";\nimport {\n validatePubkey,\n validateSignature,\n validateLimit,\n DEFAULT_TIMEOUT_MS,\n} from \"./validation\";\nimport { authenticate, type AuthCredentials } from \"../auth\";\nimport type {\n MarketsResponse,\n MarketInfoResponse,\n DepositAssetsResponse,\n OrderbookResponse,\n SubmitOrderRequest,\n OrderResponse,\n CancelOrderRequest,\n CancelResponse,\n CancelAllOrdersRequest,\n CancelAllResponse,\n PositionsResponse,\n MarketPositionsResponse,\n UserOrdersResponse,\n PriceHistoryParams,\n PriceHistoryResponse,\n TradesParams,\n TradesResponse,\n AdminResponse,\n CreateOrderbookRequest,\n CreateOrderbookResponse,\n} from \"./types\";\n\n/**\n * Convert a typed params object to query string record.\n */\nfunction toQueryParams(\n params: object\n): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n result[key] = String(value);\n }\n }\n return result;\n}\n\nimport { DEFAULT_API_URL } from \"../network\";\nexport { DEFAULT_API_URL } from \"../network\";\n\n/**\n * Configuration for retry behavior.\n */\nexport interface RetryConfig {\n /** Maximum number of retry attempts (default: 0 = disabled) */\n maxRetries: number;\n /** Initial delay in milliseconds (default: 100) */\n baseDelayMs: number;\n /** Maximum delay cap in milliseconds (default: 10000) */\n maxDelayMs: number;\n}\n\n/** Default retry configuration (disabled) */\nexport const DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxRetries: 0,\n baseDelayMs: 100,\n maxDelayMs: 10000,\n};\n\n/**\n * Configuration for the Lightcone API client.\n */\nexport interface LightconeApiClientConfig {\n /** Base URL for the API (default: https://tapi.lightcone.xyz/api) */\n baseUrl?: string;\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n /** Additional headers to include in requests */\n headers?: Record<string, string>;\n /** Retry configuration for transient failures */\n retry?: Partial<RetryConfig>;\n /** Authentication token for authenticated endpoints */\n authToken?: string;\n}\n\n/**\n * Calculate delay with exponential backoff and jitter.\n * Jitter: 75-100% of calculated delay (prevents thundering herd)\n */\nfunction calculateRetryDelay(attempt: number, config: RetryConfig): number {\n const expDelay = config.baseDelayMs * Math.pow(2, Math.min(attempt, 10));\n const cappedDelay = Math.min(expDelay, config.maxDelayMs);\n const jitterRange = cappedDelay * 0.25;\n const jitter = Math.random() * jitterRange;\n return cappedDelay - jitterRange + jitter;\n}\n\n/**\n * Check if error is retryable.\n */\nfunction isRetryable(error: ApiError): boolean {\n if (error.variant === \"ServerError\") return true;\n if (error.variant === \"RateLimited\") return true;\n if (error.variant === \"Http\") return true; // Network errors\n return false;\n}\n\n/**\n * Sleep for a duration.\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * REST API client for the Lightcone platform.\n *\n * @example\n * ```typescript\n * import { LightconeApiClient } from \"@lightcone/sdk/api\";\n *\n * const client = new LightconeApiClient();\n *\n * // Get all markets\n * const markets = await client.getMarkets();\n *\n * // Get orderbook\n * const orderbook = await client.getOrderbook(\"market1:ob1\");\n * ```\n */\nexport class LightconeApiClient {\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly headers: Record<string, string>;\n private readonly retryConfig: RetryConfig;\n private authToken?: string;\n\n constructor(config: LightconeApiClientConfig = {}) {\n this.baseUrl = config.baseUrl || DEFAULT_API_URL;\n this.timeout = config.timeout || DEFAULT_TIMEOUT_MS;\n this.headers = {\n \"Content-Type\": \"application/json\",\n ...config.headers,\n };\n this.retryConfig = {\n ...DEFAULT_RETRY_CONFIG,\n ...config.retry,\n };\n this.authToken = config.authToken;\n }\n\n // ============================================================================\n // AUTHENTICATION\n // ============================================================================\n\n /**\n * Log in with a Solana keypair. Stores the auth token for subsequent requests.\n *\n * @param keypair - The Solana Keypair for authentication\n * @returns AuthCredentials containing the auth token and user info\n */\n async login(keypair: Keypair): Promise<AuthCredentials> {\n const credentials = await authenticate(keypair);\n this.authToken = credentials.authToken;\n return credentials;\n }\n\n /**\n * Set the authentication token manually.\n */\n setAuthToken(token: string): void {\n this.authToken = token;\n }\n\n /**\n * Clear the authentication token.\n */\n clearAuthToken(): void {\n this.authToken = undefined;\n }\n\n /**\n * Check if the client has an authentication token.\n */\n hasAuthToken(): boolean {\n return this.authToken !== undefined;\n }\n\n // ============================================================================\n // PRIVATE HELPERS\n // ============================================================================\n\n /**\n * Make an HTTP request with retry support.\n */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n queryParams?: Record<string, string>,\n authenticated?: boolean\n ): Promise<T> {\n let url = `${this.baseUrl}${path}`;\n\n // Add query parameters\n if (queryParams && Object.keys(queryParams).length > 0) {\n const params = new URLSearchParams(queryParams);\n url += `?${params.toString()}`;\n }\n\n // Build headers, adding auth cookie if needed\n const requestHeaders: Record<string, string> = { ...this.headers };\n if (authenticated && this.authToken) {\n requestHeaders[\"Cookie\"] = `auth_token=${this.authToken}`;\n }\n\n let lastError: ApiError | undefined;\n\n for (let attempt = 0; attempt <= this.retryConfig.maxRetries; attempt++) {\n // Delay before retry (not on first attempt)\n if (attempt > 0) {\n const delay = calculateRetryDelay(attempt - 1, this.retryConfig);\n await sleep(delay);\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: requestHeaders,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n let errorMessage = `HTTP ${response.status}`;\n try {\n const errorData = (await response.json()) as ErrorResponse;\n errorMessage = getErrorMessage(errorData);\n } catch (parseError) {\n console.warn(\n `Failed to parse error response: ${parseError instanceof Error ? parseError.message : String(parseError)}`\n );\n }\n const error = ApiError.fromStatus(response.status, errorMessage);\n\n // Check if retryable\n if (isRetryable(error) && attempt < this.retryConfig.maxRetries) {\n lastError = error;\n continue;\n }\n throw error;\n }\n\n const data = (await response.json()) as T;\n return data;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof ApiError) {\n // Already an ApiError - check if retryable\n if (isRetryable(error) && attempt < this.retryConfig.maxRetries) {\n lastError = error;\n continue;\n }\n throw error;\n }\n\n let apiError: ApiError;\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n apiError = ApiError.http(\"Request timeout\");\n } else {\n apiError = ApiError.http(error.message);\n }\n } else {\n apiError = ApiError.http(\"Unknown error\");\n }\n\n // Network errors are retryable\n if (isRetryable(apiError) && attempt < this.retryConfig.maxRetries) {\n lastError = apiError;\n continue;\n }\n throw apiError;\n }\n }\n\n // Should not reach here, but throw last error if we do\n throw lastError || ApiError.http(\"Unknown error\");\n }\n\n // ============================================================================\n // HEALTH CHECK\n // ============================================================================\n\n /**\n * Check if the API is healthy.\n *\n * @throws {ApiError} If the health check fails\n */\n async healthCheck(): Promise<void> {\n await this.request<{ status: string }>(\"GET\", \"/health\");\n }\n\n // ============================================================================\n // MARKETS\n // ============================================================================\n\n /**\n * Get all available markets.\n *\n * @returns List of markets\n */\n async getMarkets(): Promise<MarketsResponse> {\n return this.request<MarketsResponse>(\"GET\", \"/markets\");\n }\n\n /**\n * Get market information by pubkey.\n *\n * @param marketPubkey - Market PDA address (Base58)\n * @returns Market details\n * @throws {ApiError} If marketPubkey is invalid\n */\n async getMarket(marketPubkey: string): Promise<MarketInfoResponse> {\n validatePubkey(marketPubkey, \"marketPubkey\");\n return this.request<MarketInfoResponse>(\n \"GET\",\n `/markets/${encodeURIComponent(marketPubkey)}`\n );\n }\n\n /**\n * Get market information by slug.\n *\n * @param slug - URL-friendly market slug\n * @returns Market details\n */\n async getMarketBySlug(slug: string): Promise<MarketInfoResponse> {\n return this.request<MarketInfoResponse>(\n \"GET\",\n `/markets/by-slug/${encodeURIComponent(slug)}`\n );\n }\n\n /**\n * Get deposit assets for a market.\n *\n * @param marketPubkey - Market PDA address (Base58)\n * @returns Deposit assets\n * @throws {ApiError} If marketPubkey is invalid\n */\n async getDepositAssets(marketPubkey: string): Promise<DepositAssetsResponse> {\n validatePubkey(marketPubkey, \"marketPubkey\");\n return this.request<DepositAssetsResponse>(\n \"GET\",\n `/markets/${encodeURIComponent(marketPubkey)}/deposit-assets`\n );\n }\n\n // ============================================================================\n // ORDERBOOK\n // ============================================================================\n\n /**\n * Get orderbook snapshot.\n *\n * @param orderbookId - Orderbook identifier\n * @param depth - Number of levels (default: 20)\n * @returns Orderbook snapshot\n */\n async getOrderbook(\n orderbookId: string,\n depth?: number\n ): Promise<OrderbookResponse> {\n return this.request<OrderbookResponse>(\n \"GET\",\n `/orderbook/${encodeURIComponent(orderbookId)}`,\n undefined,\n toQueryParams({ depth })\n );\n }\n\n // ============================================================================\n // ORDERS\n // ============================================================================\n\n /**\n * Submit a new order.\n *\n * @param request - Order details\n * @returns Order response with hash and fill info\n * @throws {ApiError} If any pubkey or signature is invalid\n */\n async submitOrder(request: SubmitOrderRequest): Promise<OrderResponse> {\n validatePubkey(request.maker, \"maker\");\n validatePubkey(request.market_pubkey, \"market_pubkey\");\n validatePubkey(request.base_token, \"base_token\");\n validatePubkey(request.quote_token, \"quote_token\");\n validateSignature(request.signature);\n return this.request<OrderResponse>(\"POST\", \"/orders/submit\", request);\n }\n\n /**\n * Cancel an order with a pre-computed signature.\n *\n * @param orderHash - Hash of the order to cancel (hex)\n * @param maker - Order creator's pubkey (Base58)\n * @param signature - Ed25519 signature over the order hash (hex, 128 chars)\n * @returns Cancel response\n * @throws {ApiError} If maker pubkey or signature is invalid\n */\n async cancelOrderWithSignature(\n orderHash: string,\n maker: string,\n signature: string\n ): Promise<CancelResponse> {\n validatePubkey(maker, \"maker\");\n validateSignature(signature);\n const request: CancelOrderRequest = { order_hash: orderHash, maker, signature };\n return this.request<CancelResponse>(\"POST\", \"/orders/cancel\", request);\n }\n\n /**\n * Cancel an order, auto-signing with the given keypair.\n *\n * @param orderHash - Hash of the order to cancel (hex)\n * @param signer - Keypair to sign the cancellation\n * @returns Cancel response\n */\n async cancelOrder(orderHash: string, signer: Keypair): Promise<CancelResponse> {\n const maker = signer.publicKey.toBase58();\n const signature = signCancelOrder(orderHash, signer);\n return this.cancelOrderWithSignature(orderHash, maker, signature);\n }\n\n /**\n * Cancel all orders for a user with a pre-computed signature.\n *\n * @param userPubkey - User's public key (Base58)\n * @param signature - Ed25519 signature over \"cancel_all:{pubkey}:{timestamp}\" (hex, 128 chars)\n * @param timestamp - Unix timestamp used in the signed message\n * @param orderbookId - Optional orderbook filter\n * @returns Cancel all response\n * @throws {ApiError} If any pubkey or signature is invalid\n */\n async cancelAllOrdersWithSignature(\n userPubkey: string,\n signature: string,\n timestamp: number,\n orderbookId?: string\n ): Promise<CancelAllResponse> {\n validatePubkey(userPubkey, \"userPubkey\");\n validateSignature(signature);\n const request: CancelAllOrdersRequest = {\n user_pubkey: userPubkey,\n orderbook_id: orderbookId,\n signature,\n timestamp,\n };\n return this.request<CancelAllResponse>(\"POST\", \"/orders/cancel-all\", request);\n }\n\n /**\n * Cancel all orders for a user, auto-signing with the given keypair.\n *\n * @param signer - Keypair to sign the cancellation\n * @param orderbookId - Optional orderbook filter\n * @returns Cancel all response\n */\n async cancelAllOrders(\n signer: Keypair,\n orderbookId?: string\n ): Promise<CancelAllResponse> {\n const userPubkey = signer.publicKey.toBase58();\n const timestamp = Math.floor(Date.now() / 1000);\n const signature = signCancelAll(userPubkey, timestamp, signer);\n return this.cancelAllOrdersWithSignature(userPubkey, signature, timestamp, orderbookId);\n }\n\n // ============================================================================\n // USER POSITIONS\n // ============================================================================\n\n /**\n * Get user positions across all markets.\n *\n * @param userPubkey - User's public key (Base58)\n * @returns User positions\n * @throws {ApiError} If userPubkey is invalid\n */\n async getUserPositions(userPubkey: string): Promise<PositionsResponse> {\n validatePubkey(userPubkey, \"userPubkey\");\n return this.request<PositionsResponse>(\n \"GET\",\n `/users/${encodeURIComponent(userPubkey)}/positions`\n );\n }\n\n /**\n * Get user positions in a specific market.\n *\n * @param userPubkey - User's public key (Base58)\n * @param marketPubkey - Market PDA address (Base58)\n * @returns Market positions\n * @throws {ApiError} If any pubkey is invalid\n */\n async getUserMarketPositions(\n userPubkey: string,\n marketPubkey: string\n ): Promise<MarketPositionsResponse> {\n validatePubkey(userPubkey, \"userPubkey\");\n validatePubkey(marketPubkey, \"marketPubkey\");\n return this.request<MarketPositionsResponse>(\n \"GET\",\n `/users/${encodeURIComponent(userPubkey)}/markets/${encodeURIComponent(marketPubkey)}/positions`\n );\n }\n\n // ============================================================================\n // USER ORDERS\n // ============================================================================\n\n /**\n * Get user's open orders.\n *\n * @param userPubkey - User's public key (Base58)\n * @returns User orders and balances\n * @throws {ApiError} If userPubkey is invalid\n */\n async getUserOrders(userPubkey: string): Promise<UserOrdersResponse> {\n validatePubkey(userPubkey, \"userPubkey\");\n return this.request<UserOrdersResponse>(\n \"POST\",\n \"/users/orders\",\n { user_pubkey: userPubkey },\n undefined,\n true\n );\n }\n\n // ============================================================================\n // PRICE HISTORY\n // ============================================================================\n\n /**\n * Get historical price data.\n *\n * @param params - Query parameters\n * @returns Price history data\n * @throws {ApiError} If limit is out of bounds (1-500)\n */\n async getPriceHistory(params: PriceHistoryParams): Promise<PriceHistoryResponse> {\n validateLimit(params.limit);\n return this.request<PriceHistoryResponse>(\n \"GET\",\n \"/price-history\",\n undefined,\n toQueryParams(params)\n );\n }\n\n // ============================================================================\n // TRADES\n // ============================================================================\n\n /**\n * Get recent trades.\n *\n * @param params - Query parameters\n * @returns Trade history\n * @throws {ApiError} If limit is out of bounds (1-500)\n */\n async getTrades(params: TradesParams): Promise<TradesResponse> {\n validateLimit(params.limit);\n return this.request<TradesResponse>(\n \"GET\",\n \"/trades\",\n undefined,\n toQueryParams(params)\n );\n }\n\n // ============================================================================\n // ADMIN\n // ============================================================================\n\n /**\n * Admin health check.\n *\n * @returns Admin status\n */\n async adminHealthCheck(): Promise<AdminResponse> {\n return this.request<AdminResponse>(\"GET\", \"/admin/test\");\n }\n\n /**\n * Create a new orderbook (admin only).\n *\n * @param request - Orderbook creation request\n * @returns Created orderbook info\n */\n async createOrderbook(\n request: CreateOrderbookRequest\n ): Promise<CreateOrderbookResponse> {\n return this.request<CreateOrderbookResponse>(\n \"POST\",\n \"/admin/create-orderbook\",\n request\n );\n }\n}\n"]}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * API error types for the Lightcone REST API client.
3
+ */
4
+ /**
5
+ * API error variants
6
+ */
7
+ export type ApiErrorVariant = "Http" | "NotFound" | "BadRequest" | "Forbidden" | "Conflict" | "ServerError" | "Deserialize" | "InvalidParameter" | "UnexpectedStatus" | "RateLimited" | "Unauthorized";
8
+ /**
9
+ * API-specific error class for the Lightcone REST API client.
10
+ */
11
+ export declare class ApiError extends Error {
12
+ readonly variant: ApiErrorVariant;
13
+ readonly statusCode?: number;
14
+ readonly details?: string;
15
+ constructor(variant: ApiErrorVariant, message: string, statusCode?: number, details?: string);
16
+ /** HTTP/network error */
17
+ static http(message: string): ApiError;
18
+ /** Resource not found (404) */
19
+ static notFound(message: string): ApiError;
20
+ /** Invalid request parameters (400) */
21
+ static badRequest(message: string): ApiError;
22
+ /** Permission denied, signature mismatch (403) */
23
+ static forbidden(message: string): ApiError;
24
+ /** Resource already exists (409) */
25
+ static conflict(message: string): ApiError;
26
+ /** Server-side error (500) */
27
+ static serverError(message: string): ApiError;
28
+ /** JSON deserialization error */
29
+ static deserialize(message: string): ApiError;
30
+ /** Invalid parameter provided */
31
+ static invalidParameter(message: string): ApiError;
32
+ /** Unexpected HTTP status code */
33
+ static unexpectedStatus(statusCode: number, message: string): ApiError;
34
+ /** Rate limited (429) */
35
+ static rateLimited(message: string): ApiError;
36
+ /** Unauthorized - invalid or missing authentication (401) */
37
+ static unauthorized(message: string): ApiError;
38
+ /** Create from HTTP status code */
39
+ static fromStatus(statusCode: number, message: string): ApiError;
40
+ }
41
+ /**
42
+ * Error response format from the API.
43
+ */
44
+ export interface ErrorResponse {
45
+ /** Error status (usually "error") */
46
+ status?: string;
47
+ /** Human-readable error message */
48
+ message?: string;
49
+ /** Alternative error field */
50
+ error?: string;
51
+ /** Additional error details */
52
+ details?: string;
53
+ }
54
+ /**
55
+ * Get the error message from an ErrorResponse.
56
+ */
57
+ export declare function getErrorMessage(response: ErrorResponse): string;
58
+ //# sourceMappingURL=error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/api/error.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,UAAU,GACV,YAAY,GACZ,WAAW,GACX,UAAU,GACV,aAAa,GACb,aAAa,GACb,kBAAkB,GAClB,kBAAkB,GAClB,aAAa,GACb,cAAc,CAAC;AAEnB;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;gBAEd,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;IAQ5F,yBAAyB;IACzB,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ;IAItC,+BAA+B;IAC/B,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ;IAI1C,uCAAuC;IACvC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ;IAI5C,kDAAkD;IAClD,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ;IAI3C,oCAAoC;IACpC,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ;IAI1C,8BAA8B;IAC9B,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ;IAI7C,iCAAiC;IACjC,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ;IAI7C,iCAAiC;IACjC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ;IAIlD,kCAAkC;IAClC,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ;IAItE,yBAAyB;IACzB,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ;IAI7C,6DAA6D;IAC7D,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ;IAI9C,mCAAmC;IACnC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ;CAuBjE;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,CAE/D"}