laplace-api 4.4.0 → 4.5.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "laplace-api",
3
- "version": "4.4.0",
3
+ "version": "4.5.0",
4
4
  "description": "Client library for Laplace API for the US stock market and BIST (Istanbul stock market) fundamental financial data.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,3 +1,5 @@
1
+ import { OrderbookLiveData } from "./live-price";
2
+
1
3
  interface RawBISTStockLiveData {
2
4
  _id: number;
3
5
  symbol: string;
@@ -33,14 +35,15 @@ export enum LivePriceFeed {
33
35
  LiveUs = "live_price_us",
34
36
  DelayedBist = "delayed_price_tr",
35
37
  DelayedUs = "delayed_price_us",
36
- // DepthBist = "depth_tr",
38
+ DepthBist = "depth_tr",
37
39
  }
38
40
 
39
41
  type StockLiveDataType<T extends LivePriceFeed> = T extends
40
42
  | LivePriceFeed.LiveBist
41
43
  | LivePriceFeed.DelayedBist
42
- ? // | LivePriceFeed.DepthBist
43
- BISTStockLiveData
44
+ ? BISTStockLiveData
45
+ : T extends LivePriceFeed.DepthBist
46
+ ? OrderbookLiveData
44
47
  : USStockLiveData;
45
48
 
46
49
  export enum LogLevel {
@@ -94,14 +97,10 @@ export class LivePriceWebSocketClient {
94
97
  number,
95
98
  {
96
99
  symbols: string[];
97
- handler: (data: BISTStockLiveData | USStockLiveData) => void;
100
+ handler: (data: BISTStockLiveData | USStockLiveData | OrderbookLiveData) => void;
98
101
  feed: LivePriceFeed;
99
102
  }
100
103
  >();
101
- private symbolLastData = new Map<
102
- string,
103
- BISTStockLiveData | USStockLiveData
104
- >();
105
104
  private reconnectAttempts = 0;
106
105
  private reconnectTimeout: NodeJS.Timeout | null = null;
107
106
  private isClosed: boolean = false;
@@ -276,13 +275,11 @@ export class LivePriceWebSocketClient {
276
275
  WebSocketErrorType.MESSAGE_PARSE_ERROR
277
276
  );
278
277
  }
279
- let priceData: BISTStockLiveData | USStockLiveData;
278
+ let priceData: BISTStockLiveData | USStockLiveData | OrderbookLiveData;
280
279
 
281
280
  if (
282
281
  feed === LivePriceFeed.DelayedBist ||
283
282
  feed === LivePriceFeed.LiveBist
284
- // ||
285
- // feed === LivePriceFeed.DepthBist
286
283
  ) {
287
284
  const message = messageData as RawBISTStockLiveData;
288
285
  priceData = {
@@ -293,6 +290,13 @@ export class LivePriceWebSocketClient {
293
290
  timestamp: message?.d,
294
291
  percentChange: message?.c,
295
292
  } as BISTStockLiveData;
293
+ } else if (feed === LivePriceFeed.DepthBist) {
294
+ const message = messageData as OrderbookLiveData;
295
+ priceData = {
296
+ updated: message.updated,
297
+ deleted: message.deleted,
298
+ symbol: message?.symbol,
299
+ } as OrderbookLiveData;
296
300
  } else {
297
301
  const message = messageData as RawUSStockLiveData;
298
302
  priceData = {
@@ -302,7 +306,6 @@ export class LivePriceWebSocketClient {
302
306
  } as USStockLiveData;
303
307
  }
304
308
  if (priceData.symbol) {
305
- this.symbolLastData.set(priceData.symbol, priceData);
306
309
  const handlers = this.getHandlersForSymbol(
307
310
  priceData.symbol,
308
311
  feed
@@ -409,7 +412,7 @@ export class LivePriceWebSocketClient {
409
412
  const subscriptionId = this.subscriptionCounter++;
410
413
  let symbolsToAdd: string[] = [];
411
414
 
412
- const typedHandler = (data: BISTStockLiveData | USStockLiveData) => {
415
+ const typedHandler = (data: BISTStockLiveData | USStockLiveData | OrderbookLiveData) => {
413
416
  handler(data as StockLiveDataType<F>);
414
417
  };
415
418
 
@@ -423,12 +426,6 @@ export class LivePriceWebSocketClient {
423
426
  const symbolHandlers = this.getHandlersForSymbol(symbol, feed);
424
427
  if (symbolHandlers.length === 1) {
425
428
  symbolsToAdd.push(symbol);
426
- } else if (symbolHandlers.length > 1) {
427
- const lastData: BISTStockLiveData | USStockLiveData | undefined =
428
- this.symbolLastData.get(symbol);
429
- if (lastData) {
430
- typedHandler(lastData);
431
- }
432
429
  }
433
430
  }
434
431
  this.addSymbols(symbolsToAdd, feed);
@@ -445,7 +442,7 @@ export class LivePriceWebSocketClient {
445
442
  private getHandlersForSymbol(
446
443
  symbol: string,
447
444
  feed: LivePriceFeed
448
- ): ((data: BISTStockLiveData | USStockLiveData) => void)[] {
445
+ ): ((data: BISTStockLiveData | USStockLiveData | OrderbookLiveData) => void)[] {
449
446
  return Array.from(this.subscriptions.values())
450
447
  .filter((s) => s.symbols.includes(symbol) && s.feed === feed)
451
448
  .map((s) => s.handler);
@@ -298,12 +298,14 @@ export class StockClient extends Client {
298
298
  if (request.resolution) params.resolution = request.resolution;
299
299
  if (request.indicators) params.indicators = request.indicators;
300
300
  if (request.chartType != null) params.chartType = request.chartType;
301
-
302
- return this.sendRequest<Blob>({
303
- method: 'GET',
304
- url: '/api/v1/stock/chart',
301
+
302
+ const data = await this.sendRequest<ArrayBuffer>({
303
+ method: "GET",
304
+ url: "/api/v1/stock/chart",
305
305
  params,
306
- responseType: 'blob',
306
+ responseType: "arraybuffer",
307
307
  });
308
+
309
+ return new Blob([data], { type: "image/png" });
308
310
  }
309
311
  }
@@ -125,14 +125,14 @@ const mockTickRulesResponse = {
125
125
 
126
126
  const mockEarningsTranscriptList: EarningsTranscriptListItem[] = [
127
127
  {
128
- symbol: "TUPRS",
128
+ symbol: "AAPL",
129
129
  year: 2024,
130
130
  quarter: 1,
131
131
  date: "2024-05-15",
132
- fiscal_year: 2024
132
+ fiscal_year: 2024,
133
133
  },
134
134
  {
135
- symbol: "TUPRS",
135
+ symbol: "AAPL",
136
136
  year: 2023,
137
137
  quarter: 4,
138
138
  date: "2024-02-20",
@@ -141,7 +141,7 @@ const mockEarningsTranscriptList: EarningsTranscriptListItem[] = [
141
141
  ];
142
142
 
143
143
  const mockEarningsTranscriptDetail: EarningsTranscriptWithSummary = {
144
- symbol: "TUPRS",
144
+ symbol: "AAPL",
145
145
  year: 2024,
146
146
  quarter: 1,
147
147
  date: "2024-05-15",
@@ -153,14 +153,14 @@ const mockEarningsTranscriptDetail: EarningsTranscriptWithSummary = {
153
153
  const mockMarketStates: MarketState[] = [
154
154
  {
155
155
  id: 1,
156
- marketSymbol: "XIST",
156
+ marketSymbol: "BIST",
157
157
  state: "OPEN",
158
158
  lastTimestamp: "2024-03-14T10:00:00Z",
159
159
  stockSymbol: "TUPRS"
160
160
  },
161
161
  {
162
162
  id: 2,
163
- marketSymbol: "XIST",
163
+ marketSymbol: "BIST",
164
164
  state: "CLOSED",
165
165
  lastTimestamp: "2024-03-14T18:00:00Z",
166
166
  stockSymbol: "GARAN"
@@ -174,7 +174,7 @@ const mockPaginatedMarketStates: PaginatedResponse<MarketState> = {
174
174
 
175
175
  const mockSingleMarketState: MarketState = {
176
176
  id: 1,
177
- marketSymbol: "XIST",
177
+ marketSymbol: "BIST",
178
178
  state: "OPEN",
179
179
  lastTimestamp: "2024-03-14T10:00:00Z",
180
180
  stockSymbol: "TUPRS"
@@ -389,7 +389,7 @@ describe("Stocks Client", () => {
389
389
 
390
390
  describe("getEarningsTranscripts", () => {
391
391
  test("should return earnings transcript list", async () => {
392
- const resp = await client.getEarningsTranscripts("TUPRS", Region.Tr);
392
+ const resp = await client.getEarningsTranscripts("AAPL", Region.Us);
393
393
 
394
394
  expect(Array.isArray(resp)).toBe(true);
395
395
 
@@ -406,7 +406,7 @@ describe("Stocks Client", () => {
406
406
 
407
407
  describe("getEarningsTranscript", () => {
408
408
  test("should return earnings transcript detail", async () => {
409
- const resp = await client.getEarningsTranscript("TUPRS", 2023, 4);
409
+ const resp = await client.getEarningsTranscript("AAPL", 2023, 4);
410
410
 
411
411
  expect(resp).toBeDefined();
412
412
  expect(typeof resp.symbol).toBe("string");
@@ -476,7 +476,7 @@ describe("Stocks Client", () => {
476
476
 
477
477
  describe("getState", () => {
478
478
  test("should return single market state", async () => {
479
- const resp = await client.getState("XIST");
479
+ const resp = await client.getState("BIST");
480
480
 
481
481
  expect(resp).toBeDefined();
482
482
  expect(typeof resp.id).toBe("number");
@@ -495,11 +495,10 @@ describe("Stocks Client", () => {
495
495
  symbol: "TUPRS",
496
496
  region: Region.Tr,
497
497
  });
498
-
499
498
  expect(resp).toBeDefined();
500
499
  expect(resp).toBeInstanceOf(Blob);
501
500
  expect(resp.size).toBeGreaterThan(0);
502
- });
501
+ }, 10000);
503
502
  });
504
503
  });
505
504
 
@@ -693,12 +692,12 @@ describe("Stocks Client", () => {
693
692
  test("should return earnings transcript list with mock data", async () => {
694
693
  jest.spyOn(client, 'getEarningsTranscripts').mockResolvedValue(mockEarningsTranscriptList);
695
694
 
696
- const resp = await client.getEarningsTranscripts("TUPRS", Region.Tr);
695
+ const resp = await client.getEarningsTranscripts("AAPL", Region.Us);
697
696
 
698
697
  expect(resp).toHaveLength(2);
699
698
 
700
699
  const firstTranscript = resp[0];
701
- expect(firstTranscript.symbol).toBe("TUPRS");
700
+ expect(firstTranscript.symbol).toBe("AAPL");
702
701
  expect(firstTranscript.year).toBe(2024);
703
702
  expect(firstTranscript.quarter).toBe(1);
704
703
  expect(firstTranscript.date).toBe("2024-05-15");
@@ -708,14 +707,18 @@ describe("Stocks Client", () => {
708
707
  expect(secondTranscript.year).toBe(2023);
709
708
  expect(secondTranscript.quarter).toBe(4);
710
709
 
711
- expect(client.getEarningsTranscripts).toHaveBeenCalledWith("TUPRS", Region.Tr);
710
+ expect(client.getEarningsTranscripts).toHaveBeenCalledWith(
711
+ "AAPL",
712
+ Region.Us
713
+ );
712
714
  });
713
715
 
714
716
  test("should handle API errors for earnings transcripts", async () => {
715
717
  jest.spyOn(client, 'getEarningsTranscripts').mockRejectedValue(new Error("Transcripts not found"));
716
718
 
717
- await expect(client.getEarningsTranscripts("INVALID", Region.Tr))
718
- .rejects.toThrow("Transcripts not found");
719
+ await expect(
720
+ client.getEarningsTranscripts("INVALID", Region.Us)
721
+ ).rejects.toThrow("Transcripts not found");
719
722
  });
720
723
  });
721
724
 
@@ -723,9 +726,9 @@ describe("Stocks Client", () => {
723
726
  test("should return earnings transcript detail with mock data", async () => {
724
727
  jest.spyOn(client, 'getEarningsTranscript').mockResolvedValue(mockEarningsTranscriptDetail);
725
728
 
726
- const resp = await client.getEarningsTranscript("TUPRS", 2024, 1);
729
+ const resp = await client.getEarningsTranscript("AAPL", 2024, 1);
727
730
 
728
- expect(resp.symbol).toBe("TUPRS");
731
+ expect(resp.symbol).toBe("AAPL");
729
732
  expect(resp.year).toBe(2024);
730
733
  expect(resp.quarter).toBe(1);
731
734
  expect(resp.date).toBe("2024-05-15");
@@ -733,14 +736,19 @@ describe("Stocks Client", () => {
733
736
  expect(resp.summary).toBe("Strong Q1 performance with 15% revenue growth");
734
737
  expect(resp.has_summary).toBe(true);
735
738
 
736
- expect(client.getEarningsTranscript).toHaveBeenCalledWith("TUPRS", 2024, 1);
739
+ expect(client.getEarningsTranscript).toHaveBeenCalledWith(
740
+ "AAPL",
741
+ 2024,
742
+ 1
743
+ );
737
744
  });
738
745
 
739
746
  test("should handle API errors for earnings transcript detail", async () => {
740
747
  jest.spyOn(client, 'getEarningsTranscript').mockRejectedValue(new Error("Transcript not found"));
741
748
 
742
- await expect(client.getEarningsTranscript("TUPRS", 2020, 1))
743
- .rejects.toThrow("Transcript not found");
749
+ await expect(
750
+ client.getEarningsTranscript("AAPL", 2020, 1)
751
+ ).rejects.toThrow("Transcript not found");
744
752
  });
745
753
  });
746
754
 
@@ -755,7 +763,7 @@ describe("Stocks Client", () => {
755
763
 
756
764
  const firstState = resp.items[0];
757
765
  expect(firstState.id).toBe(1);
758
- expect(firstState.marketSymbol).toBe("XIST");
766
+ expect(firstState.marketSymbol).toBe("BIST");
759
767
  expect(firstState.state).toBe("OPEN");
760
768
  expect(firstState.stockSymbol).toBe("TUPRS");
761
769
 
@@ -777,7 +785,7 @@ describe("Stocks Client", () => {
777
785
  const resp = await client.getStockState("TUPRS");
778
786
 
779
787
  expect(resp.id).toBe(1);
780
- expect(resp.marketSymbol).toBe("XIST");
788
+ expect(resp.marketSymbol).toBe("BIST");
781
789
  expect(resp.state).toBe("OPEN");
782
790
  expect(resp.lastTimestamp).toBe("2024-03-14T10:00:00Z");
783
791
  expect(resp.stockSymbol).toBe("TUPRS");
@@ -821,14 +829,14 @@ describe("Stocks Client", () => {
821
829
  test("should return single market state with mock data", async () => {
822
830
  jest.spyOn(client, 'getState').mockResolvedValue(mockSingleMarketState);
823
831
 
824
- const resp = await client.getState("XIST");
832
+ const resp = await client.getState("BIST");
825
833
 
826
834
  expect(resp.id).toBe(1);
827
- expect(resp.marketSymbol).toBe("XIST");
835
+ expect(resp.marketSymbol).toBe("BIST");
828
836
  expect(resp.state).toBe("OPEN");
829
837
  expect(resp.lastTimestamp).toBe("2024-03-14T10:00:00Z");
830
838
 
831
- expect(client.getState).toHaveBeenCalledWith("XIST");
839
+ expect(client.getState).toHaveBeenCalledWith("BIST");
832
840
  });
833
841
 
834
842
  test("should handle API errors for single state", async () => {