@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
@@ -0,0 +1,482 @@
1
+ // ForexSimulationEngine.ts - StableFX RFQ+PvP on-chain forex simulation engine
2
+ // Simulates Circle StableFX-style foreign exchange operations using USDC stablecoin pairs
3
+
4
+ import type {
5
+ ForexLogEntry,
6
+ ForexLogType,
7
+ ForexCurrencyPair,
8
+ ForexTradeRecord,
9
+ ForexPosition,
10
+ ForexPoolTransaction,
11
+ } from '../../types/forex';
12
+ import { FOREX_CURRENCY_PAIRS } from '../../types/forex';
13
+
14
+ // ── Types ──────────────────────────────────────────────────────────────────────
15
+
16
+ type LogCallback = (entry: ForexLogEntry) => void;
17
+ type PoolTxCallback = (tx: ForexPoolTransaction) => void;
18
+
19
+ interface PairState {
20
+ pair: ForexCurrencyPair;
21
+ currentPrice: number;
22
+ bidPrice: number;
23
+ askPrice: number;
24
+ lastSpread: number;
25
+ }
26
+
27
+ // ── Helpers ────────────────────────────────────────────────────────────────────
28
+
29
+ let idCounter = 0;
30
+ function genId(): string {
31
+ return `fxlog_${Date.now()}_${++idCounter}`;
32
+ }
33
+
34
+ function tradeId(): string {
35
+ return `FXT_${Date.now().toString(36).toUpperCase()}_${(++idCounter).toString(36).toUpperCase()}`;
36
+ }
37
+
38
+ function rand(min: number, max: number): number {
39
+ return min + Math.random() * (max - min);
40
+ }
41
+
42
+ function randInt(min: number, max: number): number {
43
+ return Math.floor(rand(min, max + 1));
44
+ }
45
+
46
+ function pick<T>(arr: T[]): T {
47
+ return arr[Math.floor(Math.random() * arr.length)];
48
+ }
49
+
50
+ function formatRate(price: number, pair: ForexCurrencyPair): string {
51
+ if (pair.pipSize >= 0.01) return price.toFixed(3);
52
+ return price.toFixed(5);
53
+ }
54
+
55
+ // ── News Headlines ───────────────────────────────────────────────────────────
56
+
57
+ const FX_NEWS = [
58
+ 'ECB signals potential rate adjustment, EUR pairs volatile',
59
+ 'BOJ maintains yield curve control, JPY weakens further',
60
+ 'Fed minutes reveal hawkish sentiment, USD strengthens',
61
+ 'UK CPI data beats expectations, GBP rallies',
62
+ 'RBA holds rates steady, AUD consolidates',
63
+ 'SNB intervenes in currency markets, CHF stabilizes',
64
+ 'Bank of Canada rate decision pending, CAD in focus',
65
+ 'Cross-border stablecoin settlement volume hits $2.1B daily',
66
+ 'Circle USDC reserves fully backed, attestation report released',
67
+ 'DeFi forex protocol TVL reaches new high at $890M',
68
+ 'On-chain FX liquidity deepens across major pairs',
69
+ 'Institutional adoption of on-chain forex accelerates',
70
+ ];
71
+
72
+ // ── Engine ─────────────────────────────────────────────────────────────────────
73
+
74
+ class ForexSimulationEngine {
75
+ private listeners: LogCallback[] = [];
76
+ private poolTxListeners: PoolTxCallback[] = [];
77
+ private cycleTimer: ReturnType<typeof setTimeout> | null = null;
78
+ private pairStates: Map<string, PairState> = new Map();
79
+ private running = false;
80
+ private openPositions: ForexPosition[] = [];
81
+ private totalPnl = 0;
82
+ private totalTrades = 0;
83
+ private totalPips = 0;
84
+ private totalLots = 0;
85
+
86
+ constructor() {
87
+ for (const pair of FOREX_CURRENCY_PAIRS) {
88
+ const jitter = pair.basePrice * rand(-0.003, 0.003);
89
+ const price = pair.basePrice + jitter;
90
+ const halfSpread = pair.spreadPips * pair.pipSize / 2;
91
+ this.pairStates.set(pair.id, {
92
+ pair,
93
+ currentPrice: price,
94
+ bidPrice: price - halfSpread,
95
+ askPrice: price + halfSpread,
96
+ lastSpread: pair.spreadPips,
97
+ });
98
+ }
99
+ }
100
+
101
+ // ── Public API ─────────────────────────────────────────────────────────────
102
+
103
+ start(): void {
104
+ this.running = true;
105
+ this.scheduleCycle();
106
+ }
107
+
108
+ stop(): void {
109
+ this.running = false;
110
+ if (this.cycleTimer) {
111
+ clearTimeout(this.cycleTimer);
112
+ this.cycleTimer = null;
113
+ }
114
+ }
115
+
116
+ onLog(callback: LogCallback): () => void {
117
+ this.listeners.push(callback);
118
+ return () => {
119
+ this.listeners = this.listeners.filter(l => l !== callback);
120
+ };
121
+ }
122
+
123
+ onPoolTransaction(callback: PoolTxCallback): () => void {
124
+ this.poolTxListeners.push(callback);
125
+ return () => {
126
+ this.poolTxListeners = this.poolTxListeners.filter(l => l !== callback);
127
+ };
128
+ }
129
+
130
+ isRunning(): boolean {
131
+ return this.running;
132
+ }
133
+
134
+ getStats(): { totalPnl: number; totalTrades: number; totalPips: number; totalLots: number; positions: number } {
135
+ return {
136
+ totalPnl: this.totalPnl,
137
+ totalTrades: this.totalTrades,
138
+ totalPips: this.totalPips,
139
+ totalLots: this.totalLots,
140
+ positions: this.openPositions.length,
141
+ };
142
+ }
143
+
144
+ getPairStates(): Map<string, PairState> {
145
+ return this.pairStates;
146
+ }
147
+
148
+ emitBootSequence(): void {
149
+ const bootMessages: Array<{ msg: string; delay: number }> = [
150
+ { msg: 'Initializing StableFX Engine v2.1.0...', delay: 0 },
151
+ { msg: 'Connecting to Circle StableFX RFQ network...', delay: 500 },
152
+ { msg: 'Loading USDC stablecoin pair feeds (6 pairs)...', delay: 1200 },
153
+ { msg: 'Calibrating PvP settlement engine...', delay: 2000 },
154
+ { msg: 'Initializing clearing pool ($12.5M)...', delay: 2800 },
155
+ { msg: 'Initializing hedging pool ($7.5M)...', delay: 3400 },
156
+ { msg: 'Initializing insurance pool ($5.0M)...', delay: 4000 },
157
+ { msg: 'Risk management module online (max exposure: 25%)', delay: 4500 },
158
+ { msg: '=== StableFX Engine ready. Starting RFQ cycles ===', delay: 5000 },
159
+ ];
160
+
161
+ for (const { msg, delay } of bootMessages) {
162
+ setTimeout(() => {
163
+ this.emit({
164
+ id: genId(),
165
+ timestamp: Date.now(),
166
+ type: 'SYSTEM',
167
+ message: msg,
168
+ importance: 'medium',
169
+ });
170
+ }, delay);
171
+ }
172
+ }
173
+
174
+ destroy(): void {
175
+ this.stop();
176
+ this.listeners = [];
177
+ this.poolTxListeners = [];
178
+ this.pairStates.clear();
179
+ this.openPositions = [];
180
+ }
181
+
182
+ // ── Private Methods ────────────────────────────────────────────────────────
183
+
184
+ private emit(entry: ForexLogEntry): void {
185
+ for (const listener of this.listeners) {
186
+ listener(entry);
187
+ }
188
+ }
189
+
190
+ private emitPoolTx(tx: ForexPoolTransaction): void {
191
+ for (const listener of this.poolTxListeners) {
192
+ listener(tx);
193
+ }
194
+ }
195
+
196
+ private generatePoolTxFromEvent(
197
+ type: 'SETTLE' | 'HEDGE' | 'CLEAR',
198
+ data: { pnl?: number; volume?: number; lots?: number },
199
+ ): void {
200
+ try {
201
+ const { ForexPoolDataGenerator } = require('./ForexPoolDataGenerator');
202
+ const generator = ForexPoolDataGenerator.getInstance();
203
+
204
+ if (type === 'SETTLE' && data.pnl !== undefined) {
205
+ const tx = generator.generateLiveTransaction('clearing', 'fee_collection', Math.abs(data.pnl) * rand(0.001, 0.003));
206
+ this.emitPoolTx(tx);
207
+ } else if (type === 'HEDGE') {
208
+ const tx = generator.generateLiveTransaction('hedging', data.pnl && data.pnl < 0 ? 'loss_absorption' : 'profit_distribution', Math.abs(data.lots || 1) * rand(50, 200));
209
+ this.emitPoolTx(tx);
210
+ } else if (type === 'CLEAR') {
211
+ const tx = generator.generateLiveTransaction('clearing', 'profit_distribution', (data.volume || 100000) * rand(0.0001, 0.0005));
212
+ this.emitPoolTx(tx);
213
+ }
214
+ } catch {
215
+ // Generator not available
216
+ }
217
+ }
218
+
219
+ private scheduleCycle(): void {
220
+ if (!this.running) return;
221
+ const interval = rand(8000, 14000);
222
+ this.cycleTimer = setTimeout(() => {
223
+ if (this.running) {
224
+ this.runTradeCycle();
225
+ this.scheduleCycle();
226
+ }
227
+ }, interval);
228
+ }
229
+
230
+ private simulatePrice(pairId: string): number {
231
+ const state = this.pairStates.get(pairId);
232
+ if (!state) return 0;
233
+ const volatility = state.pair.id.includes('JPYC') ? 0.0008 : 0.0004;
234
+ const drift = rand(-volatility, volatility);
235
+ const newPrice = state.currentPrice * (1 + drift);
236
+ const halfSpread = (state.pair.spreadPips + rand(-0.3, 0.3)) * state.pair.pipSize / 2;
237
+ state.currentPrice = newPrice;
238
+ state.bidPrice = newPrice - halfSpread;
239
+ state.askPrice = newPrice + halfSpread;
240
+ state.lastSpread = halfSpread * 2 / state.pair.pipSize;
241
+ return newPrice;
242
+ }
243
+
244
+ private runTradeCycle(): void {
245
+ const pairState = pick(Array.from(this.pairStates.values()));
246
+ const pair = pairState.pair;
247
+ const entries: Array<{ entry: Omit<ForexLogEntry, 'id' | 'timestamp'>; delay: number }> = [];
248
+ let delay = 0;
249
+
250
+ // Update price
251
+ const price = this.simulatePrice(pair.id);
252
+
253
+ // 1. RFQ - Request for Quote
254
+ const side = Math.random() > 0.5 ? 'BUY' : 'SELL';
255
+ const lots = parseFloat((rand(0.1, 2.5)).toFixed(2));
256
+ const notional = lots * 100000;
257
+ const rfqId = tradeId();
258
+
259
+ entries.push({
260
+ entry: {
261
+ type: 'RFQ',
262
+ message: `RFQ ${rfqId} | ${pair.symbol} ${side} ${lots.toFixed(2)} lots ($${(notional / 1000).toFixed(0)}K) | Mid: ${formatRate(price, pair)}`,
263
+ data: { rfqId, pair: pair.id, side, lots, price },
264
+ importance: 'medium',
265
+ pairId: pair.id,
266
+ },
267
+ delay,
268
+ });
269
+ delay += rand(400, 800);
270
+
271
+ // 2. QUOTE - Price quote from LP
272
+ const quoteSpread = rand(0.5, 2.0) * pair.pipSize;
273
+ const quotePrice = side === 'BUY'
274
+ ? price + quoteSpread
275
+ : price - quoteSpread;
276
+ const quotePips = Math.abs(quotePrice - price) / pair.pipSize;
277
+
278
+ entries.push({
279
+ entry: {
280
+ type: 'QUOTE',
281
+ message: `QUOTE ${rfqId} | ${pair.symbol} @ ${formatRate(quotePrice, pair)} | Spread: ${quotePips.toFixed(1)} pips | Valid: 3s`,
282
+ data: { rfqId, quotePrice, spread: quotePips },
283
+ importance: 'medium',
284
+ pairId: pair.id,
285
+ },
286
+ delay,
287
+ });
288
+ delay += rand(500, 1000);
289
+
290
+ // 3. MATCH - Trade matching (85% success rate)
291
+ const matched = Math.random() < 0.85;
292
+ if (matched) {
293
+ const matchPrice = quotePrice * (1 + rand(-0.00005, 0.00005));
294
+ entries.push({
295
+ entry: {
296
+ type: 'MATCH',
297
+ message: `MATCH ${rfqId} | ${pair.symbol} ${side} @ ${formatRate(matchPrice, pair)} | ${lots.toFixed(2)} lots | Counterparty: LP-${randInt(1, 8)}`,
298
+ data: { rfqId, matchPrice, counterparty: `LP-${randInt(1, 8)}` },
299
+ importance: 'high',
300
+ pairId: pair.id,
301
+ },
302
+ delay,
303
+ });
304
+ delay += rand(1000, 2500);
305
+
306
+ // 4. SETTLE - PvP Settlement
307
+ const settlePrice = matchPrice * (1 + rand(-0.00002, 0.00002));
308
+ const pips = ((settlePrice - price) / pair.pipSize) * (side === 'BUY' ? 1 : -1);
309
+ const pnl = pips * pair.pipSize * lots * 100000;
310
+
311
+ entries.push({
312
+ entry: {
313
+ type: 'SETTLE',
314
+ message: `SETTLE ${rfqId} | PvP confirmed | ${pair.symbol} @ ${formatRate(settlePrice, pair)} | P&L: ${pips >= 0 ? '+' : ''}${pips.toFixed(1)} pips ($${pnl >= 0 ? '+' : ''}${pnl.toFixed(2)})`,
315
+ data: { rfqId, settlePrice, pips, pnl, pvp: true },
316
+ importance: 'high',
317
+ pairId: pair.id,
318
+ },
319
+ delay,
320
+ });
321
+ delay += rand(300, 600);
322
+
323
+ // 5. PVP - Settlement confirmation
324
+ entries.push({
325
+ entry: {
326
+ type: 'PVP',
327
+ message: `PvP ${rfqId} | Atomic settlement confirmed on-chain | USDC transferred: $${notional.toLocaleString()} | Gas: ~$0.${randInt(10, 50)}`,
328
+ data: { rfqId, settled: true, gasWei: randInt(10, 50) },
329
+ importance: 'medium',
330
+ pairId: pair.id,
331
+ },
332
+ delay,
333
+ });
334
+
335
+ // Generate pool transaction for settlement
336
+ this.generatePoolTxFromEvent('SETTLE', { pnl });
337
+
338
+ // Update stats
339
+ this.totalTrades++;
340
+ this.totalPnl += pnl;
341
+ this.totalPips += pips;
342
+ this.totalLots += lots;
343
+
344
+ // Update positions
345
+ if (Math.random() < 0.4) {
346
+ this.openPositions.push({
347
+ id: rfqId,
348
+ pairId: pair.id,
349
+ side: side as 'BUY' | 'SELL',
350
+ lots,
351
+ pips,
352
+ entryPrice: matchPrice,
353
+ currentPrice: settlePrice,
354
+ pnl,
355
+ openTime: Date.now(),
356
+ });
357
+ if (this.openPositions.length > 5) {
358
+ this.openPositions.shift();
359
+ }
360
+ }
361
+ } else {
362
+ entries.push({
363
+ entry: {
364
+ type: 'MATCH',
365
+ message: `MATCH FAILED ${rfqId} | ${pair.symbol} | No counterparty at requested price | Requoting...`,
366
+ data: { rfqId, matched: false },
367
+ importance: 'low',
368
+ pairId: pair.id,
369
+ },
370
+ delay,
371
+ });
372
+ }
373
+
374
+ // 6. HEDGE - Pool hedging operations (20% chance)
375
+ if (Math.random() < 0.2) {
376
+ delay += rand(400, 800);
377
+ const hedgePair = pick(FOREX_CURRENCY_PAIRS);
378
+ const hedgeLots = parseFloat(rand(0.5, 5.0).toFixed(2));
379
+ const hedgeDirection = Math.random() > 0.5 ? 'LONG' : 'SHORT';
380
+ entries.push({
381
+ entry: {
382
+ type: 'HEDGE',
383
+ message: `HEDGE | ${hedgePair.symbol} ${hedgeDirection} ${hedgeLots.toFixed(2)} lots | Pool delta neutralization | Exposure: ${rand(5, 20).toFixed(1)}%`,
384
+ data: { pair: hedgePair.id, direction: hedgeDirection, lots: hedgeLots },
385
+ importance: 'medium',
386
+ },
387
+ delay,
388
+ });
389
+ this.generatePoolTxFromEvent('HEDGE', { lots: hedgeLots });
390
+ }
391
+
392
+ // 7. CLEAR - Clearing pool operations (15% chance)
393
+ if (Math.random() < 0.15) {
394
+ delay += rand(300, 600);
395
+ const clearAmount = randInt(50000, 500000);
396
+ entries.push({
397
+ entry: {
398
+ type: 'CLEAR',
399
+ message: `CLEAR | Netting cycle complete | Volume: $${(clearAmount / 1000).toFixed(0)}K | Pairs settled: ${randInt(2, 6)} | Pool util: ${rand(60, 85).toFixed(1)}%`,
400
+ data: { volume: clearAmount, pairsSettled: randInt(2, 6) },
401
+ importance: 'low',
402
+ },
403
+ delay,
404
+ });
405
+ this.generatePoolTxFromEvent('CLEAR', { volume: clearAmount });
406
+ }
407
+
408
+ // 8. POSITION - Position update (25% chance)
409
+ if (this.openPositions.length > 0 && Math.random() < 0.25) {
410
+ delay += rand(300, 600);
411
+ const posUpdates = this.openPositions.slice(0, 3).map(pos => {
412
+ const pState = this.pairStates.get(pos.pairId);
413
+ if (pState) {
414
+ pos.currentPrice = pState.currentPrice;
415
+ pos.pips = ((pos.currentPrice - pos.entryPrice) / pState.pair.pipSize) * (pos.side === 'BUY' ? 1 : -1);
416
+ pos.pnl = pos.pips * pState.pair.pipSize * pos.lots * 100000;
417
+ }
418
+ return `${pState?.pair.symbol || pos.pairId} ${pos.side}: ${pos.pips >= 0 ? '+' : ''}${pos.pips.toFixed(1)} pips`;
419
+ });
420
+ entries.push({
421
+ entry: {
422
+ type: 'POSITION',
423
+ message: `POSITION | ${posUpdates.join(' | ')} | Open: ${this.openPositions.length}`,
424
+ data: { positions: this.openPositions.length },
425
+ importance: 'low',
426
+ },
427
+ delay,
428
+ });
429
+
430
+ // Close old positions
431
+ if (this.openPositions.length > 2 && Math.random() < 0.3) {
432
+ const closed = this.openPositions.shift()!;
433
+ this.totalPnl += closed.pnl * rand(0.01, 0.03);
434
+ }
435
+ }
436
+
437
+ // 9. PNL - Periodic P&L summary (30% chance)
438
+ if (Math.random() < 0.3) {
439
+ delay += rand(300, 600);
440
+ entries.push({
441
+ entry: {
442
+ type: 'PNL',
443
+ message: `PNL | Session: $${this.totalPnl >= 0 ? '+' : ''}${this.totalPnl.toFixed(2)} | Trades: ${this.totalTrades} | Pips: ${this.totalPips >= 0 ? '+' : ''}${this.totalPips.toFixed(1)} | Lots: ${this.totalLots.toFixed(2)}`,
444
+ data: { totalPnl: this.totalPnl, totalTrades: this.totalTrades, totalPips: this.totalPips },
445
+ importance: 'medium',
446
+ },
447
+ delay,
448
+ });
449
+ }
450
+
451
+ // 10. NEWS (10% chance)
452
+ if (Math.random() < 0.1) {
453
+ delay += rand(300, 600);
454
+ entries.push({
455
+ entry: {
456
+ type: 'SYSTEM',
457
+ message: `[Market] ${pick(FX_NEWS)}`,
458
+ importance: 'medium',
459
+ },
460
+ delay,
461
+ });
462
+ }
463
+
464
+ // Emit all entries with delays
465
+ for (const { entry, delay: d } of entries) {
466
+ setTimeout(() => {
467
+ if (this.running) {
468
+ this.emit({
469
+ ...entry,
470
+ id: genId(),
471
+ timestamp: Date.now(),
472
+ });
473
+ }
474
+ }, d);
475
+ }
476
+ }
477
+ }
478
+
479
+ // ── Singleton Export ──────────────────────────────────────────────────────────
480
+
481
+ export const forexSimulationEngine = new ForexSimulationEngine();
482
+ export type { PairState };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * ONE SDK - Forex Trading Services
3
+ * Simulation engines and data generators for StableFX on-chain forex
4
+ */
5
+
6
+ // Forex RFQ+PvP Simulation Engine
7
+ export { forexSimulationEngine } from './ForexSimulationEngine';
8
+ export type { PairState } from './ForexSimulationEngine';
9
+
10
+ // Pool Data Generator (historical snapshots & transactions)
11
+ export { ForexPoolDataGenerator } from './ForexPoolDataGenerator';
12
+
13
+ // Bot Simulation Engine (AI crypto trading strategies)
14
+ export { botSimulationEngine, STRATEGY_PERSONALITIES } from './BotSimulationEngine';
15
+ export type {
16
+ BotLogType,
17
+ BotLogEntry,
18
+ IndicatorSnapshot,
19
+ BotState,
20
+ StrategyPersonality,
21
+ } from './BotSimulationEngine';
@@ -44,3 +44,19 @@ export type {
44
44
  UsageActivity,
45
45
  UsageResponse,
46
46
  } from './usage';
