@finatic/client 0.0.137 → 0.0.138

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.d.ts CHANGED
@@ -1383,6 +1383,25 @@ declare class FinaticConnect extends EventEmitter {
1383
1383
  side?: 'Buy' | 'Sell';
1384
1384
  order_id?: string;
1385
1385
  }>, broker?: 'robinhood' | 'tasty_trade' | 'ninja_trader', connection_id?: string): Promise<OrderResponse>;
1386
+ /**
1387
+ * Set the broker context for trading
1388
+ * @param broker - The broker to use for trading
1389
+ */
1390
+ setTradingContextBroker(broker: 'robinhood' | 'tasty_trade' | 'ninja_trader' | 'interactive_brokers' | 'tradestation'): void;
1391
+ /**
1392
+ * Set the account context for trading
1393
+ * @param accountNumber - The account number to use for trading
1394
+ * @param accountId - Optional account ID
1395
+ */
1396
+ setTradingContextAccount(accountNumber: string, accountId?: string): void;
1397
+ /**
1398
+ * Get the current trading context
1399
+ */
1400
+ getTradingContext(): TradingContext;
1401
+ /**
1402
+ * Clear the trading context
1403
+ */
1404
+ clearTradingContext(): void;
1386
1405
  /**
1387
1406
  * Place a stock market order (convenience method)
1388
1407
  */
package/dist/index.js CHANGED
@@ -666,7 +666,7 @@ class ApiClient {
666
666
  return this.request('/brokers/data/orders', {
667
667
  method: 'GET',
668
668
  headers: {
669
- 'Authorization': `Bearer ${accessToken}`,
669
+ Authorization: `Bearer ${accessToken}`,
670
670
  },
671
671
  });
672
672
  }
@@ -747,8 +747,8 @@ class ApiClient {
747
747
  order: {
748
748
  order_id: orderId,
749
749
  account_number: accountNumber,
750
- ...extras
751
- }
750
+ ...extras,
751
+ },
752
752
  };
753
753
  }
