@one_deploy/sdk 1.0.7 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +339 -0
  2. package/dist/ForexPoolDataGenerator--__twRwl.d.mts +76 -0
  3. package/dist/ForexPoolDataGenerator-eUgwsU_B.d.ts +76 -0
  4. package/dist/OneForexTradeHistory-TlKxjbFF.d.ts +250 -0
  5. package/dist/OneForexTradeHistory-iDySMcw0.d.mts +250 -0
  6. package/dist/components/index.d.mts +539 -0
  7. package/dist/components/index.d.ts +539 -0
  8. package/dist/components/index.js +7295 -0
  9. package/dist/components/index.js.map +1 -0
  10. package/dist/components/index.mjs +7243 -0
  11. package/dist/components/index.mjs.map +1 -0
  12. package/dist/config/index.d.mts +1 -0
  13. package/dist/config/index.d.ts +1 -0
  14. package/dist/console-BfTMA7ah.d.mts +504 -0
  15. package/dist/console-BfTMA7ah.d.ts +504 -0
  16. package/dist/hooks/index.d.mts +323 -1
  17. package/dist/hooks/index.d.ts +323 -1
  18. package/dist/hooks/index.js +3223 -0
  19. package/dist/hooks/index.js.map +1 -1
  20. package/dist/hooks/index.mjs +3204 -1
  21. package/dist/hooks/index.mjs.map +1 -1
  22. package/dist/index.d.mts +18 -352
  23. package/dist/index.d.ts +18 -352
  24. package/dist/index.js +8646 -574
  25. package/dist/index.js.map +1 -1
  26. package/dist/index.mjs +8449 -432
  27. package/dist/index.mjs.map +1 -1
  28. package/dist/providers/index.d.mts +31 -31
  29. package/dist/providers/index.d.ts +31 -31
  30. package/dist/providers/index.js +140 -153
  31. package/dist/providers/index.js.map +1 -1
  32. package/dist/providers/index.mjs +100 -109
  33. package/dist/providers/index.mjs.map +1 -1
  34. package/dist/react-native.d.mts +8 -144
  35. package/dist/react-native.d.ts +8 -144
  36. package/dist/react-native.js +2640 -689
  37. package/dist/react-native.js.map +1 -1
  38. package/dist/react-native.mjs +2610 -691
  39. package/dist/react-native.mjs.map +1 -1
  40. package/dist/services/index.d.mts +85 -4
  41. package/dist/services/index.d.ts +85 -4
  42. package/dist/services/index.js +1621 -0
  43. package/dist/services/index.js.map +1 -1
  44. package/dist/services/index.mjs +1619 -1
  45. package/dist/services/index.mjs.map +1 -1
  46. package/dist/types/index.d.mts +203 -1
  47. package/dist/types/index.d.ts +203 -1
  48. package/dist/types/index.js +275 -0
  49. package/dist/types/index.js.map +1 -1
  50. package/dist/types/index.mjs +251 -0
  51. package/dist/types/index.mjs.map +1 -1
  52. package/dist/useForexTrading-BleeSor8.d.mts +80 -0
  53. package/dist/useForexTrading-ZgW_G40Q.d.ts +80 -0
  54. package/package.json +9 -2
  55. package/src/components/OneConnectButton.tsx +24 -1
  56. package/src/components/OneNFTGallery.tsx +13 -7
  57. package/src/components/OneOfframpWidget.tsx +4 -3
  58. package/src/components/OnePayWidget.tsx +10 -1
  59. package/src/components/OneSendWidget.tsx +3 -3
  60. package/src/components/OneSwapWidget.tsx +4 -4
  61. package/src/components/OneTransactionButton.tsx +28 -3
  62. package/src/components/OneWalletBalance.tsx +1 -1
  63. package/src/components/ai/OneChainSelector.tsx +63 -336
  64. package/src/components/ai/OneForexCapitalSplit.tsx +112 -0
  65. package/src/components/ai/OneForexConsoleView.tsx +90 -0
  66. package/src/components/ai/OneForexPairSelector.tsx +101 -0
  67. package/src/components/ai/OneForexPoolCard.tsx +105 -0
  68. package/src/components/ai/OneForexTradeHistory.tsx +107 -0
  69. package/src/components/ai/OnePairSelector.tsx +77 -434
  70. package/src/components/ai/console/OneAIQuantConsole.tsx +423 -0
  71. package/src/components/ai/console/OneAgentCard.tsx +383 -0
  72. package/src/components/ai/console/OneAgentConsole.tsx +469 -0
  73. package/src/components/ai/console/OneDecisionTimeline.tsx +433 -0
  74. package/src/components/ai/console/OneMetricsDashboard.tsx +493 -0
  75. package/src/components/ai/console/OnePositionCard.tsx +406 -0
  76. package/src/components/ai/console/OnePositionDetail.tsx +600 -0
  77. package/src/components/ai/console/OneRiskIndicator.tsx +464 -0
  78. package/src/components/ai/console/OneTradingConsole.tsx +660 -0
  79. package/src/components/ai/console/index.ts +17 -0
  80. package/src/components/ai/index.ts +10 -0
  81. package/src/hooks/index.ts +46 -0
  82. package/src/hooks/useAIDecisions.ts +280 -0
  83. package/src/hooks/useAIPositions.ts +349 -0
  84. package/src/hooks/useAIQuantConsole.ts +283 -0
  85. package/src/hooks/useAIRiskStatus.ts +276 -0
  86. package/src/hooks/useAITrading.ts +190 -0
  87. package/src/hooks/useBotSimulation.ts +201 -0
  88. package/src/hooks/useForexTrading.ts +430 -0
  89. package/src/hooks/useTradingConsole.ts +243 -0
  90. package/src/index.ts +123 -5
  91. package/src/providers/OneProvider.tsx +181 -5
  92. package/src/providers/index.ts +22 -8
  93. package/src/react-native.ts +41 -0
  94. package/src/services/forex/BotSimulationEngine.ts +968 -0
  95. package/src/services/forex/ForexPoolDataGenerator.ts +542 -0
  96. package/src/services/forex/ForexSimulationEngine.ts +482 -0
  97. package/src/services/forex/index.ts +21 -0
  98. package/src/services/index.ts +16 -0
  99. package/src/types/aiTrading.ts +151 -0
  100. package/src/types/console.ts +380 -0
  101. package/src/types/forex.ts +282 -0
  102. package/src/types/index.ts +106 -0
  103. package/dist/price-CgqXPnT3.d.ts +0 -13
  104. package/dist/price-ClbLHHjv.d.mts +0 -13
  105. package/dist/supabase-BT0c7q9e.d.mts +0 -82
  106. package/dist/supabase-BT0c7q9e.d.ts +0 -82