47
+
48
+ // ===== Forex Trading Services =====
49
+ export {
50
+ forexSimulationEngine,
51
+ ForexPoolDataGenerator,
52
+ botSimulationEngine,
53
+ STRATEGY_PERSONALITIES,
54
+ } from './forex';
55
+ export type {
56
+ PairState,
57
+ BotLogType,
58
+ BotLogEntry,
59
+ IndicatorSnapshot,
60
+ BotState,
61
+ StrategyPersonality,
62
+ } from './forex';
@@ -0,0 +1,151 @@
1
+ // ══════════════════════════════════════════════════════════════════════════════
2
+ // ONE SDK - AI Trading Types & Constants
3
+ // Shared types for AI-powered crypto trading strategies
4
+ // ══════════════════════════════════════════════════════════════════════════════
5
+
6
+ export type StrategyCategory = 'conservative' | 'balanced' | 'aggressive' | 'hedge' | 'arbitrage' | 'trend' | 'grid' | 'dca';
7
+ export type OrderStatus = 'pending' | 'active' | 'paused' | 'completed' | 'cancelled' | 'pending_redemption' | 'redeemed';
8
+ export type TradeAction = 'buy' | 'sell' | 'long' | 'short' | 'close_long' | 'close_short';
9
+ export type TradeStatus = 'open' | 'closed' | 'liquidated' | 'cancelled';
10
+ export type FeeType = 'management' | 'performance' | 'withdrawal' | 'early_redemption_penalty';
11
+ export type OrderEventType = 'created' | 'activated' | 'paused' | 'resumed' | 'redemption_requested' | 'redeemed' | 'cancelled' | 'fee_deducted' | 'profit_realized';
12
+
13
+ export interface AIStrategyConfig {
14
+ id: string;
15
+ name: string;
16
+ description: string | null;
17
+ category: StrategyCategory;
18
+ riskLevel: 1 | 2 | 3 | 4 | 5;
19
+ minInvestment: number;
20
+ maxInvestment: number | null;
21
+ lockPeriodDays: number;
22
+ expectedApyMin: number | null;
23
+ expectedApyMax: number | null;
24
+ managementFeeRate: number;
25
+ performanceFeeRate: number;
26
+ supportedPairs: string[];
27
+ supportedChains: string[];
28
+ supportedCurrencies: string[];
29
+ leverageMin: number;
30
+ leverageMax: number;
31
+ isActive: boolean;
32
+ }
33
+
34
+ export interface AIOrderCreateInput {
35
+ strategyId: string;
36
+ amount: number;
37
+ currency: string;
38
+ chain: string;
39
+ lockPeriodDays: number;
40
+ }
41
+
42
+ export interface AIOrderSummary {
43
+ orderId: string;
44
+ strategyId: string;
45
+ strategyName: string;
46
+ amount: number;
47
+ currentValue: number;
48
+ profit: number;
49
+ profitPercent: number;
50
+ status: OrderStatus;
51
+ daysRemaining: number;
52
+ lockProgress: number;
53
+ }
54
+
55
+ export interface AIPortfolioSummary {
56
+ totalInvested: number;
57
+ totalValue: number;
58
+ totalProfit: number;
59
+ totalProfitPercent: number;
60
+ activeOrders: number;
61
+ totalTrades: number;
62
+ profitToday: number;
63
+ profit7d: number;
64
+ profit30d: number;
65
+ }
66
+
67
+ export interface AITradeLog {
68
+ id: string;
69
+ timestamp: string;
70
+ action: TradeAction;
71
+ pair: string;
72
+ entryPrice: number;
73
+ exitPrice: number | null;
74
+ amount: number;
75
+ pnl: number;
76
+ pnlPercent: number;
77
+ leverage: number;
78
+ status: TradeStatus;
79
+ aiConfidence: number | null;
80
+ aiReasoning: string | null;
81
+ }
82
+
83
+ export interface AIPenaltyCalculation {
84
+ completionRate: number;
85
+ penaltyRate: number;
86
+ estimatedPenalty: number;
87
+ estimatedRedemption: number;
88
+ isEarlyWithdrawal: boolean;
89
+ }
90
+
91
+ export interface AIPerformanceChart {
92
+ date: string;
93
+ nav: number;
94
+ dailyPnl: number;
95
+ cumulativePnl: number;
96
+ }
97
+
98
+ export const PENALTY_TIERS = [
99
+ { minProgress: 0.75, maxProgress: 1.0, rate: 0.50, label: '50%' },
100
+ { minProgress: 0.50, maxProgress: 0.75, rate: 0.60, label: '60%' },
101
+ { minProgress: 0.25, maxProgress: 0.50, rate: 0.70, label: '70%' },
102
+ { minProgress: 0.00, maxProgress: 0.25, rate: 0.80, label: '80%' },
103
+ ] as const;
104
+
105
+ export function calculateEarlyWithdrawalPenalty(
106
+ investedAmount: number,
107
+ profit: number,
108
+ lockProgress: number,
109
+ ): AIPenaltyCalculation {
110
+ const totalValue = investedAmount + profit;
111
+ const isEarlyWithdrawal = lockProgress < 1.0;
112
+ let penaltyRate = 0;
113
+ if (isEarlyWithdrawal) {
114
+ if (lockProgress >= 0.75) penaltyRate = 0.50;
115
+ else if (lockProgress >= 0.50) penaltyRate = 0.60;
116
+ else if (lockProgress >= 0.25) penaltyRate = 0.70;
117
+ else penaltyRate = 0.80;
118
+ }
119
+ const estimatedPenalty = totalValue * penaltyRate;
120
+ const estimatedRedemption = totalValue - estimatedPenalty;
121
+ return { completionRate: lockProgress, penaltyRate, estimatedPenalty, estimatedRedemption, isEarlyWithdrawal };
122
+ }
123
+
124
+ export const STRATEGY_CATEGORIES: Record<StrategyCategory, { labelKey: string; color: string; icon: string }> = {
125
+ conservative: { labelKey: 'ai.category_conservative', color: '#10B981', icon: '\u{1F6E1}\u{FE0F}' },
126
+ balanced: { labelKey: 'ai.category_balanced', color: '#3B82F6', icon: '\u{2696}\u{FE0F}' },
127
+ aggressive: { labelKey: 'ai.category_aggressive', color: '#EF4444', icon: '\u{1F680}' },
128
+ hedge: { labelKey: 'ai.category_hedge', color: '#8B5CF6', icon: '\u{1F512}' },
129
+ arbitrage: { labelKey: 'ai.category_arbitrage', color: '#F59E0B', icon: '\u{26A1}' },
130
+ trend: { labelKey: 'ai.category_trend', color: '#EC4899', icon: '\u{1F4C8}' },
131
+ grid: { labelKey: 'ai.category_grid', color: '#6366F1', icon: '\u{25A6}' },
132
+ dca: { labelKey: 'ai.category_dca', color: '#14B8A6', icon: '\u{1F4CA}' },
133
+ };
134
+
135
+ export const RISK_LEVELS: Record<number, { labelKey: string; color: string; bgColor: string }> = {
136
+ 1: { labelKey: 'ai.risk_very_low', color: '#10B981', bgColor: '#D1FAE5' },
137
+ 2: { labelKey: 'ai.risk_low', color: '#22C55E', bgColor: '#DCFCE7' },
138
+ 3: { labelKey: 'ai.risk_medium', color: '#F59E0B', bgColor: '#FEF3C7' },
139
+ 4: { labelKey: 'ai.risk_high', color: '#F97316', bgColor: '#FFEDD5' },
140
+ 5: { labelKey: 'ai.risk_very_high', color: '#EF4444', bgColor: '#FEE2E2' },
141
+ };
142
+
143
+ export const ORDER_STATUS_CONFIG: Record<OrderStatus, { labelKey: string; color: string; bgColor: string }> = {
144
+ pending: { labelKey: 'ai.status_pending', color: '#F59E0B', bgColor: '#FEF3C7' },
145
+ active: { labelKey: 'ai.status_active', color: '#10B981', bgColor: '#D1FAE5' },
146
+ paused: { labelKey: 'ai.status_paused', color: '#6B7280', bgColor: '#F3F4F6' },
147
+ completed: { labelKey: 'ai.status_completed', color: '#3B82F6', bgColor: '#DBEAFE' },
148
+ cancelled: { labelKey: 'ai.status_cancelled', color: '#EF4444', bgColor: '#FEE2E2' },
149
+ pending_redemption: { labelKey: 'ai.status_pending_redemption', color: '#8B5CF6', bgColor: '#EDE9FE' },
150
+ redeemed: { labelKey: 'ai.status_redeemed', color: '#14B8A6', bgColor: '#CCFBF1' },
151
+ };