@one_deploy/sdk 1.0.6 → 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 (104) 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 -140
  35. package/dist/react-native.d.ts +8 -140
  36. package/dist/react-native.js +2527 -0
  37. package/dist/react-native.js.map +1 -1
  38. package/dist/react-native.mjs +2497 -2
  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/OneForexCapitalSplit.tsx +112 -0
  64. package/src/components/ai/OneForexConsoleView.tsx +90 -0
  65. package/src/components/ai/OneForexPairSelector.tsx +101 -0
  66. package/src/components/ai/OneForexPoolCard.tsx +105 -0
  67. package/src/components/ai/OneForexTradeHistory.tsx +107 -0
  68. package/src/components/ai/console/OneAIQuantConsole.tsx +423 -0
  69. package/src/components/ai/console/OneAgentCard.tsx +383 -0
  70. package/src/components/ai/console/OneAgentConsole.tsx +469 -0
  71. package/src/components/ai/console/OneDecisionTimeline.tsx +433 -0
  72. package/src/components/ai/console/OneMetricsDashboard.tsx +493 -0
  73. package/src/components/ai/console/OnePositionCard.tsx +406 -0
  74. package/src/components/ai/console/OnePositionDetail.tsx +600 -0
  75. package/src/components/ai/console/OneRiskIndicator.tsx +464 -0
  76. package/src/components/ai/console/OneTradingConsole.tsx +660 -0
  77. package/src/components/ai/console/index.ts +17 -0
  78. package/src/components/ai/index.ts +10 -0
  79. package/src/hooks/index.ts +46 -0
  80. package/src/hooks/useAIDecisions.ts +280 -0
  81. package/src/hooks/useAIPositions.ts +349 -0
  82. package/src/hooks/useAIQuantConsole.ts +283 -0
  83. package/src/hooks/useAIRiskStatus.ts +276 -0
  84. package/src/hooks/useAITrading.ts +190 -0
  85. package/src/hooks/useBotSimulation.ts +201 -0
  86. package/src/hooks/useForexTrading.ts +430 -0
  87. package/src/hooks/useTradingConsole.ts +243 -0
  88. package/src/index.ts +123 -5
  89. package/src/providers/OneProvider.tsx +181 -5
  90. package/src/providers/index.ts +22 -8
  91. package/src/react-native.ts +41 -0
  92. package/src/services/forex/BotSimulationEngine.ts +968 -0
  93. package/src/services/forex/ForexPoolDataGenerator.ts +542 -0
  94. package/src/services/forex/ForexSimulationEngine.ts +482 -0
  95. package/src/services/forex/index.ts +21 -0
  96. package/src/services/index.ts +16 -0
  97. package/src/types/aiTrading.ts +151 -0
  98. package/src/types/console.ts +380 -0
  99. package/src/types/forex.ts +282 -0
  100. package/src/types/index.ts +106 -0
  101. package/dist/price-CgqXPnT3.d.ts +0 -13
  102. package/dist/price-ClbLHHjv.d.mts +0 -13
  103. package/dist/supabase-BT0c7q9e.d.mts +0 -82
  104. package/dist/supabase-BT0c7q9e.d.ts +0 -82
