@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,430 @@
1
+ /**
2
+ * ONE SDK - Forex Trading Hooks
3
+ * Provides React hooks for StableFX on-chain forex trading integration
4
+ * Can be used by any ecosystem partner
5
+ */
6
+
7
+ import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
8
+ import type {
9
+ ForexPool,
10
+ ForexPoolType,
11
+ ForexInvestment,
12
+ ForexLogEntry,
13
+ ForexPoolTransaction,
14
+ ForexPoolDailySnapshot,
15
+ ForexTradeRecord,
16
+ } from '../types/forex';
17
+ import {
18
+ FOREX_POOL_DEFAULTS,
19
+ FOREX_CYCLE_OPTIONS,
20
+ FOREX_AGENT,
21
+ FOREX_CAPITAL_SPLIT,
22
+ computePoolAllocations,
23
+ estimateForexProfit,
24
+ } from '../types/forex';
25
+
26
+ // ── Configuration ────────────────────────────────────────────────────────────
27
+
28
+ let _forexAccessToken: string | null = null;
29
+ let _forexEngineUrl: string = 'https://api.one23.io';
30
+
31
+ /** Set the access token for authenticated forex API calls */
32
+ export function setForexAccessToken(token: string): void {
33
+ _forexAccessToken = token;
34
+ }
35
+
36
+ /** Clear the forex access token */
37
+ export function clearForexAccessToken(): void {
38
+ _forexAccessToken = null;
39
+ }
40
+
41
+ /** Configure the engine URL for forex API calls */
42
+ export function setForexEngineUrl(url: string): void {
43
+ _forexEngineUrl = url;
44
+ }
45
+
46
+ // ── Internal API Helper ──────────────────────────────────────────────────────
47
+
48
+ async function forexApi<T>(path: string, options?: RequestInit): Promise<T | null> {
49
+ try {
50
+ const headers: Record<string, string> = {
51
+ 'Content-Type': 'application/json',
52
+ };
53
+ if (_forexAccessToken) {
54
+ headers['Authorization'] = `Bearer ${_forexAccessToken}`;
55
+ }
56
+ const res = await fetch(`${_forexEngineUrl}${path}`, { ...options, headers });
57
+ if (!res.ok) return null;
58
+ const json = await res.json();
59
+ return json?.data ?? json;
60
+ } catch {
61
+ return null;
62
+ }
63
+ }
64
+
65
+ // ── useForexPools ────────────────────────────────────────────────────────────
66
+
67
+ export interface UseForexPoolsResult {
68
+ pools: ForexPool[];
69
+ isLoading: boolean;
70
+ error: string | null;
71
+ refresh: () => void;
72
+ }
73
+
74
+ export function useForexPools(options?: { refreshInterval?: number }): UseForexPoolsResult {
75
+ const [pools, setPools] = useState<ForexPool[]>(FOREX_POOL_DEFAULTS);
76
+ const [isLoading, setIsLoading] = useState(false);
77
+ const [error, setError] = useState<string | null>(null);
78
+
79
+ const fetchPools = useCallback(async () => {
80
+ setIsLoading(true);
81
+ try {
82
+ const data = await forexApi<{ pools: any[] }>('/api/forex/pools');
83
+ if (data?.pools) {
84
+ setPools(data.pools.map((p: any) => ({
85
+ id: p.type ?? p.id,
86
+ nameKey: `forex.pool_${p.type ?? p.id}`,
87
+ descriptionKey: `forex.pool_${p.type ?? p.id}_desc`,
88
+ allocation: p.allocation ?? (p.type === 'clearing' ? 0.50 : p.type === 'hedging' ? 0.30 : 0.20),
89
+ totalSize: p.totalSize ?? p.total_size ?? 0,
90
+ utilization: p.utilization ?? 0,
91
+ color: p.type === 'clearing' ? '#3B82F6' : p.type === 'hedging' ? '#F59E0B' : '#10B981',
92
+ apy7d: p.apy7d ?? 0,
93
+ apy30d: p.apy30d ?? 0,
94
+ netFlow24h: p.netFlow24h ?? 0,
95
+ txCount24h: p.txCount24h ?? 0,
96
+ txCountTotal: p.txCountTotal ?? 0,
97
+ totalDeposits: p.totalDeposits ?? 0,
98
+ totalWithdrawals: p.totalWithdrawals ?? 0,
99
+ profitDistributed: p.profitDistributed ?? 0,
100
+ lastUpdated: p.lastUpdated ?? Date.now(),
101
+ })));
102
+ }
103
+ setError(null);
104
+ } catch (err) {
105
+ setError(err instanceof Error ? err.message : 'Failed to fetch pools');
106
+ } finally {
107
+ setIsLoading(false);
108
+ }
109
+ }, []);
110
+
111
+ useEffect(() => {
112
+ fetchPools();
113
+ if (options?.refreshInterval) {
114
+ const timer = setInterval(fetchPools, options.refreshInterval);
115
+ return () => clearInterval(timer);
116
+ }
117
+ }, [fetchPools, options?.refreshInterval]);
118
+
119
+ return { pools, isLoading, error, refresh: fetchPools };
120
+ }
121
+
122
+ // ── useForexInvestments ──────────────────────────────────────────────────────
123
+
124
+ export interface UseForexInvestmentsResult {
125
+ investments: ForexInvestment[];
126
+ isLoading: boolean;
127
+ error: string | null;
128
+ createInvestment: (params: { amount: number; selectedPairs: string[]; cycleDays: number }) => Promise<ForexInvestment | null>;
129
+ redeemInvestment: (investmentId: string) => Promise<boolean>;
130
+ refresh: () => void;
131
+ portfolioSummary: {
132
+ totalInvested: number;
133
+ totalValue: number;
134
+ totalProfit: number;
135
+ activeCount: number;
136
+ };
137
+ }
138
+
139
+ export function useForexInvestments(options?: { refreshInterval?: number }): UseForexInvestmentsResult {
140
+ const [investments, setInvestments] = useState<ForexInvestment[]>([]);
141
+ const [isLoading, setIsLoading] = useState(false);
142
+ const [error, setError] = useState<string | null>(null);
143
+
144
+ const fetchInvestments = useCallback(async () => {
145
+ setIsLoading(true);
146
+ try {
147
+ const data = await forexApi<{ investments: any[] }>('/api/forex/investments');
148
+ if (data?.investments) {
149
+ setInvestments(data.investments.map(mapInvestment));
150
+ }
151
+ setError(null);
152
+ } catch {
153
+ setError('Failed to fetch investments');
154
+ } finally {
155
+ setIsLoading(false);
156
+ }
157
+ }, []);
158
+
159
+ const createInvestment = useCallback(async (params: {
160
+ amount: number; selectedPairs: string[]; cycleDays: number;
161
+ }): Promise<ForexInvestment | null> => {
162
+ setIsLoading(true);
163
+ try {
164
+ const data = await forexApi<{ investment: any }>('/api/forex/investments', {
165
+ method: 'POST',
166
+ body: JSON.stringify(params),
167
+ });
168
+ if (data?.investment) {
169
+ const inv = mapInvestment(data.investment);
170
+ setInvestments(prev => [inv, ...prev]);
171
+ return inv;
172
+ }
173
+ // Local fallback
174
+ const inv = createLocalInvestment(params);
175
+ setInvestments(prev => [inv, ...prev]);
176
+ return inv;
177
+ } catch {
178
+ const inv = createLocalInvestment(params);
179
+ setInvestments(prev => [inv, ...prev]);
180
+ return inv;
181
+ } finally {
182
+ setIsLoading(false);
183
+ }
184
+ }, []);
185
+
186
+ const redeemInvestment = useCallback(async (investmentId: string): Promise<boolean> => {
187
+ try {
188
+ await forexApi(`/api/forex/investments/${investmentId}/redeem`, { method: 'POST' });
189
+ setInvestments(prev => prev.map(inv =>
190
+ inv.id === investmentId ? { ...inv, status: 'redeemed' as const } : inv
191
+ ));
192
+ return true;
193
+ } catch {
194
+ return false;
195
+ }
196
+ }, []);
197
+
198
+ useEffect(() => {
199
+ fetchInvestments();
200
+ if (options?.refreshInterval) {
201
+ const timer = setInterval(fetchInvestments, options.refreshInterval);
202
+ return () => clearInterval(timer);
203
+ }
204
+ }, [fetchInvestments, options?.refreshInterval]);
205
+
206
+ const portfolioSummary = useMemo(() => {
207
+ const active = investments.filter(i => i.status === 'active');
208
+ return {
209
+ totalInvested: active.reduce((s, i) => s + i.amount, 0),
210
+ totalValue: active.reduce((s, i) => s + i.currentValue, 0),
211
+ totalProfit: active.reduce((s, i) => s + i.profit, 0),
212
+ activeCount: active.length,
213
+ };
214
+ }, [investments]);
215
+
216
+ return { investments, isLoading, error, createInvestment, redeemInvestment, refresh: fetchInvestments, portfolioSummary };
217
+ }
218
+
219
+ // ── useForexSimulation ───────────────────────────────────────────────────────
220
+
221
+ export interface UseForexSimulationResult {
222
+ logs: ForexLogEntry[];
223
+ poolTransactions: ForexPoolTransaction[];
224
+ isRunning: boolean;
225
+ stats: { totalPnl: number; totalTrades: number; totalPips: number; totalLots: number };
226
+ start: () => void;
227
+ stop: () => void;
228
+ clearLogs: () => void;
229
+ }
230
+
231
+ export function useForexSimulation(options?: { maxLogs?: number }): UseForexSimulationResult {
232
+ const maxLogs = options?.maxLogs ?? 500;
233
+ const [logs, setLogs] = useState<ForexLogEntry[]>([]);
234
+ const [poolTxs, setPoolTxs] = useState<ForexPoolTransaction[]>([]);
235
+ const [isRunning, setIsRunning] = useState(false);
236
+ const [stats, setStats] = useState({ totalPnl: 0, totalTrades: 0, totalPips: 0, totalLots: 0 });
237
+ const engineRef = useRef<any>(null);
238
+
239
+ const getEngine = useCallback(() => {
240
+ if (!engineRef.current) {
241
+ try {
242
+ const { forexSimulationEngine } = require('../services/forex/ForexSimulationEngine');
243
+ engineRef.current = forexSimulationEngine;
244
+ } catch { /* not available */ }
245
+ }
246
+ return engineRef.current;
247
+ }, []);
248
+
249
+ const start = useCallback(() => {
250
+ const engine = getEngine();
251
+ if (!engine) return;
252
+ if (!engine.isRunning()) engine.start();
253
+ setIsRunning(true);
254
+ }, [getEngine]);
255
+
256
+ const stop = useCallback(() => {
257
+ const engine = getEngine();
258
+ if (engine) engine.stop();
259
+ setIsRunning(false);
260
+ }, [getEngine]);
261
+
262
+ const clearLogs = useCallback(() => {
263
+ setLogs([]);
264
+ setPoolTxs([]);
265
+ }, []);
266
+
267
+ useEffect(() => {
268
+ const engine = getEngine();
269
+ if (!engine) return;
270
+
271
+ const unsubLog = engine.onLog((entry: ForexLogEntry) => {
272
+ setLogs(prev => {
273
+ const next = [...prev, entry];
274
+ return next.length > maxLogs ? next.slice(-maxLogs) : next;
275
+ });
276
+ const s = engine.getStats();
277
+ setStats({ totalPnl: s.totalPnl, totalTrades: s.totalTrades, totalPips: s.totalPips, totalLots: s.totalLots });
278
+ });
279
+
280
+ const unsubTx = engine.onPoolTransaction((tx: ForexPoolTransaction) => {
281
+ setPoolTxs(prev => [...prev.slice(-999), tx]);
282
+ });
283
+
284
+ return () => {
285
+ unsubLog();
286
+ unsubTx();
287
+ };
288
+ }, [getEngine, maxLogs]);
289
+
290
+ return { logs, poolTransactions: poolTxs, isRunning, stats, start, stop, clearLogs };
291
+ }
292
+
293
+ // ── useForexPoolData ─────────────────────────────────────────────────────────
294
+
295
+ export interface UseForexPoolDataResult {
296
+ snapshots: Record<ForexPoolType, ForexPoolDailySnapshot[]>;
297
+ transactions: ForexPoolTransaction[];
298
+ isInitialized: boolean;
299
+ initialize: () => void;
300
+ }
301
+
302
+ export function useForexPoolData(): UseForexPoolDataResult {
303
+ const [snapshots, setSnapshots] = useState<Record<ForexPoolType, ForexPoolDailySnapshot[]>>({ clearing: [], hedging: [], insurance: [] });
304
+ const [transactions, setTransactions] = useState<ForexPoolTransaction[]>([]);
305
+ const [isInitialized, setIsInitialized] = useState(false);
306
+
307
+ const initialize = useCallback(() => {
308
+ if (isInitialized) return;
309
+ try {
310
+ const { ForexPoolDataGenerator } = require('../services/forex/ForexPoolDataGenerator');
311
+ const gen = ForexPoolDataGenerator.getInstance();
312
+ setSnapshots(gen.generateAllSnapshots());
313
+ setTransactions(gen.generateAllTransactions());
314
+ setIsInitialized(true);
315
+ } catch { /* not available */ }
316
+ }, [isInitialized]);
317
+
318
+ return { snapshots, transactions, isInitialized, initialize };
319
+ }
320
+
321
+ // ── Combined useForexTrading ─────────────────────────────────────────────────
322
+
323
+ export interface UseForexTradingResult {
324
+ pools: UseForexPoolsResult;
325
+ investments: UseForexInvestmentsResult;
326
+ simulation: UseForexSimulationResult;
327
+ poolData: UseForexPoolDataResult;
328
+ // Convenience re-exports
329
+ capitalSplit: typeof FOREX_CAPITAL_SPLIT;
330
+ agent: typeof FOREX_AGENT;
331
+ currencyPairs: typeof import('../types/forex').FOREX_CURRENCY_PAIRS;
332
+ cycleOptions: typeof import('../types/forex').FOREX_CYCLE_OPTIONS;
333
+ computePoolAllocations: typeof computePoolAllocations;
334
+ estimateProfit: typeof estimateForexProfit;
335
+ }
336
+
337
+ export function useForexTrading(options?: {
338
+ poolRefreshInterval?: number;
339
+ investmentRefreshInterval?: number;
340
+ }): UseForexTradingResult {
341
+ const pools = useForexPools({ refreshInterval: options?.poolRefreshInterval });
342
+ const investments = useForexInvestments({ refreshInterval: options?.investmentRefreshInterval });
343
+ const simulation = useForexSimulation();
344
+ const poolData = useForexPoolData();
345
+
346
+ return {
347
+ pools,
348
+ investments,
349
+ simulation,
350
+ poolData,
351
+ capitalSplit: FOREX_CAPITAL_SPLIT,
352
+ agent: FOREX_AGENT,
353
+ currencyPairs: require('../types/forex').FOREX_CURRENCY_PAIRS,
354
+ cycleOptions: require('../types/forex').FOREX_CYCLE_OPTIONS,
355
+ computePoolAllocations,
356
+ estimateProfit: estimateForexProfit,
357
+ };
358
+ }
359
+
360
+ // ── Internal Helpers ─────────────────────────────────────────────────────────
361
+
362
+ function mapInvestment(raw: any): ForexInvestment {
363
+ const cycleDays = raw.cycleDays ?? raw.cycle_days ?? 90;
364
+ const cycleOption = FOREX_CYCLE_OPTIONS.find(c => c.days === cycleDays) || FOREX_CYCLE_OPTIONS[2];
365
+ const amount = typeof raw.amount === 'string' ? parseFloat(raw.amount) : (raw.amount ?? 0);
366
+ const allocs = computePoolAllocations(amount);
367
+
368
+ return {
369
+ id: raw.id,
370
+ userId: raw.userId ?? raw.user_id,
371
+ amount,
372
+ currentValue: raw.currentValue ?? raw.current_value ?? amount,
373
+ profit: raw.profit ?? 0,
374
+ status: raw.status ?? 'active',
375
+ selectedPairs: raw.selectedPairs ?? raw.selected_pairs ?? [],
376
+ cycleDays,
377
+ cycleOption,
378
+ feeRate: raw.feeRate ?? cycleOption.feeRate,
379
+ commissionRate: raw.commissionRate ?? cycleOption.commissionRate,
380
+ startDate: raw.startDate ?? raw.start_date ?? new Date().toISOString(),
381
+ endDate: raw.endDate ?? raw.end_date ?? '',
382
+ tradingCapital: raw.tradingCapital ?? allocs.tradingCapital,
383
+ totalPoolReserves: raw.totalPoolReserves ?? allocs.totalPoolReserves,
384
+ poolAllocations: raw.poolAllocations ?? {
385
+ clearing: allocs.clearing,
386
+ hedging: allocs.hedging,
387
+ insurance: allocs.insurance,
388
+ },
389
+ tradeWeight: raw.tradeWeight ?? 0,
390
+ totalLots: raw.totalLots ?? 0,
391
+ totalPips: raw.totalPips ?? 0,
392
+ totalTrades: raw.totalTrades ?? 0,
393
+ positions: raw.positions ?? [],
394
+ tradeHistory: raw.tradeHistory ?? [],
395
+ redeemedAt: raw.redeemedAt,
396
+ createdAt: raw.createdAt,
397
+ updatedAt: raw.updatedAt,
398
+ };
399
+ }
400
+
401
+ function createLocalInvestment(params: { amount: number; selectedPairs: string[]; cycleDays: number }): ForexInvestment {
402
+ const { amount, selectedPairs, cycleDays } = params;
403
+ const cycleOption = FOREX_CYCLE_OPTIONS.find(c => c.days === cycleDays) || FOREX_CYCLE_OPTIONS[2];
404
+ const allocs = computePoolAllocations(amount);
405
+ const now = new Date();
406
+ const endDate = new Date(now);
407
+ endDate.setDate(endDate.getDate() + cycleDays);
408
+
409
+ return {
410
+ id: `fx_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
411
+ amount,
412
+ currentValue: amount,
413
+ profit: 0,
414
+ status: 'active',
415
+ selectedPairs,
416
+ cycleDays,
417
+ cycleOption,
418
+ startDate: now.toISOString(),
419
+ endDate: endDate.toISOString(),
420
+ tradingCapital: allocs.tradingCapital,
421
+ totalPoolReserves: allocs.totalPoolReserves,
422
+ poolAllocations: { clearing: allocs.clearing, hedging: allocs.hedging, insurance: allocs.insurance },
423
+ tradeWeight: 0,
424
+ totalLots: 0,
425
+ totalPips: 0,
426
+ totalTrades: 0,
427
+ positions: [],
428
+ tradeHistory: [],
429
+ };
430
+ }
@@ -0,0 +1,243 @@
1
+ /**
2
+ * ONE SDK - Master Trading Console Hook
3
+ * Orchestrates all AI and Forex trading data in a unified interface
4
+ */
5
+
6
+ import { useState, useEffect, useCallback, useMemo } from 'react';
7
+ import { useAIQuantConsole } from './useAIQuantConsole';
8
+ import { useForexSimulation, useForexPools, useForexInvestments } from './useForexTrading';
9
+ import type {
10
+ AIAgent,
11
+ AIPosition,
12
+ AIDecision,
13
+ RiskStatus,
14
+ ConsoleMetrics,
15
+ CombinedLogEntry,
16
+ TradingConsoleOptions,
17
+ TradingConsoleState,
18
+ } from '../types/console';
19
+ import { DEFAULT_CONSOLE_METRICS } from '../types/console';
20
+ import type { BotLogEntry, BotState, StrategyPersonality } from '../services/forex/BotSimulationEngine';
21
+ import type { ForexLogEntry, ForexPoolTransaction, ForexPool, ForexInvestment } from '../types/forex';
22
+
23
+ // ── Types ─────────────────────────────────────────────────────────────────────
24
+
25
+ export interface UseTradingConsoleResult {
26
+ // AI Data
27
+ ai: {
28
+ strategies: StrategyPersonality[];
29
+ agents: AIAgent[];
30
+ positions: AIPosition[];
31
+ decisions: AIDecision[];
32
+ riskStatus: RiskStatus | null;
33
+ simulationLogs: BotLogEntry[];
34
+ logsByStrategy: Map<string, BotLogEntry[]>;
35
+ botStates: Map<string, BotState>;
36
+ };
37
+ // Forex Data
38
+ forex: {
39
+ logs: ForexLogEntry[];
40
+ poolTransactions: ForexPoolTransaction[];
41
+ pools: ForexPool[];
42
+ investments: ForexInvestment[];
43
+ stats: {
44
+ totalPnl: number;
45
+ totalTrades: number;
46
+ totalPips: number;
47
+ totalLots: number;
48
+ };
49
+ };
50
+ // Combined
51
+ combinedLogs: CombinedLogEntry[];
52
+ metrics: ConsoleMetrics;
53
+ // Controls
54
+ controls: {
55
+ startAISimulation: (strategyIds?: string[]) => void;
56
+ stopAISimulation: (strategyIds?: string[]) => void;
57
+ startForexSimulation: () => void;
58
+ stopForexSimulation: () => void;
59
+ startAll: () => void;
60
+ stopAll: () => void;
61
+ clearLogs: () => void;
62
+ emitBootSequence: () => void;
63
+ refreshAll: () => Promise<void>;
64
+ };
65
+ // State
66
+ state: {
67
+ isAISimulationRunning: boolean;
68
+ isForexSimulationRunning: boolean;
69
+ isAnyRunning: boolean;
70
+ isLoading: boolean;
71
+ error: string | null;
72
+ };
73
+ // Agent helpers
74
+ getAgent: (strategyId: string) => AIAgent | undefined;
75
+ getAgentLogs: (strategyId: string) => BotLogEntry[];
76
+ getAgentPositions: (strategyId: string) => AIPosition[];
77
+ getAgentDecisions: (strategyId: string) => AIDecision[];
78
+ }
79
+
80
+ // ── Hook Implementation ───────────────────────────────────────────────────────
81
+
82
+ export function useTradingConsole(options?: TradingConsoleOptions): UseTradingConsoleResult {
83
+ const simulation = options?.simulation ?? true;
84
+ const pollInterval = options?.pollInterval ?? 5000;
85
+ const maxLogs = options?.maxLogs ?? 500;
86
+ const strategyIds = options?.strategyIds;
87
+ const autoStart = options?.autoStart ?? false;
88
+
89
+ // AI Console Hook
90
+ const aiConsole = useAIQuantConsole({
91
+ simulation,
92
+ pollInterval,
93
+ maxLogs,
94
+ strategyIds,
95
+ });
96
+
97
+ // Forex Hooks
98
+ const forexSim = useForexSimulation({ maxLogs });
99
+ const forexPools = useForexPools({ refreshInterval: pollInterval });
100
+ const forexInvestments = useForexInvestments({ refreshInterval: pollInterval });
101
+
102
+ // Combine logs from both AI and Forex
103
+ const combinedLogs = useMemo((): CombinedLogEntry[] => {
104
+ const combined: CombinedLogEntry[] = [];
105
+
106
+ // Add AI logs
107
+ for (const log of aiConsole.logs) {
108
+ combined.push({
109
+ id: log.id,
110
+ timestamp: log.timestamp,
111
+ source: 'ai',
112
+ strategyId: log.strategyId,
113
+ strategyName: log.strategyName,
114
+ type: log.type,
115
+ message: log.message,
116
+ data: log.data,
117
+ importance: log.importance,
118
+ });
119
+ }
120
+
121
+ // Add Forex logs
122
+ for (const log of forexSim.logs) {
123
+ combined.push({
124
+ id: log.id,
125
+ timestamp: log.timestamp,
126
+ source: 'forex',
127
+ type: log.type,
128
+ message: log.message,
129
+ data: log.data,
130
+ importance: log.importance,
131
+ });
132
+ }
133
+
134
+ // Sort by timestamp descending
135
+ return combined.sort((a, b) => b.timestamp - a.timestamp).slice(0, maxLogs);
136
+ }, [aiConsole.logs, forexSim.logs, maxLogs]);
137
+
138
+ // Combine metrics from AI and Forex
139
+ const combinedMetrics = useMemo((): ConsoleMetrics => {
140
+ const aiMetrics = aiConsole.metrics;
141
+
142
+ // Add forex stats to metrics
143
+ return {
144
+ ...aiMetrics,
145
+ totalPnl: aiMetrics.totalPnl + forexSim.stats.totalPnl,
146
+ totalTrades: aiMetrics.totalTrades + forexSim.stats.totalTrades,
147
+ };
148
+ }, [aiConsole.metrics, forexSim.stats]);
149
+
150
+ // Controls
151
+ const controls = useMemo(() => ({
152
+ startAISimulation: (ids?: string[]) => {
153
+ aiConsole.emitBootSequence();
154
+ setTimeout(() => aiConsole.start(ids), 5500);
155
+ },
156
+ stopAISimulation: (ids?: string[]) => {
157
+ aiConsole.stop(ids);
158
+ },
159
+ startForexSimulation: () => {
160
+ forexSim.start();
161
+ },
162
+ stopForexSimulation: () => {
163
+ forexSim.stop();
164
+ },
165
+ startAll: () => {
166
+ aiConsole.emitBootSequence();
167
+ setTimeout(() => {
168
+ aiConsole.start();
169
+ forexSim.start();
170
+ }, 5500);
171
+ },
172
+ stopAll: () => {
173
+ aiConsole.stop();
174
+ forexSim.stop();
175
+ },
176
+ clearLogs: () => {
177
+ aiConsole.clearLogs();
178
+ forexSim.clearLogs();
179
+ },
180
+ emitBootSequence: () => {
181
+ aiConsole.emitBootSequence();
182
+ },
183
+ refreshAll: async () => {
184
+ await Promise.all([
185
+ aiConsole.refresh(),
186
+ forexPools.refresh(),
187
+ forexInvestments.refresh(),
188
+ ]);
189
+ },
190
+ }), [aiConsole, forexSim, forexPools, forexInvestments]);
191
+
192
+ // State
193
+ const state = useMemo(() => ({
194
+ isAISimulationRunning: aiConsole.isRunning,
195
+ isForexSimulationRunning: forexSim.isRunning,
196
+ isAnyRunning: aiConsole.isRunning || forexSim.isRunning,
197
+ isLoading: aiConsole.isLoading || forexPools.isLoading || forexInvestments.isLoading,
198
+ error: aiConsole.error || forexPools.error || forexInvestments.error,
199
+ }), [aiConsole.isRunning, aiConsole.isLoading, aiConsole.error, forexSim.isRunning, forexPools, forexInvestments]);
200
+
201
+ // Auto-start if configured
202
+ useEffect(() => {
203
+ if (autoStart) {
204
+ controls.startAll();
205
+ }
206
+ }, [autoStart, controls]);
207
+
208
+ return {
209
+ ai: {
210
+ strategies: aiConsole.strategies,
211
+ agents: aiConsole.agents,
212
+ positions: aiConsole.positions,
213
+ decisions: aiConsole.decisions,
214
+ riskStatus: aiConsole.riskStatus,
215
+ simulationLogs: aiConsole.logs,
216
+ logsByStrategy: aiConsole.logsByStrategy,
217
+ botStates: aiConsole.botStates,
218
+ },
219
+ forex: {
220
+ logs: forexSim.logs,
221
+ poolTransactions: forexSim.poolTransactions,
222
+ pools: forexPools.pools,
223
+ investments: forexInvestments.investments,
224
+ stats: forexSim.stats,
225
+ },
226
+ combinedLogs,
227
+ metrics: combinedMetrics,
228
+ controls,
229
+ state,
230
+ getAgent: aiConsole.getAgent,
231
+ getAgentLogs: aiConsole.getAgentLogs,
232
+ getAgentPositions: aiConsole.getAgentPositions,
233
+ getAgentDecisions: aiConsole.getAgentDecisions,
234
+ };
235
+ }
236
+
237
+ // ── Convenience Exports ───────────────────────────────────────────────────────
238
+
239
+ export { useAIQuantConsole } from './useAIQuantConsole';
240
+ export { useBotSimulation } from './useBotSimulation';
241
+ export { useAIPositions, setConsoleAccessToken, clearConsoleAccessToken, setConsoleEngineUrl } from './useAIPositions';
242
+ export { useAIDecisions } from './useAIDecisions';
243
+ export { useAIRiskStatus } from './useAIRiskStatus';