@@ -1,10 +1,10 @@
1
1
  /**
2
- * OneChainSelector - Multi-chain selection component with dropdown style
3
- * Part of ONE Ecosystem SDK - Responsive design for desktop and mobile
2
+ * OneChainSelector - Multi-chain selection component for AI trading
3
+ * Part of ONE Ecosystem SDK - can be used by any ecosystem partner
4
4
  */
5
5
 
6
- import React, { useState } from 'react';
7
- import { View, Text, StyleSheet, TouchableOpacity, ViewStyle, TextStyle, Modal, ScrollView, Pressable, Dimensions, Platform } from 'react-native';
6
+ import React from 'react';
7
+ import { View, Text, StyleSheet, TouchableOpacity, ViewStyle, TextStyle } from 'react-native';
8
8
 
9
9
  // Chain configuration with branding
10
10
  export const CHAIN_CONFIG: Record<string, { name: string; icon: string; color: string }> = {
@@ -37,19 +37,12 @@ export interface OneChainSelectorProps {
37
37
  subtitle?: string;
38
38
  /** Minimum required selections (for multi-select) */
39
39
  minSelections?: number;
40
- /** Placeholder text */
41
- placeholder?: string;
42
40
  /** Custom styles */
43
41
  style?: ViewStyle;
44
42
  /** Custom title style */
45
43
  titleStyle?: TextStyle;
46
44
  }
47
45
 
48
- const isDesktop = () => {
49
- const { width } = Dimensions.get('window');
50
- return Platform.OS === 'web' && width >= 768;
51
- };
52
-
53
46
  export const OneChainSelector: React.FC<OneChainSelectorProps> = ({
54
47
  supportedChains,
55
48
  selectedChains,
@@ -59,179 +52,69 @@ export const OneChainSelector: React.FC<OneChainSelectorProps> = ({
59
52
  title,
60
53
  subtitle,
61
54
  minSelections = 1,
62
- placeholder = 'Select chains...',
63
55
  style,
64
56
  titleStyle,
65
57
  }) => {
66
- const [isOpen, setIsOpen] = useState(false);
67
- const desktop = isDesktop();
68
-
69
58
  const handleSelect = (chain: string) => {
70
59
  if (multiSelect) {
60
+ // In multi-select, prevent deselecting if at minimum
71
61
  if (selectedChains.includes(chain) && selectedChains.length <= minSelections) {
72
62
  return;
73
63
  }
74
64
  onSelectChain(chain);
75
65
  } else {
66
+ // Single select - always allow selection
76
67
  if (!selectedChains.includes(chain)) {
77
68
  onSelectChain(chain);
78
69
  }
79
- setIsOpen(false);
80
70
  }
81
71
  };
82
72
 
83
- // Desktop: Inline grid display
84
- if (desktop) {
85
- return (
86
- <View style={[styles.container, style]}>
87
- {title && <Text style={[styles.title, titleStyle]}>{title}</Text>}
88
- {subtitle && <Text style={styles.subtitle}>{subtitle}</Text>}
89
-
90
- <View style={styles.desktopGrid}>
91
- {supportedChains.map((chain) => {
92
- const chainInfo = CHAIN_CONFIG[chain] || { name: chain, icon: '●', color: '#888' };
93
- const isSelected = selectedChains.includes(chain);
94
-
95
- return (
96
- <TouchableOpacity
97
- key={chain}
98
- style={[
99
- styles.desktopChip,
100
- isSelected && styles.desktopChipSelected,
101
- isSelected && { borderColor: accentColor, backgroundColor: accentColor + '12' }
102
- ]}
103
- onPress={() => handleSelect(chain)}
104
- activeOpacity={0.7}
105
- >
106
- <View style={[styles.desktopIconBg, { backgroundColor: chainInfo.color + '20' }]}>
107
- <Text style={[styles.desktopIcon, { color: chainInfo.color }]}>{chainInfo.icon}</Text>
108
- </View>
109
- <Text style={[
110
- styles.desktopChipText,
111
- isSelected && { color: accentColor, fontWeight: '600' }
112
- ]}>
113
- {chainInfo.name}
114
- </Text>
115
- {isSelected && (
116
- <View style={[styles.desktopCheckbox, { backgroundColor: accentColor }]}>
117
- <Text style={styles.desktopCheckIcon}>✓</Text>
118
- </View>
119
- )}
120
- </TouchableOpacity>
121
- );
122
- })}
123
- </View>
124
-
125
- {multiSelect && selectedChains.length > 0 && (
126
- <Text style={[styles.selectedCount, { color: accentColor }]}>
127
- {selectedChains.length} chain{selectedChains.length > 1 ? 's' : ''} selected
128
- </Text>
129
- )}
130
- </View>
131
- );
132
- }
133
-
134
- // Mobile: Dropdown modal
135
73
  return (
136
74
  <View style={[styles.container, style]}>
137
75
  {title && <Text style={[styles.title, titleStyle]}>{title}</Text>}
138
76
  {subtitle && <Text style={styles.subtitle}>{subtitle}</Text>}
139
77
 
140
- <TouchableOpacity
141
- style={[styles.dropdownTrigger, { borderColor: isOpen ? accentColor : '#e5e5e5' }]}
142
- onPress={() => setIsOpen(true)}
143
- activeOpacity={0.7}
144
- >
145
- <View style={styles.selectedPreview}>
146
- {selectedChains.slice(0, 3).map((chain) => {
147
- const chainInfo = CHAIN_CONFIG[chain] || { name: chain, icon: '●', color: '#888' };
148
- return (
149
- <View key={chain} style={[styles.previewChip, { backgroundColor: chainInfo.color + '20' }]}>
150
- <Text style={[styles.previewIcon, { color: chainInfo.color }]}>{chainInfo.icon}</Text>
78
+ <View style={styles.chainsContainer}>
79
+ {supportedChains.map((chain) => {
80
+ const chainInfo = CHAIN_CONFIG[chain] || { name: chain, icon: '●', color: '#888' };
81
+ const isSelected = selectedChains.includes(chain);
82
+
83
+ return (
84
+ <TouchableOpacity
85
+ key={chain}
86
+ style={[
87
+ styles.chainChip,
88
+ isSelected && styles.chainChipSelected,
89
+ isSelected && { borderColor: accentColor, backgroundColor: accentColor + '15' }
90
+ ]}
91
+ onPress={() => handleSelect(chain)}
92
+ activeOpacity={0.7}
93
+ >
94
+ <View style={[styles.chainIconBg, { backgroundColor: chainInfo.color + '20' }]}>
95
+ <Text style={[styles.chainIcon, { color: chainInfo.color }]}>{chainInfo.icon}</Text>
151
96
  </View>
152
- );
153
- })}
154
- {selectedChains.length > 3 && (
155
- <View style={styles.previewMore}>
156
- <Text style={styles.previewMoreText}>+{selectedChains.length - 3}</Text>
157
- </View>
158
- )}
159
- {selectedChains.length === 0 && (
160
- <Text style={styles.placeholderText}>{placeholder}</Text>
161
- )}
162
- </View>
163
- <Text style={styles.dropdownArrow}>{isOpen ? '▲' : '▼'}</Text>
164
- </TouchableOpacity>
97
+ <Text style={[
98
+ styles.chainText,
99
+ isSelected && { color: accentColor, fontWeight: '600' }
100
+ ]}>
101
+ {chainInfo.name}
102
+ </Text>
103
+ {isSelected && (
104
+ <Text style={[styles.checkmark, { color: accentColor }]}>✓</Text>
105
+ )}
106
+ </TouchableOpacity>
107
+ );
108
+ })}
109
+ </View>
165
110
 
166
111
  {multiSelect && selectedChains.length > 0 && (
167
- <Text style={[styles.selectedCount, { color: accentColor }]}>
168
- {selectedChains.length} chain{selectedChains.length > 1 ? 's' : ''} selected
169
- </Text>
112
+ <View style={styles.selectedInfo}>
113
+ <Text style={styles.selectedText}>
114
+ {selectedChains.length} chain{selectedChains.length > 1 ? 's' : ''} selected
115
+ </Text>
116
+ </View>
170
117
  )}
171
-
172
- <Modal
173
- visible={isOpen}
174
- transparent
175
- animationType="fade"
176
- onRequestClose={() => setIsOpen(false)}
177
- >
178
- <Pressable style={styles.modalOverlay} onPress={() => setIsOpen(false)}>
179
- <View style={styles.modalContent}>
180
- <View style={styles.modalHeader}>
181
- <Text style={styles.modalTitle}>{title || 'Select Chains'}</Text>
182
- <TouchableOpacity onPress={() => setIsOpen(false)}>
183
- <Text style={styles.modalClose}>✕</Text>
184
- </TouchableOpacity>
185
- </View>
186
-
187
- <ScrollView style={styles.optionsList} showsVerticalScrollIndicator={false}>
188
- {supportedChains.map((chain) => {
189
- const chainInfo = CHAIN_CONFIG[chain] || { name: chain, icon: '●', color: '#888' };
190
- const isSelected = selectedChains.includes(chain);
191
-
192
- return (
193
- <TouchableOpacity
194
- key={chain}
195
- style={[
196
- styles.optionItem,
197
- isSelected && styles.optionItemSelected,
198
- isSelected && { backgroundColor: accentColor + '10', borderColor: accentColor }
199
- ]}
200
- onPress={() => handleSelect(chain)}
201
- activeOpacity={0.7}
202
- >
203
- <View style={[styles.optionIconBg, { backgroundColor: chainInfo.color + '20' }]}>
204
- <Text style={[styles.optionIcon, { color: chainInfo.color }]}>{chainInfo.icon}</Text>
205
- </View>
206
- <Text style={[
207
- styles.optionText,
208
- isSelected && { color: accentColor, fontWeight: '600' }
209
- ]}>
210
- {chainInfo.name}
211
- </Text>
212
- {isSelected ? (
213
- <View style={[styles.checkbox, { backgroundColor: accentColor }]}>
214
- <Text style={styles.checkboxIcon}>✓</Text>
215
- </View>
216
- ) : (
217
- <View style={styles.checkboxEmpty} />
218
- )}
219
- </TouchableOpacity>
220
- );
221
- })}
222
- </ScrollView>
223
-
224
- {multiSelect && (
225
- <TouchableOpacity
226
- style={[styles.doneButton, { backgroundColor: accentColor }]}
227
- onPress={() => setIsOpen(false)}
228
- >
229
- <Text style={styles.doneButtonText}>Done ({selectedChains.length})</Text>
230
- </TouchableOpacity>
231
- )}
232
- </View>
233
- </Pressable>
234
- </Modal>
235
118
  </View>
236
119
  );
237
120
  };
@@ -251,206 +134,50 @@ const styles = StyleSheet.create({
251
134
  color: '#666',
252
135
  marginBottom: 12,
253
136
  },
254
- // Desktop styles
255
- desktopGrid: {
137
+ chainsContainer: {
256
138
  flexDirection: 'row',
257
139
  flexWrap: 'wrap',
258
- gap: 10,
140
+ gap: 8,
259
141
  },
260
- desktopChip: {
142
+ chainChip: {
261
143
  flexDirection: 'row',
262
144
  alignItems: 'center',
263
- paddingHorizontal: 14,
264
- paddingVertical: 10,
145
+ paddingHorizontal: 12,
146
+ paddingVertical: 8,
265
147
  backgroundColor: '#fff',
266
- borderRadius: 10,
148
+ borderRadius: 12,
267
149
  borderWidth: 2,
268
- borderColor: '#e8e8e8',
269
- gap: 10,
270
- cursor: 'pointer' as any,
150
+ borderColor: '#e5e5e5',
151
+ gap: 8,
271
152
  },
272
- desktopChipSelected: {
153
+ chainChipSelected: {
273
154
  borderWidth: 2,
274
155
  },
275
- desktopIconBg: {
276
- width: 32,
277
- height: 32,
278
- borderRadius: 16,
156
+ chainIconBg: {
157
+ width: 28,
158
+ height: 28,
159
+ borderRadius: 14,
279
160
  alignItems: 'center',
280
161
  justifyContent: 'center',
281
162
  },
282
- desktopIcon: {
163
+ chainIcon: {
283
164
  fontSize: 14,
284
165
  fontWeight: '700',
285
166
  },
286
- desktopChipText: {
167
+ chainText: {
287
168
  fontSize: 14,
288
- color: '#444',
289
- },
290
- desktopCheckbox: {
291
- width: 20,
292
- height: 20,
293
- borderRadius: 10,
294
- alignItems: 'center',
295
- justifyContent: 'center',
296
- marginLeft: 4,
297
- },
298
- desktopCheckIcon: {
299
- fontSize: 12,
300
- color: '#fff',
301
- fontWeight: '700',
302
- },
303
- // Mobile dropdown styles
304
- dropdownTrigger: {
305
- flexDirection: 'row',
306
- alignItems: 'center',
307
- justifyContent: 'space-between',
308
- paddingHorizontal: 14,
309
- paddingVertical: 12,
310
- backgroundColor: '#fff',
311
- borderRadius: 12,
312
- borderWidth: 2,
313
- borderColor: '#e5e5e5',
314
- minHeight: 52,
315
- },
316
- selectedPreview: {
317
- flex: 1,
318
- flexDirection: 'row',
319
- alignItems: 'center',
320
- gap: 6,
321
- },
322
- previewChip: {
323
- width: 32,
324
- height: 32,
325
- borderRadius: 16,
326
- alignItems: 'center',
327
- justifyContent: 'center',
169
+ color: '#666',
328
170
  },
329
- previewIcon: {
330
- fontSize: 14,
171
+ checkmark: {
172
+ fontSize: 16,
331
173
  fontWeight: '700',
332
174
  },
333
- previewMore: {
334
- paddingHorizontal: 8,
175
+ selectedInfo: {
176
+ marginTop: 8,
335
177
  paddingVertical: 4,
336
- backgroundColor: '#f0f0f0',
337
- borderRadius: 8,
338
- },
339
- previewMoreText: {
340
- fontSize: 12,
341
- color: '#666',
342
- fontWeight: '600',
343
- },
344
- placeholderText: {
345
- fontSize: 14,
346
- color: '#999',
347
- },
348
- dropdownArrow: {
349
- fontSize: 12,
350
- color: '#888',
351
- marginLeft: 8,
352
178
  },
353
- selectedCount: {
179
+ selectedText: {
354
180
  fontSize: 12,
355
- marginTop: 6,
356
- fontWeight: '500',
357
- },
358
- // Modal styles
359
- modalOverlay: {
360
- flex: 1,
361
- backgroundColor: 'rgba(0, 0, 0, 0.5)',
362
- justifyContent: 'center',
363
- alignItems: 'center',
364
- },
365
- modalContent: {
366
- width: '85%',
367
- maxWidth: 340,
368
- maxHeight: '70%',
369
- backgroundColor: '#fff',
370
- borderRadius: 16,
371
- overflow: 'hidden',
372
- },
373
- modalHeader: {
374
- flexDirection: 'row',
375
- justifyContent: 'space-between',
376
- alignItems: 'center',
377
- paddingHorizontal: 16,
378
- paddingVertical: 14,
379
- borderBottomWidth: 1,
380
- borderBottomColor: '#f0f0f0',
381
- },
382
- modalTitle: {
383
- fontSize: 18,
384
- fontWeight: '700',
385
- color: '#1a1a1a',
386
- },
387
- modalClose: {
388
- fontSize: 20,
389
181
  color: '#888',
390
- padding: 4,
391
- },
392
- optionsList: {
393
- padding: 8,
394
- },
395
- optionItem: {
396
- flexDirection: 'row',
397
- alignItems: 'center',
398
- paddingHorizontal: 12,
399
- paddingVertical: 12,
400
- borderRadius: 10,
401
- borderWidth: 1,
402
- borderColor: 'transparent',
403
- marginBottom: 6,
404
- gap: 12,
405
- },
406
- optionItemSelected: {
407
- borderWidth: 1,
408
- },
409
- optionIconBg: {
410
- width: 36,
411
- height: 36,
412
- borderRadius: 18,
413
- alignItems: 'center',
414
- justifyContent: 'center',
415
- },
416
- optionIcon: {
417
- fontSize: 16,
418
- fontWeight: '700',
419
- },
420
- optionText: {
421
- flex: 1,
422
- fontSize: 15,
423
- color: '#333',
424
- },
425
- checkbox: {
426
- width: 24,
427
- height: 24,
428
- borderRadius: 12,
429
- alignItems: 'center',
430
- justifyContent: 'center',
431
- },
432
- checkboxIcon: {
433
- fontSize: 14,
434
- color: '#fff',
435
- fontWeight: '700',
436
- },
437
- checkboxEmpty: {
438
- width: 24,
439
- height: 24,
440
- borderRadius: 12,
441
- borderWidth: 2,
442
- borderColor: '#ddd',
443
- },
444
- doneButton: {
445
- marginHorizontal: 16,
446
- marginVertical: 12,
447
- paddingVertical: 14,
448
- borderRadius: 10,
449
- alignItems: 'center',
450
- },
451
- doneButtonText: {
452
- fontSize: 16,
453
- fontWeight: '600',
454
- color: '#fff',
455
182
  },
456
183
  });
@@ -0,0 +1,112 @@
1
+ /**
2
+ * OneForexCapitalSplit - Displays 50/50 capital allocation split
3
+ * Part of ONE Ecosystem SDK
4
+ */
5
+
6
+ import React from 'react';
7
+ import { View, Text, StyleSheet, ViewStyle } from 'react-native';
8
+ import { FOREX_CAPITAL_SPLIT, FOREX_POOL_DEFAULTS, computePoolAllocations } from '../../types/forex';
9
+
10
+ export interface OneForexCapitalSplitProps {
11
+ /** Total investment amount */
12
+ amount: number;
13
+ /** Labels (provide translated strings) */
14
+ labels?: {
15
+ title?: string;
16
+ tradingCapital?: string;
17
+ poolReserves?: string;
18
+ clearing?: string;
19
+ hedging?: string;
20
+ insurance?: string;
21
+ };
22
+ /** Show pool breakdown within reserves */
23
+ showPoolBreakdown?: boolean;
24
+ /** Custom container style */
25
+ style?: ViewStyle;
26
+ /** Dark mode */
27
+ dark?: boolean;
28
+ }
29
+
30
+ export const OneForexCapitalSplit: React.FC<OneForexCapitalSplitProps> = ({
31
+ amount,
32
+ labels = {},
33
+ showPoolBreakdown = true,
34
+ style,
35
+ dark = false,
36
+ }) => {
37
+ const allocs = computePoolAllocations(amount);
38
+ const bg = dark ? '#111111' : '#ffffff';
39
+ const border = dark ? '#1a1a1a' : '#e5e5e5';
40
+ const textPrimary = dark ? '#ffffff' : '#1a1a1a';
41
+ const textSecondary = dark ? '#9ca3af' : '#666666';
42
+ const itemBg = dark ? '#0a0a0a' : '#f5f5f5';
43
+
44
+ return (
45
+ <View style={[styles.container, { backgroundColor: bg, borderColor: border }, style]}>
46
+ {labels.title && <Text style={[styles.title, { color: textPrimary }]}>{labels.title}</Text>}
47
+
48
+ <View style={styles.splitRow}>
49
+ <View style={[styles.splitItem, { backgroundColor: itemBg }]}>
50
+ <View style={[styles.dot, { backgroundColor: '#0EA5E9' }]} />
51
+ <Text style={[styles.splitLabel, { color: textSecondary }]}>
52
+ {labels.tradingCapital || 'Active Trading (RFQ)'}
53
+ </Text>
54
+ <Text style={[styles.splitPct, { color: textSecondary }]}>50%</Text>
55
+ <Text style={[styles.splitAmt, { color: textPrimary }]}>
56
+ ${allocs.tradingCapital.toLocaleString()}
57
+ </Text>
58
+ </View>
59
+ <View style={[styles.splitItem, { backgroundColor: itemBg }]}>
60
+ <View style={[styles.dot, { backgroundColor: '#8B5CF6' }]} />
61
+ <Text style={[styles.splitLabel, { color: textSecondary }]}>
62
+ {labels.poolReserves || 'Pool Reserves'}
63
+ </Text>
64
+ <Text style={[styles.splitPct, { color: textSecondary }]}>50%</Text>
65
+ <Text style={[styles.splitAmt, { color: textPrimary }]}>
66
+ ${allocs.totalPoolReserves.toLocaleString()}
67
+ </Text>
68
+ </View>
69
+ </View>
70
+
71
+ {showPoolBreakdown && amount > 0 && (
72
+ <View style={[styles.breakdown, { borderTopColor: border }]}>
73
+ {FOREX_POOL_DEFAULTS.map(pool => {
74
+ const poolAmt = allocs[pool.id as keyof typeof allocs] as number;
75
+ return (
76
+ <View key={pool.id} style={styles.poolRow}>
77
+ <View style={[styles.poolDot, { backgroundColor: pool.color }]} />
78
+ <Text style={[styles.poolName, { color: textSecondary }]}>
79
+ {(labels as any)?.[pool.id] || pool.nameKey}
80
+ </Text>
81
+ <View style={[styles.poolBar, { backgroundColor: dark ? '#1a1a1a' : '#e5e5e5' }]}>
82
+ <View style={[styles.poolBarFill, { width: `${pool.allocation * 100}%`, backgroundColor: pool.color }]} />
83
+ </View>
84
+ <Text style={[styles.poolAmt, { color: textPrimary }]}>
85
+ ${poolAmt.toLocaleString()}
86
+ </Text>
87
+ </View>
88
+ );
89
+ })}
90
+ </View>
91
+ )}
92
+ </View>
93
+ );
94
+ };
95
+
96
+ const styles = StyleSheet.create({
97
+ container: { borderRadius: 8, borderWidth: 1, padding: 14 },
98
+ title: { fontSize: 14, fontWeight: '600', marginBottom: 12 },
99
+ splitRow: { gap: 8 },
100
+ splitItem: { flexDirection: 'row', alignItems: 'center', paddingVertical: 10, paddingHorizontal: 12, borderRadius: 8 },
101
+ dot: { width: 10, height: 10, borderRadius: 5, marginRight: 8 },
102
+ splitLabel: { flex: 1, fontSize: 13, fontWeight: '500' },
103
+ splitPct: { fontSize: 12, fontWeight: '600', marginRight: 12 },
104
+ splitAmt: { fontSize: 14, fontWeight: '700' },
105
+ breakdown: { marginTop: 12, paddingTop: 12, borderTopWidth: 1 },
106
+ poolRow: { flexDirection: 'row', alignItems: 'center', marginBottom: 8 },
107
+ poolDot: { width: 8, height: 8, borderRadius: 4, marginRight: 8 },
108
+ poolName: { width: 80, fontSize: 12 },
109
+ poolBar: { flex: 1, height: 6, borderRadius: 3, overflow: 'hidden', marginHorizontal: 8 },
110
+ poolBarFill: { height: '100%', borderRadius: 3 },
111
+ poolAmt: { width: 70, fontSize: 12, fontWeight: '600', textAlign: 'right' },
112
+ });
@@ -0,0 +1,90 @@
1
+ /**
2
+ * OneForexConsoleView - Displays live forex trading console log feed
3
+ * Part of ONE Ecosystem SDK
4
+ */
5
+
6
+ import React, { useRef, useEffect } from 'react';
7
+ import { View, Text, StyleSheet, ScrollView, ViewStyle, Platform } from 'react-native';
8
+ import type { ForexLogEntry } from '../../types/forex';
9
+ import { FOREX_LOG_COLORS } from '../../types/console';
10
+
11
+ const MONO = Platform.OS === 'ios' ? 'Courier New' : 'monospace';
12
+
13
+ export interface OneForexConsoleViewProps {
14
+ /** Array of log entries to display */
15
+ logs: ForexLogEntry[];
16
+ /** Maximum visible entries */
17
+ maxItems?: number;
18
+ /** Auto-scroll to bottom */
19
+ autoScroll?: boolean;
20
+ /** Custom container style */
21
+ style?: ViewStyle;
22
+ /** Console height */
23
+ height?: number;
24
+ }
25
+
26
+ export const OneForexConsoleView: React.FC<OneForexConsoleViewProps> = ({
27
+ logs,
28
+ maxItems = 100,
29
+ autoScroll = true,
30
+ style,
31
+ height = 400,
32
+ }) => {
33
+ const scrollRef = useRef<ScrollView>(null);
34
+ const visibleLogs = logs.slice(-maxItems);
35
+
36
+ useEffect(() => {
37
+ if (autoScroll && scrollRef.current) {
38
+ setTimeout(() => scrollRef.current?.scrollToEnd({ animated: true }), 50);
39
+ }
40
+ }, [logs.length, autoScroll]);
41
+
42
+ const formatTime = (ts: number) => {
43
+ const d = new Date(ts);
44
+ return `${d.getHours().toString().padStart(2, '0')}:${d.getMinutes().toString().padStart(2, '0')}:${d.getSeconds().toString().padStart(2, '0')}`;
45
+ };
46
+
47
+ return (
48
+ <View style={[styles.container, { height }, style]}>
49
+ <ScrollView ref={scrollRef} style={styles.scroll} contentContainerStyle={styles.scrollContent}>
50
+ {visibleLogs.map((log) => (
51
+ <View key={log.id} style={styles.logRow}>
52
+ <Text style={styles.timestamp}>{formatTime(log.timestamp)}</Text>
53
+ <Text style={[styles.type, { color: FOREX_LOG_COLORS[log.type] || '#9CA3AF' }]}>
54
+ {log.type.padEnd(8)}
55
+ </Text>
56
+ <Text style={[
57
+ styles.message,
58
+ log.importance === 'high' && styles.messageHigh,
59
+ ]} numberOfLines={2}>
60
+ {log.message}
61
+ </Text>
62
+ </View>
63
+ ))}
64
+ {visibleLogs.length === 0 && (
65
+ <Text style={styles.emptyText}>Waiting for trading activity...</Text>
66
+ )}
67
+ </ScrollView>
68
+ </View>
69
+ );
70
+ };
71
+
72
+ // Terminal palette – always dark regardless of app theme
73
+ const T = {
74
+ base: '#0A0A0C',
75
+ border: '#2A2A35',
76
+ muted: '#555560',
77
+ secondary: '#9CA3AF',
78
+ };
79
+
80
+ const styles = StyleSheet.create({
81
+ container: { backgroundColor: T.base, borderRadius: 8, borderWidth: 1, borderColor: T.border, overflow: 'hidden' },
82
+ scroll: { flex: 1 },
83
+ scrollContent: { padding: 8 },
84
+ logRow: { flexDirection: 'row', paddingVertical: 3 },
85
+ timestamp: { fontFamily: MONO, fontSize: 10, color: T.muted, width: 60, marginRight: 6 },
86
+ type: { fontFamily: MONO, fontSize: 10, fontWeight: '700', width: 65, marginRight: 6 },
87
+ message: { fontFamily: MONO, fontSize: 10, color: T.secondary, flex: 1 },
88
+ messageHigh: { color: '#ffffff', fontWeight: '600' },
89
+ emptyText: { fontFamily: MONO, fontSize: 11, color: T.muted, textAlign: 'center', paddingVertical: 40 },
90
+ });