@@ -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
+ });
@@ -0,0 +1,101 @@
1
+ /**
2
+ * OneForexPairSelector - Stablecoin FX pair selection for forex trading
3
+ * Part of ONE Ecosystem SDK
4
+ */
5
+
6
+ import React from 'react';
7
+ import { View, Text, StyleSheet, TouchableOpacity, ViewStyle } from 'react-native';
8
+ import { FOREX_CURRENCY_PAIRS } from '../../types/forex';
9
+ import type { ForexCurrencyPair } from '../../types/forex';
10
+
11
+ export interface OneForexPairSelectorProps {
12
+ /** Currently selected pair IDs */
13
+ selectedPairs: string[];
14
+ /** Callback when a pair is toggled */
15
+ onTogglePair: (pairId: string) => void;
16
+ /** Accent color for selected state */
17
+ accentColor?: string;
18
+ /** Section title */
19
+ title?: string;
20
+ /** Section subtitle */
21
+ subtitle?: string;
22
+ /** Custom pairs list (defaults to FOREX_CURRENCY_PAIRS) */
23
+ pairs?: ForexCurrencyPair[];
24
+ /** Custom container style */
25
+ style?: ViewStyle;
26
+ }
27
+
28
+ export const OneForexPairSelector: React.FC<OneForexPairSelectorProps> = ({
29
+ selectedPairs,
30
+ onTogglePair,
31
+ accentColor = '#0EA5E9',
32
+ title,
33
+ subtitle,
34
+ pairs = FOREX_CURRENCY_PAIRS,
35
+ style,
36
+ }) => {
37
+ const handleToggle = (pairId: string) => {
38
+ if (selectedPairs.includes(pairId) && selectedPairs.length <= 1) return;
39
+ onTogglePair(pairId);
40
+ };
41
+
42
+ return (
43
+ <View style={[styles.container, style]}>
44
+ {title && <Text style={styles.title}>{title}</Text>}
45
+ {subtitle && <Text style={styles.subtitle}>{subtitle}</Text>}
46
+
47
+ <View style={styles.pairGrid}>
48
+ {pairs.map((pair) => {
49
+ const isSelected = selectedPairs.includes(pair.id);
50
+ return (
51
+ <TouchableOpacity
52
+ key={pair.id}
53
+ style={[
54
+ styles.pairBtn,
55
+ isSelected && styles.pairBtnActive,
56
+ isSelected && { borderColor: accentColor, backgroundColor: accentColor + '08' },
57
+ ]}
58
+ onPress={() => handleToggle(pair.id)}
59
+ activeOpacity={0.7}
60
+ >
61
+ <Text style={styles.pairFlag}>{pair.flag}</Text>
62
+ <View style={styles.pairInfo}>
63
+ <Text style={[styles.pairSymbol, isSelected && { color: accentColor, fontWeight: '600' }]}>
64
+ {pair.symbol}
65
+ </Text>
66
+ <Text style={styles.pairName}>{pair.name}</Text>
67
+ </View>
68
+ {isSelected && (
69
+ <Text style={[styles.check, { color: accentColor }]}>{'\u2713'}</Text>
70
+ )}
71
+ </TouchableOpacity>
72
+ );
73
+ })}
74
+ </View>
75
+
76
+ <Text style={styles.selectedInfo}>
77
+ {selectedPairs.length} pair{selectedPairs.length !== 1 ? 's' : ''} selected (min: 1)
78
+ </Text>
79
+ </View>
80
+ );
81
+ };
82
+
83
+ const styles = StyleSheet.create({
84
+ container: { marginBottom: 16 },
85
+ title: { fontSize: 16, fontWeight: '600', color: '#1a1a1a', marginBottom: 4 },
86
+ subtitle: { fontSize: 12, color: '#666', marginBottom: 12 },
87
+ pairGrid: { gap: 8 },
88
+ pairBtn: {
89
+ flexDirection: 'row', alignItems: 'center',
90
+ paddingHorizontal: 12, paddingVertical: 12,
91
+ borderRadius: 8, borderWidth: 1.5, borderColor: '#e5e5e5',
92
+ backgroundColor: '#fff', gap: 10,
93
+ },
94
+ pairBtnActive: { borderWidth: 2 },
95
+ pairFlag: { fontSize: 20 },
96
+ pairInfo: { flex: 1 },
97
+ pairSymbol: { fontSize: 14, color: '#666' },
98
+ pairName: { fontSize: 11, color: '#999' },
99
+ check: { fontSize: 16, fontWeight: '700' },
100
+ selectedInfo: { fontSize: 12, color: '#888', marginTop: 8 },
101
+ });
@@ -0,0 +1,105 @@
1
+ /**
2
+ * OneForexPoolCard - Displays a forex liquidity pool with metrics
3
+ * Part of ONE Ecosystem SDK
4
+ */
5
+
6
+ import React from 'react';
7
+ import { View, Text, StyleSheet, ViewStyle } from 'react-native';
8
+ import type { ForexPool } from '../../types/forex';
9
+
10
+ export interface OneForexPoolCardProps {
11
+ /** Pool data object */
12
+ pool: ForexPool;
13
+ /** Pool display name (provide translated string) */
14
+ poolName?: string;
15
+ /** Whether to show enhanced metrics (APY, flow, tx count) */
16
+ showMetrics?: boolean;
17
+ /** Custom accent color override */
18
+ accentColor?: string;
19
+ /** Custom container style */
20
+ style?: ViewStyle;
21
+ /** Dark mode */
22
+ dark?: boolean;
23
+ }
24
+
25
+ export const OneForexPoolCard: React.FC<OneForexPoolCardProps> = ({
26
+ pool,
27
+ poolName,
28
+ showMetrics = true,
29
+ accentColor,
30
+ style,
31
+ dark = true,
32
+ }) => {
33
+ const color = accentColor || pool.color;
34
+ const bg = dark ? '#111111' : '#ffffff';
35
+ const border = dark ? '#1a1a1a' : '#e5e5e5';
36
+ const textPrimary = dark ? '#ffffff' : '#1a1a1a';
37
+ const textSecondary = dark ? '#9ca3af' : '#666666';
38
+ const textMuted = dark ? '#666666' : '#999999';
39
+ const barBg = dark ? '#1a1a1a' : '#e5e5e5';
40
+
41
+ return (
42
+ <View style={[styles.container, { backgroundColor: bg, borderColor: border }, style]}>
43
+ <View style={styles.header}>
44
+ <View style={[styles.dot, { backgroundColor: color }]} />
45
+ <Text style={[styles.name, { color: textPrimary }]}>
46
+ {poolName || pool.nameKey}
47
+ </Text>
48
+ <Text style={[styles.alloc, { color: textSecondary }]}>
49
+ {(pool.allocation * 100).toFixed(0)}%
50
+ </Text>
51
+ </View>
52
+
53
+ <View style={[styles.barOuter, { backgroundColor: barBg }]}>
54
+ <View style={[styles.barFill, { width: `${pool.utilization * 100}%`, backgroundColor: color }]} />
55
+ </View>
56
+
57
+ <View style={styles.statsRow}>
58
+ <Text style={[styles.statValue, { color: textSecondary }]}>
59
+ ${(pool.totalSize / 1_000_000).toFixed(1)}M
60
+ </Text>
61
+ <Text style={[styles.statLabel, { color: textMuted }]}>
62
+ {(pool.utilization * 100).toFixed(1)}% util
63
+ </Text>
64
+ </View>
65
+
66
+ {showMetrics && (
67
+ <View style={[styles.metricsRow, { borderTopColor: border }]}>
68
+ <View style={styles.metricItem}>
69
+ <Text style={[styles.metricLabel, { color: textMuted }]}>APY 7d</Text>
70
+ <Text style={[styles.metricValue, { color: '#10B981' }]}>
71
+ {pool.apy7d.toFixed(1)}%
72
+ </Text>
73
+ </View>
74
+ <View style={styles.metricItem}>
75
+ <Text style={[styles.metricLabel, { color: textMuted }]}>24h Flow</Text>
76
+ <Text style={[styles.metricValue, { color: pool.netFlow24h >= 0 ? '#10B981' : '#EF4444' }]}>
77
+ {pool.netFlow24h >= 0 ? '+' : ''}${(pool.netFlow24h / 1000).toFixed(0)}K
78
+ </Text>
79
+ </View>
80
+ <View style={styles.metricItem}>
81
+ <Text style={[styles.metricLabel, { color: textMuted }]}>Txs</Text>
82
+ <Text style={[styles.metricValue, { color: textPrimary }]}>{pool.txCount24h}</Text>
83
+ </View>
84
+ </View>
85
+ )}
86
+ </View>
87
+ );
88
+ };
89
+
90
+ const styles = StyleSheet.create({
91
+ container: { borderRadius: 8, borderWidth: 1, padding: 14 },
92
+ header: { flexDirection: 'row', alignItems: 'center', marginBottom: 8, gap: 8 },
93
+ dot: { width: 8, height: 8, borderRadius: 4 },
94
+ name: { fontSize: 13, fontWeight: '600', flex: 1 },
95
+ alloc: { fontSize: 12 },
96
+ barOuter: { height: 6, borderRadius: 3, overflow: 'hidden', marginBottom: 6 },
97
+ barFill: { height: '100%', borderRadius: 3 },
98
+ statsRow: { flexDirection: 'row', justifyContent: 'space-between' },
99
+ statValue: { fontSize: 12, fontWeight: '600' },
100
+ statLabel: { fontSize: 11 },
101
+ metricsRow: { flexDirection: 'row', justifyContent: 'space-between', paddingTop: 8, marginTop: 8, borderTopWidth: 1 },
102
+ metricItem: { alignItems: 'center', flex: 1 },
103
+ metricLabel: { fontSize: 9, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 2 },
104
+ metricValue: { fontSize: 12, fontWeight: '600' },
105
+ });
@@ -0,0 +1,107 @@
1
+ /**
2
+ * OneForexTradeHistory - Displays trade history with settlement details
3
+ * Part of ONE Ecosystem SDK
4
+ */
5
+
6
+ import React from 'react';
7
+ import { View, Text, StyleSheet, ScrollView, ViewStyle, Platform } from 'react-native';
8
+ import type { ForexTradeRecord } from '../../types/forex';
9
+
10
+ const MONO = Platform.OS === 'ios' ? 'Courier New' : 'monospace';
11
+
12
+ export interface OneForexTradeHistoryProps {
13
+ /** Trade records to display */
14
+ trades: ForexTradeRecord[];
15
+ /** Maximum trades to show */
16
+ maxItems?: number;
17
+ /** Show settlement details (clearing/hedging/insurance fees) */
18
+ showSettlementDetails?: boolean;
19
+ /** Show transaction hash */
20
+ showTxHash?: boolean;
21
+ /** Empty state text */
22
+ emptyText?: string;
23
+ /** Custom container style */
24
+ style?: ViewStyle;
25
+ }
26
+
27
+ export const OneForexTradeHistory: React.FC<OneForexTradeHistoryProps> = ({
28
+ trades,
29
+ maxItems = 50,
30
+ showSettlementDetails = true,
31
+ showTxHash = true,
32
+ emptyText = 'No trade history yet',
33
+ style,
34
+ }) => {
35
+ const visibleTrades = trades.slice(-maxItems).reverse();
36
+
37
+ if (visibleTrades.length === 0) {
38
+ return (
39
+ <View style={[styles.empty, style]}>
40
+ <Text style={styles.emptyText}>{emptyText}</Text>
41
+ </View>
42
+ );
43
+ }
44
+
45
+ return (
46
+ <ScrollView style={[styles.container, style]} contentContainerStyle={styles.scrollContent}>
47
+ {visibleTrades.map((trade) => (
48
+ <View key={trade.id} style={styles.card}>
49
+ <View style={styles.header}>
50
+ <Text style={styles.pair}>{trade.pairSymbol}</Text>
51
+ <View style={[
52
+ styles.sideBadge,
53
+ { backgroundColor: trade.side === 'BUY' ? '#10B98118' : '#EF444418', borderColor: trade.side === 'BUY' ? '#10B98140' : '#EF444440' },
54
+ ]}>
55
+ <Text style={[styles.sideText, { color: trade.side === 'BUY' ? '#10B981' : '#EF4444' }]}>
56
+ {trade.side}
57
+ </Text>
58
+ </View>
59
+ <Text style={[styles.pnl, { color: trade.pnl >= 0 ? '#10B981' : '#EF4444' }]}>
60
+ {trade.pnl >= 0 ? '+' : ''}${trade.pnl.toFixed(2)}
61
+ </Text>
62
+ </View>
63
+
64
+ <View style={styles.details}>
65
+ <Text style={styles.detail}>
66
+ {trade.lots.toFixed(2)} lots | {trade.pips >= 0 ? '+' : ''}{trade.pips.toFixed(1)} pips
67
+ </Text>
68
+ <Text style={styles.time}>{new Date(trade.timestamp).toLocaleString()}</Text>
69
+ </View>
70
+
71
+ {showSettlementDetails && trade.clearingFee !== undefined && (
72
+ <View style={styles.settlement}>
73
+ <Text style={styles.settlementText}>
74
+ CLR: ${trade.clearingFee.toFixed(2)} | HDG: ${(trade.hedgingCost || 0).toFixed(2)} | INS: ${(trade.insuranceReserve || 0).toFixed(2)}
75
+ </Text>
76
+ </View>
77
+ )}
78
+
79
+ {showTxHash && trade.txHash && (
80
+ <Text style={styles.txHash}>
81
+ {trade.txHash.slice(0, 10)}...{trade.txHash.slice(-6)}
82
+ </Text>
83
+ )}
84
+ </View>
85
+ ))}
86
+ </ScrollView>
87
+ );
88
+ };
89
+
90
+ const styles = StyleSheet.create({
91
+ container: { flex: 1 },
92
+ scrollContent: { paddingBottom: 16 },
93
+ empty: { alignItems: 'center', justifyContent: 'center', padding: 40 },
94
+ emptyText: { fontSize: 14, color: '#666' },
95
+ card: { backgroundColor: '#111111', borderRadius: 6, borderWidth: 1, borderColor: '#1a1a1a', padding: 12, marginBottom: 8 },
96
+ header: { flexDirection: 'row', alignItems: 'center', gap: 8 },
97
+ pair: { fontSize: 13, fontWeight: '600', color: '#ffffff' },
98
+ sideBadge: { paddingHorizontal: 6, paddingVertical: 2, borderRadius: 3, borderWidth: 1 },
99
+ sideText: { fontSize: 9, fontWeight: '700', letterSpacing: 0.5 },
100
+ pnl: { fontFamily: MONO, marginLeft: 'auto', fontSize: 13, fontWeight: '700' },
101
+ details: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 6 },
102
+ detail: { fontFamily: MONO, fontSize: 11, color: '#9ca3af' },
103
+ time: { fontSize: 11, color: '#666' },
104
+ settlement: { marginTop: 6, paddingTop: 6, borderTopWidth: 1, borderTopColor: '#1a1a1a' },
105
+ settlementText: { fontFamily: MONO, fontSize: 10, color: '#666' },
106
+ txHash: { fontFamily: MONO, fontSize: 9, color: '#444', marginTop: 2 },
107
+ });