@adaptic/utils 0.1.2 → 0.1.4

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/dist/index.mjs CHANGED
@@ -300,23 +300,42 @@ const fetchAssetOverview = async (symbol) => {
300
300
  /**
301
301
  * Validates Alpaca API credentials
302
302
  * @param auth - Authentication object containing API key and secret
303
- * @throws {Error} If credentials are invalid or missing
303
+ * @param options - Validation options
304
+ * @param options.throwOnMissing - If false, missing credentials will log a warning instead of throwing (default: true)
305
+ * @throws {Error} If credentials are invalid (when throwOnMissing is true)
306
+ * @returns {boolean} True if credentials are valid, false if missing (when throwOnMissing is false)
304
307
  */
305
- function validateAlpacaCredentials(auth) {
308
+ function validateAlpacaCredentials(auth, options = { throwOnMissing: true }) {
309
+ const { throwOnMissing = true } = options;
310
+ // Check for missing or empty API key
306
311
  if (!auth.apiKey ||
307
312
  typeof auth.apiKey !== "string" ||
308
313
  auth.apiKey.trim().length === 0) {
309
- throw new Error("Invalid Alpaca API key: must be a non-empty string");
314
+ if (throwOnMissing) {
315
+ throw new Error("Invalid Alpaca API key: must be a non-empty string");
316
+ }
317
+ console.warn("[AlpacaAPI] API key not configured. Market data features will be unavailable.");
318
+ return false;
310
319
  }
320
+ // Check for missing or empty API secret
311
321
  if (!auth.apiSecret ||
312
322
  typeof auth.apiSecret !== "string" ||
313
323
  auth.apiSecret.trim().length === 0) {
314
- throw new Error("Invalid Alpaca API secret: must be a non-empty string");
324
+ if (throwOnMissing) {
325
+ throw new Error("Invalid Alpaca API secret: must be a non-empty string");
326
+ }
327
+ console.warn("[AlpacaAPI] API secret not configured. Market data features will be unavailable.");
328
+ return false;
315
329
  }
316
330
  // Alpaca keys are typically 20+ characters
317
331
  if (auth.apiKey.length < 10) {
318
- throw new Error("Alpaca API key appears to be too short");
332
+ if (throwOnMissing) {
333
+ throw new Error("Alpaca API key appears to be too short");
334
+ }
335
+ console.warn("[AlpacaAPI] API key appears to be too short.");
336
+ return false;
319
337
  }
338
+ return true;
320
339
  }
321
340
  /**
322
341
  * Validates Polygon API key
@@ -349,21 +368,21 @@ function validateAlphaVantageApiKey(apiKey) {
349
368
  async function validateAuth(auth) {
350
369
  if (auth.adapticAccountId) {
351
370
  const client = await getSharedApolloClient();
352
- const alpacaAccount = (await adaptic$1.alpacaAccount.get({
371
+ const brokerageAccount = (await adaptic$1.brokerageAccount.get({
353
372
  id: auth.adapticAccountId,
354
373
  }, client));
355
- if (!alpacaAccount || !alpacaAccount.APIKey || !alpacaAccount.APISecret) {
374
+ if (!brokerageAccount || !brokerageAccount.apiKey || !brokerageAccount.apiSecret) {
356
375
  throw new Error("Alpaca account not found or incomplete");
357
376
  }
358
377
  validateAlpacaCredentials({
359
- apiKey: alpacaAccount.APIKey,
360
- apiSecret: alpacaAccount.APISecret,
361
- isPaper: alpacaAccount.type === "PAPER",
378
+ apiKey: brokerageAccount.apiKey,
379
+ apiSecret: brokerageAccount.apiSecret,
380
+ isPaper: brokerageAccount.type === "PAPER",
362
381
  });
363
382
  return {
364
- APIKey: alpacaAccount.APIKey,
365
- APISecret: alpacaAccount.APISecret,
366
- type: alpacaAccount.type,
383
+ apiKey: brokerageAccount.apiKey,
384
+ apiSecret: brokerageAccount.apiSecret,
385
+ type: brokerageAccount.type,
367
386
  };
368
387
  }
369
388
  else if (auth.alpacaApiKey && auth.alpacaApiSecret) {
@@ -372,8 +391,8 @@ async function validateAuth(auth) {
372
391
  apiKey: auth.alpacaApiKey,
373
392
  apiSecret: auth.alpacaApiSecret});
374
393
  return {
375
- APIKey: auth.alpacaApiKey,
376
- APISecret: auth.alpacaApiSecret,
394
+ apiKey: auth.alpacaApiKey,
395
+ apiSecret: auth.alpacaApiSecret,
377
396
  type: accountType,
378
397
  };
379
398
  }
@@ -544,11 +563,11 @@ const ORDER_CHUNK_SIZE = 500;
544
563
  async function makeRequest(auth, params) {
545
564
  const { endpoint, method, body, queryString, apiBaseUrl } = params;
546
565
  try {
547
- const { APIKey, APISecret, type } = await validateAuth(auth);
566
+ const { apiKey, apiSecret, type } = await validateAuth(auth);
548
567
  const apiBaseUrlInner = apiBaseUrl
549
568
  ? apiBaseUrl
550
569
  : getTradingApiUrl(type);
551
- if (!APIKey || !APISecret) {
570
+ if (!apiKey || !apiSecret) {
552
571
  throw new Error("No valid Alpaca authentication found. Please provide either auth object or set ALPACA_API_KEY and ALPACA_API_SECRET environment variables.");
553
572
  }
554
573
  const url = `${apiBaseUrlInner}${endpoint}${queryString || ""}`;
@@ -559,8 +578,8 @@ async function makeRequest(auth, params) {
559
578
  const fetchOptions = {
560
579
  method,
561
580
  headers: {
562
- "APCA-API-KEY-ID": APIKey,
563
- "APCA-API-SECRET-KEY": APISecret,
581
+ "APCA-API-KEY-ID": apiKey,
582
+ "APCA-API-SECRET-KEY": apiSecret,
564
583
  },
565
584
  };
566
585
  // Only add Content-Type and body for non-GET/HEAD requests that have a body
@@ -604,13 +623,13 @@ async function makeRequest(auth, params) {
604
623
  */
605
624
  async function createOrder$1(auth, params) {
606
625
  try {
607
- const { APIKey, APISecret, type } = await validateAuth(auth);
626
+ const { apiKey, apiSecret, type } = await validateAuth(auth);
608
627
  const apiBaseUrl = getTradingApiUrl(type);
609
628
  const response = await fetch(`${apiBaseUrl}/v2/orders`, {
610
629
  method: "POST",
611
630
  headers: {
612
- "APCA-API-KEY-ID": APIKey,
613
- "APCA-API-SECRET-KEY": APISecret,
631
+ "APCA-API-KEY-ID": apiKey,
632
+ "APCA-API-SECRET-KEY": apiSecret,
614
633
  "Content-Type": "application/json",
615
634
  },
616
635
  body: JSON.stringify(params),
@@ -635,7 +654,7 @@ async function createOrder$1(auth, params) {
635
654
  */
636
655
  async function getOrders$1(auth, params = {}) {
637
656
  try {
638
- const { APIKey, APISecret, type } = await validateAuth(auth);
657
+ const { apiKey, apiSecret, type } = await validateAuth(auth);
639
658
  const apiBaseUrl = getTradingApiUrl(type);
640
659
  const allOrders = [];
641
660
  let currentUntil = params.until ? params.until : new Date().toISOString();
@@ -658,8 +677,8 @@ async function getOrders$1(auth, params = {}) {
658
677
  const response = await fetch(`${apiBaseUrl}/v2/orders?${queryParams}`, {
659
678
  method: "GET",
660
679
  headers: {
661
- "APCA-API-KEY-ID": APIKey,
662
- "APCA-API-SECRET-KEY": APISecret,
680
+ "APCA-API-KEY-ID": apiKey,
681
+ "APCA-API-SECRET-KEY": apiSecret,
663
682
  },
664
683
  signal: createTimeoutSignal(DEFAULT_TIMEOUTS.ALPACA_API),
665
684
  });
@@ -691,13 +710,13 @@ async function getOrders$1(auth, params = {}) {
691
710
  */
692
711
  async function cancelAllOrders$1(auth) {
693
712
  try {
694
- const { APIKey, APISecret, type } = await validateAuth(auth);
713
+ const { apiKey, apiSecret, type } = await validateAuth(auth);
695
714
  const apiBaseUrl = getTradingApiUrl(type);
696
715
  const response = await fetch(`${apiBaseUrl}/v2/orders`, {
697
716
  method: "DELETE",
698
717
  headers: {
699
- "APCA-API-KEY-ID": APIKey,
700
- "APCA-API-SECRET-KEY": APISecret,
718
+ "APCA-API-KEY-ID": apiKey,
719
+ "APCA-API-SECRET-KEY": apiSecret,
701
720
  },
702
721
  signal: createTimeoutSignal(DEFAULT_TIMEOUTS.ALPACA_API),
703
722
  });
@@ -721,7 +740,7 @@ async function cancelAllOrders$1(auth) {
721
740
  */
722
741
  async function getOrder$1(auth, orderId, nested) {
723
742
  try {
724
- const { APIKey, APISecret, type } = await validateAuth(auth);
743
+ const { apiKey, apiSecret, type } = await validateAuth(auth);
725
744
  const apiBaseUrl = getTradingApiUrl(type);
726
745
  const queryParams = new URLSearchParams();
727
746
  if (nested)
@@ -729,8 +748,8 @@ async function getOrder$1(auth, orderId, nested) {
729
748
  const response = await fetch(`${apiBaseUrl}/v2/orders/${orderId}?${queryParams}`, {
730
749
  method: "GET",
731
750
  headers: {
732
- "APCA-API-KEY-ID": APIKey,
733
- "APCA-API-SECRET-KEY": APISecret,
751
+ "APCA-API-KEY-ID": apiKey,
752
+ "APCA-API-SECRET-KEY": apiSecret,
734
753
  },
735
754
  signal: createTimeoutSignal(DEFAULT_TIMEOUTS.ALPACA_API),
736
755
  });
@@ -754,13 +773,13 @@ async function getOrder$1(auth, orderId, nested) {
754
773
  */
755
774
  async function replaceOrder$1(auth, orderId, params) {
756
775
  try {
757
- const { APIKey, APISecret, type } = await validateAuth(auth);
776
+ const { apiKey, apiSecret, type } = await validateAuth(auth);
758
777
  const apiBaseUrl = getTradingApiUrl(type);
759
778
  const response = await fetch(`${apiBaseUrl}/v2/orders/${orderId}`, {
760
779
  method: "PATCH",
761
780
  headers: {
762
- "APCA-API-KEY-ID": APIKey,
763
- "APCA-API-SECRET-KEY": APISecret,
781
+ "APCA-API-KEY-ID": apiKey,
782
+ "APCA-API-SECRET-KEY": apiSecret,
764
783
  "Content-Type": "application/json",
765
784
  accept: "application/json",
766
785
  },
@@ -786,13 +805,13 @@ async function replaceOrder$1(auth, orderId, params) {
786
805
  */
787
806
  async function cancelOrder$1(auth, orderId) {
788
807
  try {
789
- const { APIKey, APISecret, type } = await validateAuth(auth);
808
+ const { apiKey, apiSecret, type } = await validateAuth(auth);
790
809
  const apiBaseUrl = getTradingApiUrl(type);
791
810
  const response = await fetch(`${apiBaseUrl}/v2/orders/${orderId}`, {
792
811
  method: "DELETE",
793
812
  headers: {
794
- "APCA-API-KEY-ID": APIKey,
795
- "APCA-API-SECRET-KEY": APISecret,
813
+ "APCA-API-KEY-ID": apiKey,
814
+ "APCA-API-SECRET-KEY": apiSecret,
796
815
  },
797
816
  signal: createTimeoutSignal(DEFAULT_TIMEOUTS.ALPACA_API),
798
817
  });
@@ -1374,14 +1393,14 @@ async function fetchNews$1(symbols, params) {
1374
1393
  }
1375
1394
  else if (mergedParams.auth.adapticAccountId) {
1376
1395
  const client = await getSharedApolloClient();
1377
- const alpacaAccount = (await adaptic$1.alpacaAccount.get({
1396
+ const brokerageAccount = (await adaptic$1.brokerageAccount.get({
1378
1397
  id: mergedParams.auth.adapticAccountId,
1379
1398
  }, client));
1380
- if (!alpacaAccount || !alpacaAccount.APIKey || !alpacaAccount.APISecret) {
1399
+ if (!brokerageAccount || !brokerageAccount.apiKey || !brokerageAccount.apiSecret) {
1381
1400
  throw new Error("Alpaca account not found or incomplete");
1382
1401
  }
1383
- APIKey = alpacaAccount.APIKey;
1384
- APISecret = alpacaAccount.APISecret;
1402
+ APIKey = brokerageAccount.apiKey;
1403
+ APISecret = brokerageAccount.apiSecret;
1385
1404
  }
1386
1405
  }
1387
1406
  else {
@@ -1474,14 +1493,14 @@ async function fetchNews$1(symbols, params) {
1474
1493
  */
1475
1494
  async function fetchAllPositions(auth) {
1476
1495
  try {
1477
- const { APIKey, APISecret, type } = await validateAuth(auth);
1496
+ const { apiKey, apiSecret, type } = await validateAuth(auth);
1478
1497
  const apiBaseUrl = getTradingApiUrl(type);
1479
1498
  const apiUrl = `${apiBaseUrl}/v2/positions`;
1480
1499
  const response = await fetch(apiUrl, {
1481
1500
  method: "GET",
1482
1501
  headers: {
1483
- "APCA-API-KEY-ID": APIKey,
1484
- "APCA-API-SECRET-KEY": APISecret,
1502
+ "APCA-API-KEY-ID": apiKey,
1503
+ "APCA-API-SECRET-KEY": apiSecret,
1485
1504
  "Content-Type": "application/json",
1486
1505
  },
1487
1506
  signal: createTimeoutSignal(DEFAULT_TIMEOUTS.ALPACA_API),
@@ -1505,13 +1524,13 @@ async function fetchAllPositions(auth) {
1505
1524
  */
1506
1525
  async function fetchPosition(auth, symbolOrAssetId) {
1507
1526
  try {
1508
- const { APIKey, APISecret, type } = await validateAuth(auth);
1527
+ const { apiKey, apiSecret, type } = await validateAuth(auth);
1509
1528
  const apiBaseUrl = getTradingApiUrl(type);
1510
1529
  const response = await fetch(`${apiBaseUrl}/v2/positions/${symbolOrAssetId}`, {
1511
1530
  method: "GET",
1512
1531
  headers: {
1513
- "APCA-API-KEY-ID": APIKey,
1514
- "APCA-API-SECRET-KEY": APISecret,
1532
+ "APCA-API-KEY-ID": apiKey,
1533
+ "APCA-API-SECRET-KEY": apiSecret,
1515
1534
  "Content-Type": "application/json",
1516
1535
  },
1517
1536
  signal: createTimeoutSignal(DEFAULT_TIMEOUTS.ALPACA_API),
@@ -1545,7 +1564,7 @@ async function fetchPosition(auth, symbolOrAssetId) {
1545
1564
  */
1546
1565
  async function closePosition$1(auth, symbolOrAssetId, params) {
1547
1566
  try {
1548
- const { APIKey, APISecret, type } = await validateAuth(auth);
1567
+ const { apiKey, apiSecret, type } = await validateAuth(auth);
1549
1568
  const apiBaseUrl = getTradingApiUrl(type);
1550
1569
  const useLimitOrder = params?.useLimitOrder ?? false;
1551
1570
  const cancelOrdersFlag = params?.cancelOrders ?? true;
@@ -1628,8 +1647,8 @@ async function closePosition$1(auth, symbolOrAssetId, params) {
1628
1647
  const response = await fetch(url, {
1629
1648
  method: "DELETE",
1630
1649
  headers: {
1631
- "APCA-API-KEY-ID": APIKey,
1632
- "APCA-API-SECRET-KEY": APISecret,
1650
+ "APCA-API-KEY-ID": apiKey,
1651
+ "APCA-API-SECRET-KEY": apiSecret,
1633
1652
  },
1634
1653
  });
1635
1654
  if (!response.ok) {
@@ -1820,20 +1839,20 @@ async function closeAllPositionsAfterHours$1(auth, params = { cancel_orders: tru
1820
1839
  * @param props - The properties for fetching account details
1821
1840
  * @returns The account details
1822
1841
  */
1823
- async function fetchAccountDetails({ accountId, client, alpacaAccount, auth, }) {
1824
- let alpacaAccountObj = alpacaAccount ? alpacaAccount : null;
1825
- if (!alpacaAccountObj && auth) {
1842
+ async function fetchAccountDetails({ accountId, client, brokerageAccount, auth, }) {
1843
+ let brokerageAccountObj = brokerageAccount ? brokerageAccount : null;
1844
+ if (!brokerageAccountObj && auth) {
1826
1845
  const validatedAuth = await validateAuth(auth);
1827
- alpacaAccountObj = {
1828
- APIKey: validatedAuth.APIKey,
1829
- APISecret: validatedAuth.APISecret,
1846
+ brokerageAccountObj = {
1847
+ apiKey: validatedAuth.apiKey,
1848
+ apiSecret: validatedAuth.apiSecret,
1830
1849
  type: validatedAuth.type,
1831
1850
  };
1832
1851
  }
1833
- if (!alpacaAccountObj) {
1852
+ if (!brokerageAccountObj) {
1834
1853
  try {
1835
1854
  const apolloClient = client || (await getSharedApolloClient());
1836
- alpacaAccountObj = (await adaptic$1.alpacaAccount.get({
1855
+ brokerageAccountObj = (await adaptic$1.brokerageAccount.get({
1837
1856
  id: accountId,
1838
1857
  }, apolloClient));
1839
1858
  }
@@ -1842,19 +1861,19 @@ async function fetchAccountDetails({ accountId, client, alpacaAccount, auth, })
1842
1861
  throw error;
1843
1862
  }
1844
1863
  }
1845
- if (!alpacaAccountObj ||
1846
- !alpacaAccountObj.APIKey ||
1847
- !alpacaAccountObj.APISecret) {
1864
+ if (!brokerageAccountObj ||
1865
+ !brokerageAccountObj.apiKey ||
1866
+ !brokerageAccountObj.apiSecret) {
1848
1867
  throw new Error("[fetchAccountDetails] Alpaca account not found or incomplete");
1849
1868
  }
1850
- const { APIKey, APISecret, type } = alpacaAccountObj;
1869
+ const { apiKey, apiSecret, type } = brokerageAccountObj;
1851
1870
  const apiUrl = `${getTradingApiUrl(type)}/account`;
1852
1871
  try {
1853
1872
  const response = await fetch(apiUrl, {
1854
1873
  method: "GET",
1855
1874
  headers: {
1856
- "APCA-API-KEY-ID": APIKey,
1857
- "APCA-API-SECRET-KEY": APISecret,
1875
+ "APCA-API-KEY-ID": apiKey,
1876
+ "APCA-API-SECRET-KEY": apiSecret,
1858
1877
  "Content-Type": "application/json",
1859
1878
  },
1860
1879
  signal: createTimeoutSignal(DEFAULT_TIMEOUTS.ALPACA_API),
@@ -1875,12 +1894,12 @@ async function fetchAccountDetails({ accountId, client, alpacaAccount, auth, })
1875
1894
  * @param props - The properties for fetching portfolio history
1876
1895
  * @returns The portfolio history
1877
1896
  */
1878
- async function fetchPortfolioHistory({ params, accountId, client, alpacaAccount, }) {
1879
- let alpacaAccountObj = alpacaAccount ? alpacaAccount : null;
1880
- if (!alpacaAccountObj) {
1897
+ async function fetchPortfolioHistory({ params, accountId, client, brokerageAccount, }) {
1898
+ let brokerageAccountObj = brokerageAccount ? brokerageAccount : null;
1899
+ if (!brokerageAccountObj) {
1881
1900
  try {
1882
1901
  const apolloClient = client || (await getSharedApolloClient());
1883
- alpacaAccountObj = (await adaptic$1.alpacaAccount.get({
1902
+ brokerageAccountObj = (await adaptic$1.brokerageAccount.get({
1884
1903
  id: accountId,
1885
1904
  }, apolloClient));
1886
1905
  }
@@ -1889,12 +1908,12 @@ async function fetchPortfolioHistory({ params, accountId, client, alpacaAccount,
1889
1908
  throw error;
1890
1909
  }
1891
1910
  }
1892
- if (!alpacaAccountObj ||
1893
- !alpacaAccountObj.APIKey ||
1894
- !alpacaAccountObj.APISecret) {
1911
+ if (!brokerageAccountObj ||
1912
+ !brokerageAccountObj.apiKey ||
1913
+ !brokerageAccountObj.apiSecret) {
1895
1914
  throw new Error("[fetchPortfolioHistory] Alpaca account not found or incomplete");
1896
1915
  }
1897
- const { APIKey, APISecret, type } = alpacaAccountObj;
1916
+ const { apiKey, apiSecret, type } = brokerageAccountObj;
1898
1917
  const apiBaseUrl = getTradingApiUrl(type);
1899
1918
  const apiUrl = `${apiBaseUrl}/v2/account/portfolio/history`;
1900
1919
  const { start, end, period } = params;
@@ -1920,8 +1939,8 @@ async function fetchPortfolioHistory({ params, accountId, client, alpacaAccount,
1920
1939
  const response = await fetch(fullUrl, {
1921
1940
  method: "GET",
1922
1941
  headers: {
1923
- "APCA-API-KEY-ID": APIKey,
1924
- "APCA-API-SECRET-KEY": APISecret,
1942
+ "APCA-API-KEY-ID": apiKey,
1943
+ "APCA-API-SECRET-KEY": apiSecret,
1925
1944
  "Content-Type": "application/json",
1926
1945
  },
1927
1946
  signal: createTimeoutSignal(DEFAULT_TIMEOUTS.ALPACA_API),
@@ -1948,31 +1967,31 @@ async function getConfiguration(account) {
1948
1967
  if (!account) {
1949
1968
  throw new Error(`Account is missing.`);
1950
1969
  }
1951
- const { APIKey, APISecret } = account;
1952
- if (!APIKey || !APISecret) {
1953
- throw new Error("User APIKey or APISecret is missing.");
1970
+ const { apiKey, apiSecret } = account;
1971
+ if (!apiKey || !apiSecret) {
1972
+ throw new Error("Account apiKey or apiSecret is missing.");
1954
1973
  }
1955
1974
  const apiUrl = getTradingApiUrl(account.type);
1956
1975
  const client = await getSharedApolloClient();
1957
- const [alpacaResponse, freshAlpacaAccount] = await Promise.all([
1976
+ const [alpacaResponse, freshBrokerageAccount] = await Promise.all([
1958
1977
  fetch(`${apiUrl}/account/configurations`, {
1959
1978
  method: "GET",
1960
1979
  headers: {
1961
- "APCA-API-KEY-ID": APIKey,
1962
- "APCA-API-SECRET-KEY": APISecret,
1980
+ "APCA-API-KEY-ID": apiKey,
1981
+ "APCA-API-SECRET-KEY": apiSecret,
1963
1982
  accept: "application/json",
1964
1983
  },
1965
1984
  }),
1966
- adaptic$1.alpacaAccount.get({ id: account.id }, client),
1985
+ adaptic$1.brokerageAccount.get({ id: account.id }, client),
1967
1986
  ]);
1968
1987
  if (!alpacaResponse.ok) {
1969
1988
  throw new Error(`Failed to fetch account configuration: ${alpacaResponse.statusText}`);
1970
1989
  }
1971
- if (!freshAlpacaAccount) {
1990
+ if (!freshBrokerageAccount) {
1972
1991
  throw new Error("Failed to get Alpaca Account from @adaptic/backend-legacy.");
1973
1992
  }
1974
1993
  const dataFromAlpaca = (await alpacaResponse.json());
1975
- const accountWithAllocation = freshAlpacaAccount;
1994
+ const accountWithAllocation = freshBrokerageAccount;
1976
1995
  const allocationData = accountWithAllocation.allocation || {
1977
1996
  stocks: 70,
1978
1997
  options: 0,
@@ -1983,26 +2002,26 @@ async function getConfiguration(account) {
1983
2002
  };
1984
2003
  const combinedConfig = {
1985
2004
  ...dataFromAlpaca,
1986
- marketOpen: freshAlpacaAccount.marketOpen,
1987
- realTime: freshAlpacaAccount.realTime,
1988
- tradeAllocationPct: freshAlpacaAccount.tradeAllocationPct,
1989
- minPercentageChange: freshAlpacaAccount.minPercentageChange,
1990
- volumeThreshold: freshAlpacaAccount.volumeThreshold,
1991
- cryptoTradingEnabled: freshAlpacaAccount.cryptoTradingEnabled ?? false,
1992
- cryptoTradingPairs: freshAlpacaAccount.cryptoTradingPairs ?? [],
1993
- cryptoTradeAllocationPct: freshAlpacaAccount.cryptoTradeAllocationPct ?? 5.0,
2005
+ marketOpen: freshBrokerageAccount.marketOpen,
2006
+ realTime: freshBrokerageAccount.realTime,
2007
+ tradeAllocationPct: freshBrokerageAccount.tradeAllocationPct,
2008
+ minPercentageChange: freshBrokerageAccount.minPercentageChange,
2009
+ volumeThreshold: freshBrokerageAccount.volumeThreshold,
2010
+ cryptoTradingEnabled: freshBrokerageAccount.cryptoTradingEnabled ?? false,
2011
+ cryptoTradingPairs: freshBrokerageAccount.cryptoTradingPairs ?? [],
2012
+ cryptoTradeAllocationPct: freshBrokerageAccount.cryptoTradeAllocationPct ?? 5.0,
1994
2013
  autoAllocation: accountWithAllocation.autoAllocation ?? false,
1995
2014
  allocation: allocationData,
1996
- enablePortfolioTrailingStop: freshAlpacaAccount.enablePortfolioTrailingStop,
1997
- portfolioTrailPercent: freshAlpacaAccount.portfolioTrailPercent,
1998
- portfolioProfitThresholdPercent: freshAlpacaAccount.portfolioProfitThresholdPercent,
1999
- reducedPortfolioTrailPercent: freshAlpacaAccount.reducedPortfolioTrailPercent,
2000
- defaultTrailingStopPercentage100: freshAlpacaAccount.defaultTrailingStopPercentage100 ?? 4.0,
2001
- firstTrailReductionThreshold100: freshAlpacaAccount.firstTrailReductionThreshold100 ?? 2.0,
2002
- secondTrailReductionThreshold100: freshAlpacaAccount.secondTrailReductionThreshold100 ?? 5.0,
2003
- firstReducedTrailPercentage100: freshAlpacaAccount.firstReducedTrailPercentage100 ?? 1.0,
2004
- secondReducedTrailPercentage100: freshAlpacaAccount.secondReducedTrailPercentage100 ?? 0.5,
2005
- minimumPriceChangePercent100: freshAlpacaAccount.minimumPriceChangePercent100 ?? 0.5,
2015
+ enablePortfolioTrailingStop: freshBrokerageAccount.enablePortfolioTrailingStop,
2016
+ portfolioTrailPercent: freshBrokerageAccount.portfolioTrailPercent,
2017
+ portfolioProfitThresholdPercent: freshBrokerageAccount.portfolioProfitThresholdPercent,
2018
+ reducedPortfolioTrailPercent: freshBrokerageAccount.reducedPortfolioTrailPercent,
2019
+ defaultTrailingStopPercentage100: freshBrokerageAccount.defaultTrailingStopPercentage100 ?? 4.0,
2020
+ firstTrailReductionThreshold100: freshBrokerageAccount.firstTrailReductionThreshold100 ?? 2.0,
2021
+ secondTrailReductionThreshold100: freshBrokerageAccount.secondTrailReductionThreshold100 ?? 5.0,
2022
+ firstReducedTrailPercentage100: freshBrokerageAccount.firstReducedTrailPercentage100 ?? 1.0,
2023
+ secondReducedTrailPercentage100: freshBrokerageAccount.secondReducedTrailPercentage100 ?? 0.5,
2024
+ minimumPriceChangePercent100: freshBrokerageAccount.minimumPriceChangePercent100 ?? 0.5,
2006
2025
  };
2007
2026
  return combinedConfig;
2008
2027
  }
@@ -2023,9 +2042,9 @@ async function updateConfiguration(user, account, updatedConfig) {
2023
2042
  if (!account) {
2024
2043
  throw new Error(`Account is missing.`);
2025
2044
  }
2026
- const { APIKey, APISecret } = account;
2027
- if (!APIKey || !APISecret) {
2028
- throw new Error("User APIKey or APISecret is missing.");
2045
+ const { apiKey, apiSecret } = account;
2046
+ if (!apiKey || !apiSecret) {
2047
+ throw new Error("Account apiKey or apiSecret is missing.");
2029
2048
  }
2030
2049
  const apiUrl = getTradingApiUrl(account.type);
2031
2050
  // Prepare the config object for Alpaca by removing DB-only fields
@@ -2053,8 +2072,8 @@ async function updateConfiguration(user, account, updatedConfig) {
2053
2072
  const alpacaUpdatePromise = fetch(`${apiUrl}/account/configurations`, {
2054
2073
  method: "PATCH",
2055
2074
  headers: {
2056
- "APCA-API-KEY-ID": APIKey,
2057
- "APCA-API-SECRET-KEY": APISecret,
2075
+ "APCA-API-KEY-ID": apiKey,
2076
+ "APCA-API-SECRET-KEY": apiSecret,
2058
2077
  "Content-Type": "application/json",
2059
2078
  accept: "application/json",
2060
2079
  },
@@ -2075,10 +2094,10 @@ async function updateConfiguration(user, account, updatedConfig) {
2075
2094
  if (account.allocation) {
2076
2095
  allocUpdatePromise = adaptic$1.allocation.update({
2077
2096
  id: account.allocation.id,
2078
- alpacaAccount: {
2097
+ brokerageAccount: {
2079
2098
  id: account.id,
2080
2099
  },
2081
- alpacaAccountId: account.id,
2100
+ brokerageAccountId: account.id,
2082
2101
  stocks: updatedConfig.allocation.stocks ?? 0,
2083
2102
  options: updatedConfig.allocation.options ?? 0,
2084
2103
  futures: updatedConfig.allocation.futures ?? 0,
@@ -2095,14 +2114,14 @@ async function updateConfiguration(user, account, updatedConfig) {
2095
2114
  etfs: updatedConfig.allocation.etfs ?? 0,
2096
2115
  forex: updatedConfig.allocation.forex ?? 0,
2097
2116
  crypto: updatedConfig.allocation.crypto ?? 0,
2098
- alpacaAccount: {
2117
+ brokerageAccount: {
2099
2118
  id: account.id,
2100
2119
  },
2101
- alpacaAccountId: account.id,
2120
+ brokerageAccountId: account.id,
2102
2121
  }, client);
2103
2122
  }
2104
2123
  }
2105
- const adapticUpdatePromise = adaptic$1.alpacaAccount.update({
2124
+ const adapticUpdatePromise = adaptic$1.brokerageAccount.update({
2106
2125
  id: account.id,
2107
2126
  user: {
2108
2127
  id: user.id,
@@ -2129,7 +2148,7 @@ async function updateConfiguration(user, account, updatedConfig) {
2129
2148
  secondReducedTrailPercentage100: updatedConfig.secondReducedTrailPercentage100 ?? 0,
2130
2149
  minimumPriceChangePercent100: updatedConfig.minimumPriceChangePercent100 ?? 0,
2131
2150
  }, client);
2132
- const [alpacaResponse, updatedAlpacaAccount, updatedAllocation] = await Promise.all([
2151
+ const [alpacaResponse, updatedBrokerageAccount, updatedAllocation] = await Promise.all([
2133
2152
  alpacaUpdatePromise,
2134
2153
  adapticUpdatePromise,
2135
2154
  allocUpdatePromise,
@@ -2149,10 +2168,10 @@ async function updateConfiguration(user, account, updatedConfig) {
2149
2168
  throw new Error(`Failed to update account config at Alpaca: ${alpacaResponse.statusText}`);
2150
2169
  }
2151
2170
  const alpacaData = (await alpacaResponse.json());
2152
- if (!updatedAlpacaAccount) {
2171
+ if (!updatedBrokerageAccount) {
2153
2172
  throw new Error("Failed to update Alpaca Account in @adaptic/backend-legacy.");
2154
2173
  }
2155
- const updatedAccountWithAllocation = updatedAlpacaAccount;
2174
+ const updatedAccountWithAllocation = updatedBrokerageAccount;
2156
2175
  const selectedAllocation = (updatedConfig.allocation ||
2157
2176
  updatedAllocation ||
2158
2177
  updatedAccountWithAllocation.allocation);
@@ -2162,26 +2181,26 @@ async function updateConfiguration(user, account, updatedConfig) {
2162
2181
  getLogger().info("Final allocation:", selectedAllocation);
2163
2182
  const finalConfig = {
2164
2183
  ...alpacaData,
2165
- marketOpen: updatedAlpacaAccount.marketOpen,
2166
- realTime: updatedAlpacaAccount.realTime,
2167
- tradeAllocationPct: updatedAlpacaAccount.tradeAllocationPct,
2168
- minPercentageChange: updatedAlpacaAccount.minPercentageChange,
2169
- volumeThreshold: updatedAlpacaAccount.volumeThreshold,
2170
- cryptoTradingEnabled: updatedAlpacaAccount.cryptoTradingEnabled,
2171
- cryptoTradingPairs: updatedAlpacaAccount.cryptoTradingPairs,
2172
- cryptoTradeAllocationPct: updatedAlpacaAccount.cryptoTradeAllocationPct,
2184
+ marketOpen: updatedBrokerageAccount.marketOpen,
2185
+ realTime: updatedBrokerageAccount.realTime,
2186
+ tradeAllocationPct: updatedBrokerageAccount.tradeAllocationPct,
2187
+ minPercentageChange: updatedBrokerageAccount.minPercentageChange,
2188
+ volumeThreshold: updatedBrokerageAccount.volumeThreshold,
2189
+ cryptoTradingEnabled: updatedBrokerageAccount.cryptoTradingEnabled,
2190
+ cryptoTradingPairs: updatedBrokerageAccount.cryptoTradingPairs,
2191
+ cryptoTradeAllocationPct: updatedBrokerageAccount.cryptoTradeAllocationPct,
2173
2192
  autoAllocation: updatedAccountWithAllocation.autoAllocation,
2174
2193
  allocation: selectedAllocation,
2175
- enablePortfolioTrailingStop: updatedAlpacaAccount.enablePortfolioTrailingStop,
2176
- portfolioTrailPercent: updatedAlpacaAccount.portfolioTrailPercent,
2177
- portfolioProfitThresholdPercent: updatedAlpacaAccount.portfolioProfitThresholdPercent,
2178
- reducedPortfolioTrailPercent: updatedAlpacaAccount.reducedPortfolioTrailPercent,
2179
- defaultTrailingStopPercentage100: updatedAlpacaAccount.defaultTrailingStopPercentage100,
2180
- firstTrailReductionThreshold100: updatedAlpacaAccount.firstTrailReductionThreshold100,
2181
- secondTrailReductionThreshold100: updatedAlpacaAccount.secondTrailReductionThreshold100,
2182
- firstReducedTrailPercentage100: updatedAlpacaAccount.firstReducedTrailPercentage100,
2183
- secondReducedTrailPercentage100: updatedAlpacaAccount.secondReducedTrailPercentage100,
2184
- minimumPriceChangePercent100: updatedAlpacaAccount.minimumPriceChangePercent100,
2194
+ enablePortfolioTrailingStop: updatedBrokerageAccount.enablePortfolioTrailingStop,
2195
+ portfolioTrailPercent: updatedBrokerageAccount.portfolioTrailPercent,
2196
+ portfolioProfitThresholdPercent: updatedBrokerageAccount.portfolioProfitThresholdPercent,
2197
+ reducedPortfolioTrailPercent: updatedBrokerageAccount.reducedPortfolioTrailPercent,
2198
+ defaultTrailingStopPercentage100: updatedBrokerageAccount.defaultTrailingStopPercentage100,
2199
+ firstTrailReductionThreshold100: updatedBrokerageAccount.firstTrailReductionThreshold100,
2200
+ secondTrailReductionThreshold100: updatedBrokerageAccount.secondTrailReductionThreshold100,
2201
+ firstReducedTrailPercentage100: updatedBrokerageAccount.firstReducedTrailPercentage100,
2202
+ secondReducedTrailPercentage100: updatedBrokerageAccount.secondReducedTrailPercentage100,
2203
+ minimumPriceChangePercent100: updatedBrokerageAccount.minimumPriceChangePercent100,
2185
2204
  };
2186
2205
  return finalConfig;
2187
2206
  }
@@ -2199,15 +2218,15 @@ async function updateConfiguration(user, account, updatedConfig) {
2199
2218
  */
2200
2219
  async function getAsset(auth, symbolOrAssetId) {
2201
2220
  try {
2202
- const { APIKey, APISecret, type } = await validateAuth(auth);
2221
+ const { apiKey, apiSecret, type } = await validateAuth(auth);
2203
2222
  const apiBaseUrl = getTradingApiUrl(type);
2204
2223
  // Use encodeURIComponent to handle special characters in symbols (e.g., BTC/USDT)
2205
2224
  const encodedSymbolOrAssetId = encodeURIComponent(symbolOrAssetId);
2206
2225
  const response = await fetch(`${apiBaseUrl}/v2/assets/${encodedSymbolOrAssetId}`, {
2207
2226
  method: "GET",
2208
2227
  headers: {
2209
- "APCA-API-KEY-ID": APIKey,
2210
- "APCA-API-SECRET-KEY": APISecret,
2228
+ "APCA-API-KEY-ID": apiKey,
2229
+ "APCA-API-SECRET-KEY": apiSecret,
2211
2230
  "Content-Type": "application/json",
2212
2231
  },
2213
2232
  signal: createTimeoutSignal(DEFAULT_TIMEOUTS.ALPACA_API),
@@ -3264,24 +3283,24 @@ async function calculateTotalReturnYTD(portfolioHistory) {
3264
3283
  * Calculates the expense ratio for a given Alpaca account.
3265
3284
  * @param accountId - The ID of the Alpaca account.
3266
3285
  * @param client - The Apollo client instance.
3267
- * @param alpacaAccount - The Alpaca account object.
3286
+ * @param brokerageAccount - The Alpaca account object.
3268
3287
  * @returns A promise that resolves to a string representing the expense ratio in percentage format.
3269
3288
  */
3270
- async function calculateExpenseRatio$1({ accountId, client, alpacaAccount, }) {
3271
- if (!accountId && !alpacaAccount && !client) {
3289
+ async function calculateExpenseRatio$1({ accountId, client, brokerageAccount, }) {
3290
+ if (!accountId && !brokerageAccount && !client) {
3272
3291
  getLogger().warn("Missing account ID or client to calculate expense ratio.");
3273
3292
  return "N/A";
3274
3293
  }
3275
- let alpacaAccountId = accountId || (alpacaAccount && alpacaAccount.id) || "";
3294
+ let brokerageAccountId = accountId || (brokerageAccount && brokerageAccount.id) || "";
3276
3295
  let accountDetails;
3277
- if (!alpacaAccountId) {
3296
+ if (!brokerageAccountId) {
3278
3297
  getLogger().warn("Invalid account ID.");
3279
3298
  return "N/A";
3280
3299
  }
3281
- if (alpacaAccount) {
3300
+ if (brokerageAccount) {
3282
3301
  // Use Alpaca account object to get accountDetails
3283
3302
  accountDetails = (await fetchAccountDetails({
3284
- alpacaAccount: alpacaAccount,
3303
+ brokerageAccount: brokerageAccount,
3285
3304
  }));
3286
3305
  if (!accountDetails) {
3287
3306
  getLogger().warn("Failed to fetch account details inside calculateExpenseRatio.");
@@ -3320,24 +3339,24 @@ async function getPortfolioExpensesFromYourSystem(accountId) {
3320
3339
  * Calculates the liquidity ratio for a given Alpaca account.
3321
3340
  * @param accountId - The ID of the Alpaca account.
3322
3341
  * @param client - The Apollo client instance.
3323
- * @param alpacaAccount - The Alpaca account object.
3342
+ * @param brokerageAccount - The Alpaca account object.
3324
3343
  * @returns A promise that resolves to a string representing the liquidity ratio in the format "1:ratio".
3325
3344
  */
3326
- async function calculateLiquidityRatio({ accountId, client, alpacaAccount, }) {
3327
- if (!accountId && !alpacaAccount && !client) {
3345
+ async function calculateLiquidityRatio({ accountId, client, brokerageAccount, }) {
3346
+ if (!accountId && !brokerageAccount && !client) {
3328
3347
  getLogger().warn("Missing account ID or client to calculateLiquidityRatio.");
3329
3348
  return "N/A";
3330
3349
  }
3331
- let alpacaAccountId = accountId || (alpacaAccount && alpacaAccount.id) || "";
3350
+ let brokerageAccountId = accountId || (brokerageAccount && brokerageAccount.id) || "";
3332
3351
  let accountDetails;
3333
- if (!alpacaAccountId) {
3352
+ if (!brokerageAccountId) {
3334
3353
  getLogger().warn("Invalid account ID.");
3335
3354
  return "N/A";
3336
3355
  }
3337
- if (alpacaAccount) {
3356
+ if (brokerageAccount) {
3338
3357
  // Use Alpaca account object to get accountDetails
3339
3358
  accountDetails = (await fetchAccountDetails({
3340
- alpacaAccount: alpacaAccount,
3359
+ brokerageAccount: brokerageAccount,
3341
3360
  }));
3342
3361
  if (!accountDetails) {
3343
3362
  getLogger().warn("Failed to fetch account details inside calculateLiquidityRatio.");
@@ -3965,11 +3984,11 @@ async function calculateInformationRatio$1(portfolioHistory, benchmarkBars) {
3965
3984
  * @param params - The parameters for fetching performance metrics.
3966
3985
  * @param client - The Apollo client instance.
3967
3986
  * @param accountId - The ID of the Alpaca account.
3968
- * @param alpacaAccount - The Alpaca account object.
3987
+ * @param brokerageAccount - The Alpaca account object.
3969
3988
  * @returns A promise that resolves to an object containing various performance metrics.
3970
3989
  * @throws Will throw an error if required parameters are missing or if fetching fails.
3971
3990
  */
3972
- async function fetchPerformanceMetrics({ params, client, accountId, alpacaAccount, }) {
3991
+ async function fetchPerformanceMetrics({ params, client, accountId, brokerageAccount, }) {
3973
3992
  // Default response for error cases
3974
3993
  const defaultMetrics = {
3975
3994
  totalReturnYTD: "N/A",
@@ -3992,12 +4011,12 @@ async function fetchPerformanceMetrics({ params, client, accountId, alpacaAccoun
3992
4011
  throw new Error("Missing required timeframe or period parameters");
3993
4012
  }
3994
4013
  // Obtain Alpaca account
3995
- let alpacaAccountObj = alpacaAccount ? alpacaAccount : null;
3996
- if (!alpacaAccountObj && accountId) {
4014
+ let brokerageAccountObj = brokerageAccount ? brokerageAccount : null;
4015
+ if (!brokerageAccountObj && accountId) {
3997
4016
  try {
3998
4017
  // Use provided client or get the shared client
3999
4018
  const apolloClient = client || (await getSharedApolloClient());
4000
- alpacaAccountObj = (await adaptic$1.alpacaAccount.get({
4019
+ brokerageAccountObj = (await adaptic$1.brokerageAccount.get({
4001
4020
  id: accountId,
4002
4021
  }, apolloClient));
4003
4022
  }
@@ -4007,9 +4026,9 @@ async function fetchPerformanceMetrics({ params, client, accountId, alpacaAccoun
4007
4026
  }
4008
4027
  }
4009
4028
  // Validate Alpaca account
4010
- if (!alpacaAccountObj ||
4011
- !alpacaAccountObj.APIKey ||
4012
- !alpacaAccountObj.APISecret) {
4029
+ if (!brokerageAccountObj ||
4030
+ !brokerageAccountObj.apiKey ||
4031
+ !brokerageAccountObj.apiSecret) {
4013
4032
  throw new Error("Alpaca account not found or credentials missing");
4014
4033
  }
4015
4034
  // Fetch portfolio history with structured error handling
@@ -4017,7 +4036,7 @@ async function fetchPerformanceMetrics({ params, client, accountId, alpacaAccoun
4017
4036
  try {
4018
4037
  portfolioHistory = await fetchPortfolioHistory({
4019
4038
  params: params,
4020
- alpacaAccount: alpacaAccountObj,
4039
+ brokerageAccount: brokerageAccountObj,
4021
4040
  });
4022
4041
  }
4023
4042
  catch (error) {
@@ -4067,10 +4086,10 @@ async function fetchPerformanceMetrics({ params, client, accountId, alpacaAccoun
4067
4086
  calculateInformationRatio$1(portfolioHistory, benchmarkBars),
4068
4087
  calculateRiskAdjustedReturn$1(portfolioHistory),
4069
4088
  calculateLiquidityRatio({
4070
- alpacaAccount: alpacaAccountObj,
4089
+ brokerageAccount: brokerageAccountObj,
4071
4090
  }),
4072
4091
  calculateExpenseRatio$1({
4073
- alpacaAccount: alpacaAccountObj,
4092
+ brokerageAccount: brokerageAccountObj,
4074
4093
  }),
4075
4094
  getDividendYield(),
4076
4095
  calculateMaxDrawdown$1(portfolioHistory.equity),
@@ -4290,15 +4309,15 @@ const timeDiffString = (milliseconds) => {
4290
4309
  };
4291
4310
 
4292
4311
  // price-utils.ts
4293
- const calculateFees = async (action, trade, alpacaAccount) => {
4312
+ const calculateFees = async (action, trade, brokerageAccount) => {
4294
4313
  let fee = 0;
4295
4314
  const alpacaOrderId = action.alpacaOrderId;
4296
4315
  if (!alpacaOrderId)
4297
4316
  return fee;
4298
4317
  const order = await getOrder$1({
4299
- adapticAccountId: trade.alpacaAccountId,
4300
- alpacaApiKey: alpacaAccount.APIKey,
4301
- alpacaApiSecret: alpacaAccount.APISecret,
4318
+ adapticAccountId: trade.brokerageAccountId,
4319
+ alpacaApiKey: brokerageAccount.apiKey,
4320
+ alpacaApiSecret: brokerageAccount.apiSecret,
4302
4321
  }, alpacaOrderId);
4303
4322
  if (!order)
4304
4323
  return fee;
@@ -4336,13 +4355,13 @@ const calculateFees = async (action, trade, alpacaAccount) => {
4336
4355
  };
4337
4356
  const computeTotalFees = async (trade) => {
4338
4357
  let totalFees = 0;
4339
- // fetch alpaca account details using adaptic.alpacaAccount.get({id: trade.alpacaAccountId})
4340
- const alpacaAccount = (await adaptic$1.alpacaAccount.get({
4341
- id: trade.alpacaAccountId,
4358
+ // fetch alpaca account details using adaptic.brokerageAccount.get({id: trade.brokerageAccountId})
4359
+ const brokerageAccount = (await adaptic$1.brokerageAccount.get({
4360
+ id: trade.brokerageAccountId,
4342
4361
  }));
4343
- if (!alpacaAccount)
4362
+ if (!brokerageAccount)
4344
4363
  return totalFees;
4345
- const feePromises = trade?.actions?.map((action) => calculateFees(action, trade, alpacaAccount));
4364
+ const feePromises = trade?.actions?.map((action) => calculateFees(action, trade, brokerageAccount));
4346
4365
  const fees = await Promise.all(feePromises || []);
4347
4366
  totalFees = fees.reduce((acc, fee) => acc + fee, 0);
4348
4367
  return totalFees;
@@ -6089,7 +6108,7 @@ async function fetchBars(params) {
6089
6108
  */
6090
6109
  async function fetchNews(params, auth) {
6091
6110
  const { symbol, start = new Date(Date.now() - 24 * 60 * 60 * 1000), sort = "desc", includeContent = false, limit = 1000, } = params;
6092
- if (!auth.APIKey || !auth.APISecret) {
6111
+ if (!auth.alpacaApiKey || !auth.alpacaApiSecret) {
6093
6112
  throw new Error("Alpaca API key and secret are required");
6094
6113
  }
6095
6114
  if (!symbol) {
@@ -6157,7 +6176,7 @@ async function fetchNews(params, auth) {
6157
6176
  */
6158
6177
  async function fetchLatestTrades(params, auth) {
6159
6178
  const { symbols, loc = "us" } = params;
6160
- if (!auth.APIKey || !auth.APISecret) {
6179
+ if (!auth.alpacaApiKey || !auth.alpacaApiSecret) {
6161
6180
  throw new Error("Alpaca API key and secret are required");
6162
6181
  }
6163
6182
  if (!symbols || symbols.length === 0) {
@@ -6173,8 +6192,8 @@ async function fetchLatestTrades(params, auth) {
6173
6192
  return withRetry(async () => {
6174
6193
  const response = await fetch(url, {
6175
6194
  headers: {
6176
- "APCA-API-KEY-ID": auth.APIKey,
6177
- "APCA-API-SECRET-KEY": auth.APISecret,
6195
+ "APCA-API-KEY-ID": auth.alpacaApiKey,
6196
+ "APCA-API-SECRET-KEY": auth.alpacaApiSecret,
6178
6197
  },
6179
6198
  signal: createTimeoutSignal(DEFAULT_TIMEOUTS.ALPACA_API),
6180
6199
  });
@@ -6200,7 +6219,7 @@ async function fetchLatestTrades(params, auth) {
6200
6219
  */
6201
6220
  async function fetchLatestQuotes(params, auth) {
6202
6221
  const { symbols, loc = "us" } = params;
6203
- if (!auth.APIKey || !auth.APISecret) {
6222
+ if (!auth.alpacaApiKey || !auth.alpacaApiSecret) {
6204
6223
  throw new Error("Alpaca API key and secret are required");
6205
6224
  }
6206
6225
  if (!symbols || symbols.length === 0) {
@@ -6216,8 +6235,8 @@ async function fetchLatestQuotes(params, auth) {
6216
6235
  return withRetry(async () => {
6217
6236
  const response = await fetch(url, {
6218
6237
  headers: {
6219
- "APCA-API-KEY-ID": auth.APIKey,
6220
- "APCA-API-SECRET-KEY": auth.APISecret,
6238
+ "APCA-API-KEY-ID": auth.alpacaApiKey,
6239
+ "APCA-API-SECRET-KEY": auth.alpacaApiSecret,
6221
6240
  },
6222
6241
  signal: createTimeoutSignal(DEFAULT_TIMEOUTS.ALPACA_API),
6223
6242
  });
@@ -12263,6 +12282,8 @@ class AlpacaMarketDataAPI extends EventEmitter {
12263
12282
  dataURL;
12264
12283
  apiURL;
12265
12284
  v1beta1url;
12285
+ /** Whether API credentials are valid and available. False during build time when env vars are missing. */
12286
+ credentialsValid = false;
12266
12287
  stockStreamUrl = getStockStreamUrl("PRODUCTION"); // production values
12267
12288
  optionStreamUrl = getOptionsStreamUrl("PRODUCTION"); // production values
12268
12289
  cryptoStreamUrl = getCryptoStreamUrl("PRODUCTION"); // production values
@@ -12318,13 +12339,16 @@ class AlpacaMarketDataAPI extends EventEmitter {
12318
12339
  constructor() {
12319
12340
  super();
12320
12341
  // Validate credentials from environment variables before initializing
12321
- const apiKey = process.env.ALPACA_API_KEY;
12322
- const apiSecret = process.env.ALPACA_SECRET_KEY;
12323
- validateAlpacaCredentials({
12342
+ // Use throwOnMissing: false to allow initialization during build time
12343
+ // when env vars are not available. Features will be unavailable until
12344
+ // credentials are provided at runtime.
12345
+ const apiKey = process.env.ALPACA_API_KEY || "";
12346
+ const apiSecret = process.env.ALPACA_SECRET_KEY || "";
12347
+ this.credentialsValid = validateAlpacaCredentials({
12324
12348
  apiKey,
12325
12349
  apiSecret,
12326
12350
  isPaper: process.env.ALPACA_ACCOUNT_TYPE === "PAPER",
12327
- });
12351
+ }, { throwOnMissing: false });
12328
12352
  this.dataURL = MARKET_DATA_API.STOCKS;
12329
12353
  this.apiURL =
12330
12354
  process.env.ALPACA_ACCOUNT_TYPE === "PAPER"