@finatic/client 0.0.137 → 0.0.139

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
@@ -664,7 +664,7 @@ class ApiClient {
664
664
  return this.request('/brokers/data/orders', {
665
665
  method: 'GET',
666
666
  headers: {
667
- 'Authorization': `Bearer ${accessToken}`,
667
+ Authorization: `Bearer ${accessToken}`,
668
668
  },
669
669
  });
670
670
  }
@@ -745,8 +745,8 @@ class ApiClient {
745
745
  order: {
746
746
  order_id: orderId,
747
747
  account_number: accountNumber,
748
- ...extras
749
- }
748
+ ...extras,
749
+ },
750
750
  };
751
751
  }
752
752
  return this.request(`/brokers/orders/${orderId}`, {
@@ -1024,7 +1024,7 @@ class ApiClient {
1024
1024
  return this.request(`/auth/session/${sessionId}/user`, {
1025
1025
  method: 'GET',
1026
1026
  headers: {
1027
- 'Authorization': `Bearer ${accessToken}`,
1027
+ Authorization: `Bearer ${accessToken}`,
1028
1028
  },
1029
1029
  });
1030
1030
  }
@@ -1051,12 +1051,9 @@ class ApiClient {
1051
1051
  }
1052
1052
  // Broker Data Management
1053
1053
  async getBrokerList() {
1054
- const accessToken = await this.getValidAccessToken();
1054
+ // Public endpoint - no auth required
1055
1055
  return this.request('/brokers/', {
1056
1056
  method: 'GET',
1057
- headers: {
1058
- 'Authorization': `Bearer ${accessToken}`,
1059
- },
1060
1057
  });
1061
1058
  }
1062
1059
  async getBrokerAccounts(options) {
@@ -1074,7 +1071,7 @@ class ApiClient {
1074
1071
  return this.request('/brokers/data/accounts', {
1075
1072
  method: 'GET',
1076
1073
  headers: {
1077
- 'Authorization': `Bearer ${accessToken}`,
1074
+ Authorization: `Bearer ${accessToken}`,
1078
1075
  },
1079
1076
  params,
1080
1077
  });
@@ -1094,7 +1091,7 @@ class ApiClient {
1094
1091
  return this.request('/brokers/data/orders', {
1095
1092
  method: 'GET',
1096
1093
  headers: {
1097
- 'Authorization': `Bearer ${accessToken}`,
1094
+ Authorization: `Bearer ${accessToken}`,
1098
1095
  },
1099
1096
  params,
1100
1097
  });
@@ -1114,7 +1111,7 @@ class ApiClient {
1114
1111
  return this.request('/brokers/data/positions', {
1115
1112
  method: 'GET',
1116
1113
  headers: {
1117
- 'Authorization': `Bearer ${accessToken}`,
1114
+ Authorization: `Bearer ${accessToken}`,
1118
1115
  },
1119
1116
  params,
1120
1117
  });
@@ -1134,7 +1131,7 @@ class ApiClient {
1134
1131
  return this.request('/brokers/data/balances', {
1135
1132
  method: 'GET',
1136
1133
  headers: {
1137
- 'Authorization': `Bearer ${accessToken}`,
1134
+ Authorization: `Bearer ${accessToken}`,
1138
1135
  },
1139
1136
  params,
1140
1137
  });
@@ -1144,7 +1141,7 @@ class ApiClient {
1144
1141
  return this.request('/brokers/connections', {
1145
1142
  method: 'GET',
1146
1143
  headers: {
1147
- 'Authorization': `Bearer ${accessToken}`,
1144
+ Authorization: `Bearer ${accessToken}`,
1148
1145
  },
1149
1146
  });
1150
1147
  }
@@ -1163,7 +1160,7 @@ class ApiClient {
1163
1160
  return this.request(url, {
1164
1161
  method: 'GET',
1165
1162
  headers: {
1166
- 'Authorization': `Bearer ${accessToken}`,
1163
+ Authorization: `Bearer ${accessToken}`,
1167
1164
  },
1168
1165
  });
1169
1166
  }
@@ -1484,7 +1481,7 @@ class ApiClient {
1484
1481
  return this.request(`/brokers/disconnect/${connectionId}`, {
1485
1482
  method: 'DELETE',
1486
1483
  headers: {
1487
- 'Authorization': `Bearer ${accessToken}`,
1484
+ Authorization: `Bearer ${accessToken}`,
1488
1485
  },
1489
1486
  });
1490
1487
  }
@@ -1547,7 +1544,6 @@ class PortalUI {
1547
1544
  this.messageHandler = null;
1548
1545
  this.sessionId = null;
1549
1546
  this.portalOrigin = null;
1550
- this.userToken = null;
1551
1547
  this.originalBodyStyle = null;
1552
1548
  this.createContainer();
1553
1549
  }
@@ -1680,9 +1676,11 @@ class PortalUI {
1680
1676
  case 'portal-success': {
1681
1677
  // Handle both direct userId and data.userId formats
1682
1678
  const successUserId = userId || (data && data.userId);
1683
- const successAccessToken = access_token || (data && data.access_token);
1684
- const successRefreshToken = refresh_token || (data && data.refresh_token);
1685
- this.handlePortalSuccess(successUserId, successAccessToken, successRefreshToken);
1679
+ const tokens = {
1680
+ access_token: access_token || (data && data.access_token),
1681
+ refresh_token: refresh_token || (data && data.refresh_token)
1682
+ };
1683
+ this.handlePortalSuccess(successUserId, tokens);
1686
1684
  break;
1687
1685
  }
1688
1686
  case 'portal-error': {
@@ -1702,7 +1700,7 @@ class PortalUI {
1702
1700
  break;
1703
1701
  // Legacy support for old message types
1704
1702
  case 'success':
1705
- this.handleSuccess(userId, access_token, refresh_token);
1703
+ this.handleSuccess(userId);
1706
1704
  break;
1707
1705
  case 'error':
1708
1706
  this.handleError(error);
@@ -1714,30 +1712,17 @@ class PortalUI {
1714
1712
  console.warn('[PortalUI] Received unhandled message type:', type);
1715
1713
  }
1716
1714
  }
1717
- handlePortalSuccess(userId, accessToken, refreshToken) {
1715
+ handlePortalSuccess(userId, tokens) {
1718
1716
  if (!userId) {
1719
1717
  console.error('[PortalUI] Missing userId in portal-success message');
1720
1718
  return;
1721
1719
  }
1722
1720
  console.log('[PortalUI] Portal success - User connected:', userId);
1723
- // If tokens are provided, store them internally
1724
- if (accessToken && refreshToken) {
1725
- const userToken = {
1726
- accessToken: accessToken,
1727
- refreshToken: refreshToken,
1728
- expiresIn: 3600, // Default to 1 hour
1729
- user_id: userId,
1730
- tokenType: 'Bearer',
1731
- scope: 'api:access',
1732
- };
1733
- this.userToken = userToken;
1734
- console.log('[PortalUI] Portal authentication successful');
1735
- }
1736
- else {
1737
- console.warn('[PortalUI] No tokens received from portal');
1721
+ if (tokens?.access_token && tokens?.refresh_token) {
1722
+ console.log('[PortalUI] Tokens received for user:', userId);
1738
1723
  }
1739
1724
  // Pass userId to parent (SDK will handle tokens internally)
1740
- this.options?.onSuccess?.(userId);
1725
+ this.options?.onSuccess?.(userId, tokens);
1741
1726
  }
1742
1727
  handlePortalError(error) {
1743
1728
  console.error('[PortalUI] Portal error:', error);
@@ -1760,22 +1745,11 @@ class PortalUI {
1760
1745
  this.options.onEvent(data.type, data.data);
1761
1746
  }
1762
1747
  }
1763
- handleSuccess(userId, access_token, refresh_token) {
1764
- if (!userId || !access_token || !refresh_token) {
1748
+ handleSuccess(userId) {
1749
+ if (!userId) {
1765
1750
  console.error('[PortalUI] Missing required fields in success message');
1766
1751
  return;
1767
1752
  }
1768
- // Convert portal tokens to UserToken format
1769
- const userToken = {
1770
- accessToken: access_token,
1771
- refreshToken: refresh_token,
1772
- expiresIn: 3600, // Default to 1 hour
1773
- user_id: userId,
1774
- tokenType: 'Bearer',
1775
- scope: 'api:access',
1776
- };
1777
- // Store tokens internally
1778
- this.userToken = userToken;
1779
1753
  // Pass userId to parent
1780
1754
  this.options?.onSuccess?.(userId);
1781
1755
  }
@@ -1794,9 +1768,6 @@ class PortalUI {
1794
1768
  this.iframe.style.height = `${height}px`;
1795
1769
  }
1796
1770
  }
1797
- getTokens() {
1798
- return this.userToken;
1799
- }
1800
1771
  }
1801
1772
 
1802
1773
  /**
@@ -2829,7 +2800,7 @@ class MockApiClient {
2829
2800
  paramsBroker: params.broker,
2830
2801
  contextBroker: this.tradingContext.broker,
2831
2802
  paramsAccountNumber: params.accountNumber,
2832
- contextAccountNumber: this.tradingContext.accountNumber
2803
+ contextAccountNumber: this.tradingContext.accountNumber,
2833
2804
  });
2834
2805
  const fullParams = {
2835
2806
  broker: (params.broker || this.tradingContext.broker) ||
@@ -2892,7 +2863,7 @@ class MockApiClient {
2892
2863
  console.log('MockApiClient.setAccount Debug:', {
2893
2864
  accountNumber,
2894
2865
  accountId,
2895
- previousContext: { ...this.tradingContext }
2866
+ previousContext: { ...this.tradingContext },
2896
2867
  });
2897
2868
  this.tradingContext.accountNumber = accountNumber;
2898
2869
  this.tradingContext.accountId = accountId;
@@ -3037,7 +3008,7 @@ class MockApiClient {
3037
3008
  }
3038
3009
  // Broker Data Management
3039
3010
  async getBrokerList() {
3040
- await this.getValidAccessToken();
3011
+ // Public in mock mode as well - no auth required
3041
3012
  return this.mockDataProvider.mockGetBrokerList();
3042
3013
  }
3043
3014
  async getBrokerAccounts(options) {
@@ -4481,6 +4452,196 @@ const orangeTheme = {
4481
4452
  hoverEnd: 'rgba(249, 115, 22, 0.08)',
4482
4453
  },
4483
4454
  };
4455
+ // StockAlgos theme - Clean professional theme matching StockAlgos website
4456
+ const stockAlgosTheme = {
4457
+ mode: 'light', // Light mode like StockAlgos website
4458
+ colors: {
4459
+ background: {
4460
+ primary: '#FFFFFF', // Clean white background
4461
+ secondary: '#FFFFFF', // Also white for consistency
4462
+ tertiary: '#F8FAFC', // Very light gray for subtle elevation
4463
+ accent: 'rgba(79, 70, 229, 0.05)', // Very subtle blue accent
4464
+ glass: '#FFFFFF', // Pure white, no transparency
4465
+ },
4466
+ status: {
4467
+ connected: '#10B981', // Green for positive/connected
4468
+ disconnected: '#EF4444', // Red for negative/disconnected
4469
+ warning: '#F59E0B', // Amber for warnings
4470
+ pending: '#6366F1', // Indigo for pending states
4471
+ error: '#EF4444', // Red for errors
4472
+ success: '#10B981', // Green for success
4473
+ },
4474
+ text: {
4475
+ primary: '#111827', // Very dark text for maximum contrast
4476
+ secondary: '#374151', // Dark gray for secondary text
4477
+ muted: '#6B7280', // Medium gray for muted text
4478
+ inverse: '#FFFFFF', // White for text on dark backgrounds
4479
+ },
4480
+ border: {
4481
+ primary: '#E5E7EB', // Light gray border
4482
+ secondary: '#F3F4F6', // Very light gray border
4483
+ hover: '#D1D5DB', // Slightly darker on hover
4484
+ focus: '#4F46E5', // Blue focus border
4485
+ accent: '#4F46E5', // Blue accent border
4486
+ },
4487
+ input: {
4488
+ background: '#FFFFFF', // White input background
4489
+ border: '#D1D5DB', // Slightly more visible light gray border
4490
+ borderFocus: '#4F46E5', // Blue focus border
4491
+ text: '#111827', // Darker text for better contrast
4492
+ placeholder: '#6B7280', // Darker placeholder for visibility
4493
+ },
4494
+ button: {
4495
+ primary: {
4496
+ background: '#4F46E5', // Blue primary button
4497
+ text: '#FFFFFF', // White text
4498
+ hover: '#4338CA', // Darker blue on hover
4499
+ active: '#3730A3', // Even darker on active
4500
+ },
4501
+ secondary: {
4502
+ background: '#FFFFFF', // White background
4503
+ text: '#4F46E5', // Blue text
4504
+ border: '#E5E7EB', // Light gray border
4505
+ hover: '#F8FAFC', // Very light gray on hover
4506
+ active: '#F1F5F9', // Light gray on active
4507
+ },
4508
+ },
4509
+ },
4510
+ typography: {
4511
+ fontFamily: {
4512
+ primary: 'Inter, system-ui, -apple-system, sans-serif', // Clean, modern font like StockAlgos
4513
+ secondary: 'Inter, system-ui, -apple-system, sans-serif',
4514
+ },
4515
+ fontSize: {
4516
+ xs: '0.75rem', // 12px
4517
+ sm: '0.875rem', // 14px
4518
+ base: '1rem', // 16px
4519
+ lg: '1.125rem', // 18px
4520
+ xl: '1.25rem', // 20px
4521
+ '2xl': '1.5rem', // 24px
4522
+ '3xl': '1.875rem', // 30px
4523
+ '4xl': '2.25rem', // 36px
4524
+ },
4525
+ fontWeight: {
4526
+ normal: 400,
4527
+ medium: 500,
4528
+ semibold: 600,
4529
+ bold: 700,
4530
+ extrabold: 800,
4531
+ },
4532
+ lineHeight: {
4533
+ tight: '1.25',
4534
+ normal: '1.5',
4535
+ relaxed: '1.75',
4536
+ },
4537
+ },
4538
+ spacing: {
4539
+ xs: '0.25rem', // 4px
4540
+ sm: '0.5rem', // 8px
4541
+ md: '1rem', // 16px
4542
+ lg: '1.5rem', // 24px
4543
+ xl: '2rem', // 32px
4544
+ '2xl': '3rem', // 48px
4545
+ '3xl': '4rem', // 64px
4546
+ },
4547
+ layout: {
4548
+ containerMaxWidth: '1440px',
4549
+ gridGap: '1rem',
4550
+ cardPadding: '1.5rem',
4551
+ borderRadius: {
4552
+ sm: '0.25rem', // 4px
4553
+ md: '0.5rem', // 8px
4554
+ lg: '0.75rem', // 12px
4555
+ xl: '1rem', // 16px
4556
+ '2xl': '1.5rem', // 24px
4557
+ full: '9999px',
4558
+ },
4559
+ },
4560
+ components: {
4561
+ brokerCard: {
4562
+ width: '100%',
4563
+ height: '180px',
4564
+ logoSize: '64px',
4565
+ padding: '1.5rem',
4566
+ },
4567
+ statusIndicator: {
4568
+ size: '22px',
4569
+ glowIntensity: 0.1, // Minimal glow for clean look
4570
+ },
4571
+ modal: {
4572
+ background: '#FFFFFF', // Pure white modal background
4573
+ backdrop: 'rgba(0, 0, 0, 0.4)', // Lighter backdrop
4574
+ },
4575
+ brokerCardModern: {
4576
+ width: '150px',
4577
+ height: '150px',
4578
+ padding: '16px',
4579
+ logoSize: '48px',
4580
+ statusSize: '22px',
4581
+ },
4582
+ connectButton: {
4583
+ width: '120px',
4584
+ height: '120px',
4585
+ },
4586
+ themeSwitcher: {
4587
+ indicatorSize: '24px',
4588
+ },
4589
+ },
4590
+ effects: {
4591
+ glassmorphism: {
4592
+ enabled: false, // Disable glass effects for clean look
4593
+ blur: '0px',
4594
+ opacity: 0,
4595
+ border: 'rgba(0, 0, 0, 0.1)',
4596
+ },
4597
+ animations: {
4598
+ enabled: true,
4599
+ duration: {
4600
+ fast: '150ms',
4601
+ normal: '200ms', // Faster, more subtle animations
4602
+ slow: '300ms',
4603
+ },
4604
+ easing: {
4605
+ default: 'cubic-bezier(0.4, 0, 0.2, 1)',
4606
+ smooth: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
4607
+ bounce: 'cubic-bezier(0.68, -0.55, 0.265, 1.55)',
4608
+ },
4609
+ },
4610
+ shadows: {
4611
+ sm: '0 1px 2px rgba(0, 0, 0, 0.05)', // Very subtle shadows
4612
+ md: '0 4px 6px rgba(0, 0, 0, 0.07)',
4613
+ lg: '0 10px 15px rgba(0, 0, 0, 0.1)',
4614
+ xl: '0 20px 25px rgba(0, 0, 0, 0.1)',
4615
+ card: '0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06)', // Clean card shadow
4616
+ cardHover: '0 4px 6px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.06)', // Subtle hover shadow
4617
+ glow: '0 0 0px transparent', // No glow effects
4618
+ focus: '0 0 0 3px rgba(79, 70, 229, 0.1)', // Subtle focus ring
4619
+ },
4620
+ },
4621
+ branding: {
4622
+ logo: '/stockalgos-logo.png', // Custom logo path
4623
+ companyName: 'StockAlgos', // Company name
4624
+ favicon: '/stockalgos-favicon.ico', // Custom favicon
4625
+ primaryColor: '#4F46E5', // Indigo brand color
4626
+ },
4627
+ // Minimal glow effects
4628
+ glow: {
4629
+ primary: 'transparent',
4630
+ secondary: 'transparent',
4631
+ card: 'transparent',
4632
+ cardHover: 'rgba(79, 70, 229, 0.05)', // Very subtle
4633
+ button: 'transparent',
4634
+ focus: 'rgba(79, 70, 229, 0.1)',
4635
+ scrollbar: 'transparent',
4636
+ },
4637
+ // Minimal gradients
4638
+ gradients: {
4639
+ start: 'rgba(79, 70, 229, 0.02)',
4640
+ end: 'rgba(79, 70, 229, 0.01)',
4641
+ hoverStart: 'rgba(79, 70, 229, 0.05)',
4642
+ hoverEnd: 'rgba(79, 70, 229, 0.02)',
4643
+ },
4644
+ };
4484
4645
  // Theme preset mapping
4485
4646
  const portalThemePresets = {
4486
4647
  dark: darkTheme,
@@ -4489,6 +4650,7 @@ const portalThemePresets = {
4489
4650
  purple: purpleTheme,
4490
4651
  green: greenTheme,
4491
4652
  orange: orangeTheme,
4653
+ stockAlgos: stockAlgosTheme,
4492
4654
  };
4493
4655
 
4494
4656
  /**
@@ -4940,7 +5102,7 @@ class FinaticConnect extends EventEmitter {
4940
5102
  expires_in: this.userToken.expiresIn,
4941
5103
  token_type: this.userToken.tokenType,
4942
5104
  scope: this.userToken.scope,
4943
- company_id: this.companyId
5105
+ company_id: this.companyId,
4944
5106
  };
4945
5107
  }
4946
5108
  async initializeWithUser(userId) {
@@ -5016,21 +5178,15 @@ class FinaticConnect extends EventEmitter {
5016
5178
  }
5017
5179
  // Show portal
5018
5180
  this.portalUI.show(themedPortalUrl, this.sessionId || '', {
5019
- onSuccess: async (userId) => {
5181
+ onSuccess: async (userId, tokens) => {
5020
5182
  try {
5021
5183
  if (!this.sessionId) {
5022
5184
  throw new SessionError('Session not initialized');
5023
5185
  }
5024
- // Get tokens from portal UI
5025
- const userToken = this.portalUI.getTokens();
5026
- if (!userToken) {
5027
- throw new Error('No tokens received from portal');
5186
+ // Handle tokens if provided
5187
+ if (tokens?.access_token && tokens?.refresh_token) {
5188
+ this.handleTokens(tokens);
5028
5189
  }
5029
- // Set the tokens internally
5030
- this.userToken = userToken;
5031
- // Set tokens in ApiClient for automatic token management
5032
- const expiresAt = new Date(Date.now() + 3600 * 1000).toISOString(); // 1 hour from now
5033
- this.apiClient.setTokens(userToken.accessToken, userToken.refreshToken, expiresAt, userId);
5034
5190
  // Emit portal success event
5035
5191
  this.emit('portal:success', userId);
5036
5192
  // Emit legacy success event
@@ -5211,7 +5367,7 @@ class FinaticConnect extends EventEmitter {
5211
5367
  * Set the broker context for trading
5212
5368
  * @param broker - The broker to use for trading
5213
5369
  */
5214
- setBroker(broker) {
5370
+ setTradingContextBroker(broker) {
5215
5371
  this.apiClient.setBroker(broker);
5216
5372
  }
5217
5373
  /**
@@ -5219,7 +5375,7 @@ class FinaticConnect extends EventEmitter {
5219
5375
  * @param accountNumber - The account number to use for trading
5220
5376
  * @param accountId - Optional account ID
5221
5377
  */
5222
- setAccount(accountNumber, accountId) {
5378
+ setTradingContextAccount(accountNumber, accountId) {
5223
5379
  this.apiClient.setAccount(accountNumber, accountId);
5224
5380
  }
5225
5381
  /**
@@ -5369,33 +5525,6 @@ class FinaticConnect extends EventEmitter {
5369
5525
  throw error;
5370
5526
  }
5371
5527
  }
5372
- /**
5373
- * Set the broker context for trading operations
5374
- * @param broker - The broker to set as context
5375
- */
5376
- setBroker(broker) {
5377
- this.apiClient.setBroker(broker);
5378
- }
5379
- /**
5380
- * Set the account context for trading operations
5381
- * @param accountNumber - The account number to set as context
5382
- */
5383
- setAccount(accountNumber) {
5384
- this.apiClient.setAccount(accountNumber);
5385
- }
5386
- /**
5387
- * Get the current trading context
5388
- * @returns Object with current broker and account context
5389
- */
5390
- getTradingContext() {
5391
- return this.apiClient.getTradingContext();
5392
- }
5393
- /**
5394
- * Clear the trading context
5395
- */
5396
- clearTradingContext() {
5397
- this.apiClient.clearTradingContext();
5398
- }
5399
5528
  /**
5400
5529
  * Get the current user ID
5401
5530
  * @returns The current user ID or undefined if not authenticated
@@ -5415,9 +5544,9 @@ class FinaticConnect extends EventEmitter {
5415
5544
  * @returns Promise with array of broker information
5416
5545
  */
5417
5546
  async getBrokerList() {
5418
- if (!this.isAuthed()) {
5419
- throw new AuthenticationError('Not authenticated');
5420
- }
5547
+ // if (!this.isAuthed()) {
5548
+ // throw new AuthenticationError('Not authenticated');
5549
+ // }
5421
5550
  const response = await this.apiClient.getBrokerList();
5422
5551
  const baseUrl = this.baseUrl.replace('/api/v1', ''); // Remove /api/v1 to get the base URL
5423
5552
  // Transform the broker list to include full logo URLs