754
754
  return this.request(`/brokers/orders/${orderId}`, {
@@ -1026,7 +1026,7 @@ class ApiClient {
1026
1026
  return this.request(`/auth/session/${sessionId}/user`, {
1027
1027
  method: 'GET',
1028
1028
  headers: {
1029
- 'Authorization': `Bearer ${accessToken}`,
1029
+ Authorization: `Bearer ${accessToken}`,
1030
1030
  },
1031
1031
  });
1032
1032
  }
@@ -1053,12 +1053,9 @@ class ApiClient {
1053
1053
  }
1054
1054
  // Broker Data Management
1055
1055
  async getBrokerList() {
1056
- const accessToken = await this.getValidAccessToken();
1056
+ // Public endpoint - no auth required
1057
1057
  return this.request('/brokers/', {
1058
1058
  method: 'GET',
1059
- headers: {
1060
- 'Authorization': `Bearer ${accessToken}`,
1061
- },
1062
1059
  });
1063
1060
  }
1064
1061
  async getBrokerAccounts(options) {
@@ -1076,7 +1073,7 @@ class ApiClient {
1076
1073
  return this.request('/brokers/data/accounts', {
1077
1074
  method: 'GET',
1078
1075
  headers: {
1079
- 'Authorization': `Bearer ${accessToken}`,
1076
+ Authorization: `Bearer ${accessToken}`,
1080
1077
  },
1081
1078
  params,
1082
1079
  });
@@ -1096,7 +1093,7 @@ class ApiClient {
1096
1093
  return this.request('/brokers/data/orders', {
1097
1094
  method: 'GET',
1098
1095
  headers: {
1099
- 'Authorization': `Bearer ${accessToken}`,
1096
+ Authorization: `Bearer ${accessToken}`,
1100
1097
  },
1101
1098
  params,
1102
1099
  });
@@ -1116,7 +1113,7 @@ class ApiClient {
1116
1113
  return this.request('/brokers/data/positions', {
1117
1114
  method: 'GET',
1118
1115
  headers: {
1119
- 'Authorization': `Bearer ${accessToken}`,
1116
+ Authorization: `Bearer ${accessToken}`,
1120
1117
  },
1121
1118
  params,
1122
1119
  });
@@ -1136,7 +1133,7 @@ class ApiClient {
1136
1133
  return this.request('/brokers/data/balances', {
1137
1134
  method: 'GET',
1138
1135
  headers: {
1139
- 'Authorization': `Bearer ${accessToken}`,
1136
+ Authorization: `Bearer ${accessToken}`,
1140
1137
  },
1141
1138
  params,
1142
1139
  });
@@ -1146,7 +1143,7 @@ class ApiClient {
1146
1143
  return this.request('/brokers/connections', {
1147
1144
  method: 'GET',
1148
1145
  headers: {
1149
- 'Authorization': `Bearer ${accessToken}`,
1146
+ Authorization: `Bearer ${accessToken}`,
1150
1147
  },
1151
1148
  });
1152
1149
  }
@@ -1165,7 +1162,7 @@ class ApiClient {
1165
1162
  return this.request(url, {
1166
1163
  method: 'GET',
1167
1164
  headers: {
1168
- 'Authorization': `Bearer ${accessToken}`,
1165
+ Authorization: `Bearer ${accessToken}`,
1169
1166
  },
1170
1167
  });
1171
1168
  }
@@ -1486,7 +1483,7 @@ class ApiClient {
1486
1483
  return this.request(`/brokers/disconnect/${connectionId}`, {
1487
1484
  method: 'DELETE',
1488
1485
  headers: {
1489
- 'Authorization': `Bearer ${accessToken}`,
1486
+ Authorization: `Bearer ${accessToken}`,
1490
1487
  },
1491
1488
  });
1492
1489
  }
@@ -1549,7 +1546,6 @@ class PortalUI {
1549
1546
  this.messageHandler = null;
1550
1547
  this.sessionId = null;
1551
1548
  this.portalOrigin = null;
1552
- this.userToken = null;
1553
1549
  this.originalBodyStyle = null;
1554
1550
  this.createContainer();
1555
1551
  }
@@ -1676,15 +1672,13 @@ class PortalUI {
1676
1672
  console.warn('[PortalUI] Received message from unauthorized origin:', event.origin, 'Expected:', this.portalOrigin);
1677
1673
  return;
1678
1674
  }
1679
- const { type, userId, access_token, refresh_token, error, height, data } = event.data;
1675
+ const { type, userId, error, height, data } = event.data;
1680
1676
  console.log('[PortalUI] Received message:', event.data);
1681
1677
  switch (type) {
1682
1678
  case 'portal-success': {
1683
1679
  // Handle both direct userId and data.userId formats
1684
1680
  const successUserId = userId || (data && data.userId);
1685
- const successAccessToken = access_token || (data && data.access_token);
1686
- const successRefreshToken = refresh_token || (data && data.refresh_token);
1687
- this.handlePortalSuccess(successUserId, successAccessToken, successRefreshToken);
1681
+ this.handlePortalSuccess(successUserId);
1688
1682
  break;
1689
1683
  }
1690
1684
  case 'portal-error': {
@@ -1704,7 +1698,7 @@ class PortalUI {
1704
1698
  break;
1705
1699
  // Legacy support for old message types
1706
1700
  case 'success':
1707
- this.handleSuccess(userId, access_token, refresh_token);
1701
+ this.handleSuccess(userId);
1708
1702
  break;
1709
1703
  case 'error':
1710
1704
  this.handleError(error);
@@ -1716,28 +1710,12 @@ class PortalUI {
1716
1710
  console.warn('[PortalUI] Received unhandled message type:', type);
1717
1711
  }
1718
1712
  }
1719
- handlePortalSuccess(userId, accessToken, refreshToken) {
1713
+ handlePortalSuccess(userId) {
1720
1714
  if (!userId) {
1721
1715
  console.error('[PortalUI] Missing userId in portal-success message');
1722
1716
  return;
1723
1717
  }
1724
1718
  console.log('[PortalUI] Portal success - User connected:', userId);
1725
- // If tokens are provided, store them internally
1726
- if (accessToken && refreshToken) {
1727
- const userToken = {
1728
- accessToken: accessToken,
1729
- refreshToken: refreshToken,
1730
- expiresIn: 3600, // Default to 1 hour
1731
- user_id: userId,
1732
- tokenType: 'Bearer',
1733
- scope: 'api:access',
1734
- };
1735
- this.userToken = userToken;
1736
- console.log('[PortalUI] Portal authentication successful');
1737
- }
1738
- else {
1739
- console.warn('[PortalUI] No tokens received from portal');
1740
- }
1741
1719
  // Pass userId to parent (SDK will handle tokens internally)
1742
1720
  this.options?.onSuccess?.(userId);
1743
1721
  }
@@ -1762,22 +1740,11 @@ class PortalUI {
1762
1740
  this.options.onEvent(data.type, data.data);
1763
1741
  }
1764
1742
  }
1765
- handleSuccess(userId, access_token, refresh_token) {
1766
- if (!userId || !access_token || !refresh_token) {
1743
+ handleSuccess(userId) {
1744
+ if (!userId) {
1767
1745
  console.error('[PortalUI] Missing required fields in success message');
1768
1746
  return;
1769
1747
  }
1770
- // Convert portal tokens to UserToken format
1771
- const userToken = {
1772
- accessToken: access_token,
1773
- refreshToken: refresh_token,
1774
- expiresIn: 3600, // Default to 1 hour
1775
- user_id: userId,
1776
- tokenType: 'Bearer',
1777
- scope: 'api:access',
1778
- };
1779
- // Store tokens internally
1780
- this.userToken = userToken;
1781
1748
  // Pass userId to parent
1782
1749
  this.options?.onSuccess?.(userId);
1783
1750
  }
@@ -1796,9 +1763,6 @@ class PortalUI {
1796
1763
  this.iframe.style.height = `${height}px`;
1797
1764
  }
1798
1765
  }
1799
- getTokens() {
1800
- return this.userToken;
1801
- }
1802
1766
  }
1803
1767
 
1804
1768
  /**
@@ -2831,7 +2795,7 @@ class MockApiClient {
2831
2795
  paramsBroker: params.broker,
2832
2796
  contextBroker: this.tradingContext.broker,
2833
2797
  paramsAccountNumber: params.accountNumber,
2834
- contextAccountNumber: this.tradingContext.accountNumber
2798
+ contextAccountNumber: this.tradingContext.accountNumber,
2835
2799
  });
2836
2800
  const fullParams = {
2837
2801
  broker: (params.broker || this.tradingContext.broker) ||
@@ -2894,7 +2858,7 @@ class MockApiClient {
2894
2858
  console.log('MockApiClient.setAccount Debug:', {
2895
2859
  accountNumber,
2896
2860
  accountId,
2897
- previousContext: { ...this.tradingContext }
2861
+ previousContext: { ...this.tradingContext },
2898
2862
  });
2899
2863
  this.tradingContext.accountNumber = accountNumber;
2900
2864
  this.tradingContext.accountId = accountId;
@@ -3039,7 +3003,7 @@ class MockApiClient {
3039
3003
  }
3040
3004
  // Broker Data Management
3041
3005
  async getBrokerList() {
3042
- await this.getValidAccessToken();
3006
+ // Public in mock mode as well - no auth required
3043
3007
  return this.mockDataProvider.mockGetBrokerList();
3044
3008
  }
3045
3009
  async getBrokerAccounts(options) {
@@ -4483,6 +4447,196 @@ const orangeTheme = {
4483
4447
  hoverEnd: 'rgba(249, 115, 22, 0.08)',
4484
4448
  },
4485
4449
  };
4450
+ // StockAlgos theme - Clean professional theme matching StockAlgos website
4451
+ const stockAlgosTheme = {
4452
+ mode: 'light', // Light mode like StockAlgos website
4453
+ colors: {
4454
+ background: {
4455
+ primary: '#FFFFFF', // Clean white background
4456
+ secondary: '#FFFFFF', // Also white for consistency
4457
+ tertiary: '#F8FAFC', // Very light gray for subtle elevation
4458
+ accent: 'rgba(79, 70, 229, 0.05)', // Very subtle blue accent
4459
+ glass: '#FFFFFF', // Pure white, no transparency
4460
+ },
4461
+ status: {
4462
+ connected: '#10B981', // Green for positive/connected
4463
+ disconnected: '#EF4444', // Red for negative/disconnected
4464
+ warning: '#F59E0B', // Amber for warnings
4465
+ pending: '#6366F1', // Indigo for pending states
4466
+ error: '#EF4444', // Red for errors
4467
+ success: '#10B981', // Green for success
4468
+ },
4469
+ text: {
4470
+ primary: '#111827', // Very dark text for maximum contrast
4471
+ secondary: '#374151', // Dark gray for secondary text
4472
+ muted: '#6B7280', // Medium gray for muted text
4473
+ inverse: '#FFFFFF', // White for text on dark backgrounds
4474
+ },
4475
+ border: {
4476
+ primary: '#E5E7EB', // Light gray border
4477
+ secondary: '#F3F4F6', // Very light gray border
4478
+ hover: '#D1D5DB', // Slightly darker on hover
4479
+ focus: '#4F46E5', // Blue focus border
4480
+ accent: '#4F46E5', // Blue accent border
4481
+ },
4482
+ input: {
4483
+ background: '#FFFFFF', // White input background
4484
+ border: '#D1D5DB', // Slightly more visible light gray border
4485
+ borderFocus: '#4F46E5', // Blue focus border
4486
+ text: '#111827', // Darker text for better contrast
4487
+ placeholder: '#6B7280', // Darker placeholder for visibility
4488
+ },
4489
+ button: {
4490
+ primary: {
4491
+ background: '#4F46E5', // Blue primary button
4492
+ text: '#FFFFFF', // White text
4493
+ hover: '#4338CA', // Darker blue on hover
4494
+ active: '#3730A3', // Even darker on active
4495
+ },
4496
+ secondary: {
4497
+ background: '#FFFFFF', // White background
4498
+ text: '#4F46E5', // Blue text
4499
+ border: '#E5E7EB', // Light gray border
4500
+ hover: '#F8FAFC', // Very light gray on hover
4501
+ active: '#F1F5F9', // Light gray on active
4502
+ },
4503
+ },
4504
+ },
4505
+ typography: {
4506
+ fontFamily: {
4507
+ primary: 'Inter, system-ui, -apple-system, sans-serif', // Clean, modern font like StockAlgos
4508
+ secondary: 'Inter, system-ui, -apple-system, sans-serif',
4509
+ },
4510
+ fontSize: {
4511
+ xs: '0.75rem', // 12px
4512
+ sm: '0.875rem', // 14px
4513
+ base: '1rem', // 16px
4514
+ lg: '1.125rem', // 18px
4515
+ xl: '1.25rem', // 20px
4516
+ '2xl': '1.5rem', // 24px
4517
+ '3xl': '1.875rem', // 30px
4518
+ '4xl': '2.25rem', // 36px
4519
+ },
4520
+ fontWeight: {
4521
+ normal: 400,
4522
+ medium: 500,
4523
+ semibold: 600,
4524
+ bold: 700,
4525
+ extrabold: 800,
4526
+ },
4527
+ lineHeight: {
4528
+ tight: '1.25',
4529
+ normal: '1.5',
4530
+ relaxed: '1.75',
4531
+ },
4532
+ },
4533
+ spacing: {
4534
+ xs: '0.25rem', // 4px
4535
+ sm: '0.5rem', // 8px
4536
+ md: '1rem', // 16px
4537
+ lg: '1.5rem', // 24px
4538
+ xl: '2rem', // 32px
4539
+ '2xl': '3rem', // 48px
4540
+ '3xl': '4rem', // 64px
4541
+ },
4542
+ layout: {
4543
+ containerMaxWidth: '1440px',
4544
+ gridGap: '1rem',
4545
+ cardPadding: '1.5rem',
4546
+ borderRadius: {
4547
+ sm: '0.25rem', // 4px
4548
+ md: '0.5rem', // 8px
4549
+ lg: '0.75rem', // 12px
4550
+ xl: '1rem', // 16px
4551
+ '2xl': '1.5rem', // 24px
4552
+ full: '9999px',
4553
+ },
4554
+ },
4555
+ components: {
4556
+ brokerCard: {
4557
+ width: '100%',
4558
+ height: '180px',
4559
+ logoSize: '64px',
4560
+ padding: '1.5rem',
4561
+ },
4562
+ statusIndicator: {
4563
+ size: '22px',
4564
+ glowIntensity: 0.1, // Minimal glow for clean look
4565
+ },
4566
+ modal: {
4567
+ background: '#FFFFFF', // Pure white modal background
4568
+ backdrop: 'rgba(0, 0, 0, 0.4)', // Lighter backdrop
4569
+ },
4570
+ brokerCardModern: {
4571
+ width: '150px',
4572
+ height: '150px',
4573
+ padding: '16px',
4574
+ logoSize: '48px',
4575
+ statusSize: '22px',
4576
+ },
4577
+ connectButton: {
4578
+ width: '120px',
4579
+ height: '120px',
4580
+ },
4581
+ themeSwitcher: {
4582
+ indicatorSize: '24px',
4583
+ },
4584
+ },
4585
+ effects: {
4586
+ glassmorphism: {
4587
+ enabled: false, // Disable glass effects for clean look
4588
+ blur: '0px',
4589
+ opacity: 0,
4590
+ border: 'rgba(0, 0, 0, 0.1)',
4591
+ },
4592
+ animations: {
4593
+ enabled: true,
4594
+ duration: {
4595
+ fast: '150ms',
4596
+ normal: '200ms', // Faster, more subtle animations
4597
+ slow: '300ms',
4598
+ },
4599
+ easing: {
4600
+ default: 'cubic-bezier(0.4, 0, 0.2, 1)',
4601
+ smooth: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
4602
+ bounce: 'cubic-bezier(0.68, -0.55, 0.265, 1.55)',
4603
+ },
4604
+ },
4605
+ shadows: {
4606
+ sm: '0 1px 2px rgba(0, 0, 0, 0.05)', // Very subtle shadows
4607
+ md: '0 4px 6px rgba(0, 0, 0, 0.07)',
4608
+ lg: '0 10px 15px rgba(0, 0, 0, 0.1)',
4609
+ xl: '0 20px 25px rgba(0, 0, 0, 0.1)',
4610
+ card: '0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06)', // Clean card shadow
4611
+ cardHover: '0 4px 6px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.06)', // Subtle hover shadow
4612
+ glow: '0 0 0px transparent', // No glow effects
4613
+ focus: '0 0 0 3px rgba(79, 70, 229, 0.1)', // Subtle focus ring
4614
+ },
4615
+ },
4616
+ branding: {
4617
+ logo: '/stockalgos-logo.png', // Custom logo path
4618
+ companyName: 'StockAlgos', // Company name
4619
+ favicon: '/stockalgos-favicon.ico', // Custom favicon
4620
+ primaryColor: '#4F46E5', // Indigo brand color
4621
+ },
4622
+ // Minimal glow effects
4623
+ glow: {
4624
+ primary: 'transparent',
4625
+ secondary: 'transparent',
4626
+ card: 'transparent',
4627
+ cardHover: 'rgba(79, 70, 229, 0.05)', // Very subtle
4628
+ button: 'transparent',
4629
+ focus: 'rgba(79, 70, 229, 0.1)',
4630
+ scrollbar: 'transparent',
4631
+ },
4632
+ // Minimal gradients
4633
+ gradients: {
4634
+ start: 'rgba(79, 70, 229, 0.02)',
4635
+ end: 'rgba(79, 70, 229, 0.01)',
4636
+ hoverStart: 'rgba(79, 70, 229, 0.05)',
4637
+ hoverEnd: 'rgba(79, 70, 229, 0.02)',
4638
+ },
4639
+ };
4486
4640
  // Theme preset mapping
4487
4641
  const portalThemePresets = {
4488
4642
  dark: darkTheme,
@@ -4491,6 +4645,7 @@ const portalThemePresets = {
4491
4645
  purple: purpleTheme,
4492
4646
  green: greenTheme,
4493
4647
  orange: orangeTheme,
4648
+ stockAlgos: stockAlgosTheme,
4494
4649
  };
4495
4650
 
4496
4651
  /**
@@ -4942,7 +5097,7 @@ class FinaticConnect extends EventEmitter {
4942
5097
  expires_in: this.userToken.expiresIn,
4943
5098
  token_type: this.userToken.tokenType,
4944
5099
  scope: this.userToken.scope,
4945
- company_id: this.companyId
5100
+ company_id: this.companyId,
4946
5101
  };
4947
5102
  }
4948
5103
  async initializeWithUser(userId) {
@@ -5023,16 +5178,6 @@ class FinaticConnect extends EventEmitter {
5023
5178
  if (!this.sessionId) {
5024
5179
  throw new SessionError('Session not initialized');
5025
5180
  }
5026
- // Get tokens from portal UI
5027
- const userToken = this.portalUI.getTokens();
5028
- if (!userToken) {
5029
- throw new Error('No tokens received from portal');
5030
- }
5031
- // Set the tokens internally
5032
- this.userToken = userToken;
5033
- // Set tokens in ApiClient for automatic token management
5034
- const expiresAt = new Date(Date.now() + 3600 * 1000).toISOString(); // 1 hour from now
5035
- this.apiClient.setTokens(userToken.accessToken, userToken.refreshToken, expiresAt, userId);
5036
5181
  // Emit portal success event
5037
5182
  this.emit('portal:success', userId);
5038
5183
  // Emit legacy success event
@@ -5213,7 +5358,7 @@ class FinaticConnect extends EventEmitter {
5213
5358
  * Set the broker context for trading
5214
5359
  * @param broker - The broker to use for trading
5215
5360
  */
5216
- setBroker(broker) {
5361
+ setTradingContextBroker(broker) {
5217
5362
  this.apiClient.setBroker(broker);
5218
5363
  }
5219
5364
  /**
@@ -5221,7 +5366,7 @@ class FinaticConnect extends EventEmitter {
5221
5366
  * @param accountNumber - The account number to use for trading
5222
5367
  * @param accountId - Optional account ID
5223
5368
  */
5224
- setAccount(accountNumber, accountId) {
5369
+ setTradingContextAccount(accountNumber, accountId) {
5225
5370
  this.apiClient.setAccount(accountNumber, accountId);
5226
5371
  }
5227
5372
  /**
@@ -5371,33 +5516,6 @@ class FinaticConnect extends EventEmitter {
5371
5516
  throw error;
5372
5517
  }
5373
5518
  }
5374
- /**
5375
- * Set the broker context for trading operations
5376
- * @param broker - The broker to set as context
5377
- */
5378
- setBroker(broker) {
5379
- this.apiClient.setBroker(broker);
5380
- }
5381
- /**
5382
- * Set the account context for trading operations
5383
- * @param accountNumber - The account number to set as context
5384
- */
5385
- setAccount(accountNumber) {
5386
- this.apiClient.setAccount(accountNumber);
5387
- }
5388
- /**
5389
- * Get the current trading context
5390
- * @returns Object with current broker and account context
5391
- */
5392
- getTradingContext() {
5393
- return this.apiClient.getTradingContext();
5394
- }
5395
- /**
5396
- * Clear the trading context
5397
- */
5398
- clearTradingContext() {
5399
- this.apiClient.clearTradingContext();
5400
- }
5401
5519
  /**
5402
5520
  * Get the current user ID
5403
5521
  * @returns The current user ID or undefined if not authenticated
@@ -5417,9 +5535,9 @@ class FinaticConnect extends EventEmitter {
5417
5535
  * @returns Promise with array of broker information
5418
5536
  */
5419
5537
  async getBrokerList() {
5420
- if (!this.isAuthed()) {
5421
- throw new AuthenticationError('Not authenticated');
5422
- }
5538
+ // if (!this.isAuthed()) {
5539
+ // throw new AuthenticationError('Not authenticated');
5540
+ // }
5423
5541
  const response = await this.apiClient.getBrokerList();
5424
5542
  const baseUrl = this.baseUrl.replace('/api/v1', ''); // Remove /api/v1 to get the base URL
5425
5543
  // Transform the broker list to include full logo URLs