@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,8 +1,932 @@
1
1
  'use strict';
2
2
 
3
- var react = require('react');
4
3
  var reactNative = require('react-native');
5
4
  var jsxRuntime = require('react/jsx-runtime');
5
+ var react = require('react');
6
+
7
+ var __defProp = Object.defineProperty;
8
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
9
+ var __getOwnPropNames = Object.getOwnPropertyNames;
10
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
11
+ var __esm = (fn, res) => function __init() {
12
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
13
+ };
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") {
20
+ for (let key of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key) && key !== except)
22
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
+ }
24
+ return to;
25
+ };
26
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
+
28
+ // src/types/forex.ts
29
+ var forex_exports = {};
30
+ __export(forex_exports, {
31
+ FOREX_AGENT: () => exports.FOREX_AGENT,
32
+ FOREX_CAPITAL_SPLIT: () => exports.FOREX_CAPITAL_SPLIT,
33
+ FOREX_CURRENCY_PAIRS: () => exports.FOREX_CURRENCY_PAIRS,
34
+ FOREX_CYCLE_OPTIONS: () => exports.FOREX_CYCLE_OPTIONS,
35
+ FOREX_POOL_DEFAULTS: () => exports.FOREX_POOL_DEFAULTS,
36
+ calculateForexNetProfit: () => calculateForexNetProfit,
37
+ computePoolAllocations: () => computePoolAllocations,
38
+ estimateForexProfit: () => estimateForexProfit
39
+ });
40
+ function computePoolAllocations(amount) {
41
+ const totalPoolReserves = amount * exports.FOREX_CAPITAL_SPLIT.poolReserves;
42
+ const tradingCapital = amount * exports.FOREX_CAPITAL_SPLIT.tradingCapital;
43
+ return {
44
+ tradingCapital,
45
+ totalPoolReserves,
46
+ clearing: totalPoolReserves * 0.5,
47
+ hedging: totalPoolReserves * 0.3,
48
+ insurance: totalPoolReserves * 0.2
49
+ };
50
+ }
51
+ function calculateForexNetProfit(grossProfit, cycleOption) {
52
+ const feeAmount = grossProfit * cycleOption.feeRate;
53
+ const postFeeProfit = grossProfit - feeAmount;
54
+ const netProfit = postFeeProfit * cycleOption.commissionRate;
55
+ return { feeAmount, postFeeProfit, netProfit };
56
+ }
57
+ function estimateForexProfit(amount, cycleDays, agent = exports.FOREX_AGENT) {
58
+ const cycleOption = exports.FOREX_CYCLE_OPTIONS.find((c) => c.days === cycleDays) || exports.FOREX_CYCLE_OPTIONS[0];
59
+ const estimatedApy = (agent.dailyRoiMin + agent.dailyRoiMax) / 2 * 365 * 100;
60
+ const dailyRate = estimatedApy / 100 / 365;
61
+ const grossProfit = amount * dailyRate * cycleDays;
62
+ const { feeAmount, netProfit } = calculateForexNetProfit(grossProfit, cycleOption);
63
+ return { grossProfit, feeAmount, netProfit, dailyRate };
64
+ }
65
+ exports.FOREX_CAPITAL_SPLIT = void 0; exports.FOREX_CYCLE_OPTIONS = void 0; exports.FOREX_CURRENCY_PAIRS = void 0; exports.FOREX_POOL_DEFAULTS = void 0; exports.FOREX_AGENT = void 0;
66
+ var init_forex = __esm({
67
+ "src/types/forex.ts"() {
68
+ exports.FOREX_CAPITAL_SPLIT = {
69
+ poolReserves: 0.5,
70
+ tradingCapital: 0.5
71
+ };
72
+ exports.FOREX_CYCLE_OPTIONS = [
73
+ { days: 30, feeRate: 0.1, commissionRate: 0.6, label: "30D" },
74
+ { days: 60, feeRate: 0.08, commissionRate: 0.7, label: "60D" },
75
+ { days: 90, feeRate: 0.07, commissionRate: 0.75, label: "90D" },
76
+ { days: 180, feeRate: 0.05, commissionRate: 0.85, label: "180D" },
77
+ { days: 360, feeRate: 0.03, commissionRate: 0.9, label: "360D" }
78
+ ];
79
+ exports.FOREX_CURRENCY_PAIRS = [
80
+ { id: "USDC_EURC", base: "USDC", quote: "EURC", symbol: "USDC/EURC", flag: "\u{1F1EA}\u{1F1FA}", name: "Euro", basePrice: 0.923, pipSize: 1e-4, spreadPips: 1.2 },
81
+ { id: "USDC_GBPC", base: "USDC", quote: "GBPC", symbol: "USDC/GBPC", flag: "\u{1F1EC}\u{1F1E7}", name: "British Pound", basePrice: 0.789, pipSize: 1e-4, spreadPips: 1.5 },
82
+ { id: "USDC_JPYC", base: "USDC", quote: "JPYC", symbol: "USDC/JPYC", flag: "\u{1F1EF}\u{1F1F5}", name: "Japanese Yen", basePrice: 154.5, pipSize: 0.01, spreadPips: 1 },
83
+ { id: "USDC_AUDC", base: "USDC", quote: "AUDC", symbol: "USDC/AUDC", flag: "\u{1F1E6}\u{1F1FA}", name: "Australian Dollar", basePrice: 1.538, pipSize: 1e-4, spreadPips: 1.8 },
84
+ { id: "USDC_CADC", base: "USDC", quote: "CADC", symbol: "USDC/CADC", flag: "\u{1F1E8}\u{1F1E6}", name: "Canadian Dollar", basePrice: 1.364, pipSize: 1e-4, spreadPips: 1.5 },
85
+ { id: "USDC_CHFC", base: "USDC", quote: "CHFC", symbol: "USDC/CHFC", flag: "\u{1F1E8}\u{1F1ED}", name: "Swiss Franc", basePrice: 0.875, pipSize: 1e-4, spreadPips: 1.3 }
86
+ ];
87
+ exports.FOREX_POOL_DEFAULTS = [
88
+ { id: "clearing", nameKey: "forex.pool_clearing", descriptionKey: "forex.pool_clearing_desc", allocation: 0.5, totalSize: 125e5, utilization: 0.78, color: "#3B82F6", apy7d: 12.8, apy30d: 11.5, netFlow24h: 185e3, txCount24h: 42, txCountTotal: 12840, totalDeposits: 452e5, totalWithdrawals: 327e5, profitDistributed: 185e4, lastUpdated: Date.now() },
89
+ { id: "hedging", nameKey: "forex.pool_hedging", descriptionKey: "forex.pool_hedging_desc", allocation: 0.3, totalSize: 75e5, utilization: 0.65, color: "#F59E0B", apy7d: 8.1, apy30d: 7.6, netFlow24h: 72e3, txCount24h: 24, txCountTotal: 7620, totalDeposits: 285e5, totalWithdrawals: 21e6, profitDistributed: 98e4, lastUpdated: Date.now() },
90
+ { id: "insurance", nameKey: "forex.pool_insurance", descriptionKey: "forex.pool_insurance_desc", allocation: 0.2, totalSize: 5e6, utilization: 0.42, color: "#10B981", apy7d: 4.8, apy30d: 4.5, netFlow24h: 35e3, txCount24h: 14, txCountTotal: 4280, totalDeposits: 158e5, totalWithdrawals: 108e5, profitDistributed: 52e4, lastUpdated: Date.now() }
91
+ ];
92
+ exports.FOREX_AGENT = {
93
+ id: "stablefx-01",
94
+ nameKey: "forex.agent_name",
95
+ descriptionKey: "forex.agent_description",
96
+ icon: "\u{1F4B1}",
97
+ color: "#0EA5E9",
98
+ supportedPairs: exports.FOREX_CURRENCY_PAIRS.map((p) => p.id),
99
+ dailyRoiMin: 2e-3,
100
+ dailyRoiMax: 5e-3,
101
+ totalManaged: 25e6,
102
+ totalUsers: 3847,
103
+ winRate: 72.5
104
+ };
105
+ }
106
+ });
107
+
108
+ // src/services/forex/ForexPoolDataGenerator.ts
109
+ var ForexPoolDataGenerator_exports = {};
110
+ __export(ForexPoolDataGenerator_exports, {
111
+ ForexPoolDataGenerator: () => exports.ForexPoolDataGenerator
112
+ });
113
+ function rand(min, max) {
114
+ return min + Math.random() * (max - min);
115
+ }
116
+ function randInt(min, max) {
117
+ return Math.floor(rand(min, max + 1));
118
+ }
119
+ function pick2(arr) {
120
+ return arr[Math.floor(Math.random() * arr.length)];
121
+ }
122
+ function genTxHash() {
123
+ const chars = "0123456789abcdef";
124
+ let hash = "0x";
125
+ for (let i = 0; i < 64; i++) hash += chars[Math.floor(Math.random() * 16)];
126
+ return hash;
127
+ }
128
+ function formatDate2(d) {
129
+ return d.toISOString().split("T")[0];
130
+ }
131
+ function genId(prefix) {
132
+ return `${prefix}_${Date.now().toString(36)}_${(++_idCounter).toString(36)}`;
133
+ }
134
+ var _idCounter, POOL_PARAMS, ForexPoolDataGeneratorClass, _instance; exports.ForexPoolDataGenerator = void 0;
135
+ var init_ForexPoolDataGenerator = __esm({
136
+ "src/services/forex/ForexPoolDataGenerator.ts"() {
137
+ init_forex();
138
+ _idCounter = 0;
139
+ POOL_PARAMS = {
140
+ clearing: {
141
+ meanDailyPnlPct: 35e-5,
142
+ stddevPnlPct: 15e-5,
143
+ utilizationMin: 0.7,
144
+ utilizationMax: 0.85,
145
+ depositsPerDay: [15, 25],
146
+ withdrawalsPerDay: [8, 12],
147
+ profitDistPerDay: 5,
148
+ avgDepositSize: 25e3,
149
+ avgWithdrawalSize: 18e3
150
+ },
151
+ hedging: {
152
+ meanDailyPnlPct: 22e-5,
153
+ stddevPnlPct: 2e-4,
154
+ utilizationMin: 0.55,
155
+ utilizationMax: 0.75,
156
+ depositsPerDay: [8, 15],
157
+ withdrawalsPerDay: [5, 8],
158
+ profitDistPerDay: 3,
159
+ avgDepositSize: 18e3,
160
+ avgWithdrawalSize: 12e3
161
+ },
162
+ insurance: {
163
+ meanDailyPnlPct: 13e-5,
164
+ stddevPnlPct: 8e-5,
165
+ utilizationMin: 0.3,
166
+ utilizationMax: 0.5,
167
+ depositsPerDay: [5, 10],
168
+ withdrawalsPerDay: [3, 5],
169
+ profitDistPerDay: 2,
170
+ avgDepositSize: 12e3,
171
+ avgWithdrawalSize: 8e3
172
+ }
173
+ };
174
+ ForexPoolDataGeneratorClass = class {
175
+ constructor() {
176
+ this.snapshotCache = null;
177
+ this.transactionCache = null;
178
+ this.baseBlockNumber = 195e5;
179
+ }
180
+ // ── Public API ─────────────────────────────────────────────────────────
181
+ generateAllSnapshots() {
182
+ if (this.snapshotCache) return this.snapshotCache;
183
+ const result = {
184
+ clearing: [],
185
+ hedging: [],
186
+ insurance: []
187
+ };
188
+ for (const pool of exports.FOREX_POOL_DEFAULTS) {
189
+ result[pool.id] = this.generatePoolSnapshots(pool.id, pool.totalSize);
190
+ }
191
+ this.snapshotCache = result;
192
+ return result;
193
+ }
194
+ generateAllTransactions() {
195
+ if (this.transactionCache) return this.transactionCache;
196
+ const allTx = [];
197
+ for (const pool of exports.FOREX_POOL_DEFAULTS) {
198
+ const snapshots = this.snapshotCache?.[pool.id] || this.generatePoolSnapshots(pool.id, pool.totalSize);
199
+ const txs = this.generatePoolTransactions(pool.id, snapshots);
200
+ allTx.push(...txs);
201
+ }
202
+ const now = /* @__PURE__ */ new Date();
203
+ for (let i = 0; i < 60; i++) {
204
+ const day = new Date(now);
205
+ day.setDate(day.getDate() - (60 - i));
206
+ const dayOfWeek = day.getDay();
207
+ if (dayOfWeek === 2 || dayOfWeek === 4 || dayOfWeek === 5 && Math.random() < 0.4) {
208
+ const fromPool = pick2(["clearing", "hedging", "insurance"]);
209
+ const toOptions = ["clearing", "hedging", "insurance"].filter((p) => p !== fromPool);
210
+ const toPool = pick2(toOptions);
211
+ const amount = rand(5e4, 2e5);
212
+ const ts = day.getTime() + randInt(10, 18) * 36e5;
213
+ allTx.push({
214
+ id: genId("ipt"),
215
+ poolId: fromPool,
216
+ type: "inter_pool_transfer",
217
+ amount: -amount,
218
+ balanceBefore: 0,
219
+ balanceAfter: 0,
220
+ txHash: genTxHash(),
221
+ blockNumber: this.baseBlockNumber + i * 7200 + randInt(0, 100),
222
+ timestamp: ts,
223
+ description: `Transfer to ${toPool} pool`
224
+ });
225
+ allTx.push({
226
+ id: genId("ipt"),
227
+ poolId: toPool,
228
+ type: "inter_pool_transfer",
229
+ amount,
230
+ balanceBefore: 0,
231
+ balanceAfter: 0,
232
+ txHash: genTxHash(),
233
+ blockNumber: this.baseBlockNumber + i * 7200 + randInt(100, 200),
234
+ timestamp: ts + 5e3,
235
+ description: `Transfer from ${fromPool} pool`
236
+ });
237
+ }
238
+ if (dayOfWeek === 3 && Math.random() < 0.85) {
239
+ const pool = pick2(exports.FOREX_POOL_DEFAULTS);
240
+ const rebalanceAmt = rand(2e4, 1e5);
241
+ const ts = day.getTime() + randInt(2, 6) * 36e5;
242
+ allTx.push({
243
+ id: genId("rrb"),
244
+ poolId: pool.id,
245
+ type: "reserve_rebalance",
246
+ amount: Math.random() < 0.5 ? rebalanceAmt : -rebalanceAmt,
247
+ balanceBefore: 0,
248
+ balanceAfter: 0,
249
+ txHash: genTxHash(),
250
+ blockNumber: this.baseBlockNumber + i * 7200 + randInt(200, 300),
251
+ timestamp: ts,
252
+ description: "Automated reserve rebalance"
253
+ });
254
+ }
255
+ }
256
+ allTx.sort((a, b) => a.timestamp - b.timestamp);
257
+ const runningBalance = {
258
+ clearing: exports.FOREX_POOL_DEFAULTS[0].totalSize * 0.85,
259
+ hedging: exports.FOREX_POOL_DEFAULTS[1].totalSize * 0.82,
260
+ insurance: exports.FOREX_POOL_DEFAULTS[2].totalSize * 0.88
261
+ };
262
+ for (const tx of allTx) {
263
+ tx.balanceBefore = runningBalance[tx.poolId];
264
+ runningBalance[tx.poolId] += tx.amount;
265
+ tx.balanceAfter = runningBalance[tx.poolId];
266
+ }
267
+ this.transactionCache = allTx;
268
+ return allTx;
269
+ }
270
+ generateTradeHistory(investmentAmount, startDate, selectedPairs) {
271
+ const trades = [];
272
+ const start = new Date(startDate);
273
+ const now = /* @__PURE__ */ new Date();
274
+ const dayCount = Math.min(60, Math.ceil((now.getTime() - start.getTime()) / 864e5));
275
+ let cumulativePnl = 0;
276
+ let blockNum = this.baseBlockNumber + randInt(0, 5e3);
277
+ for (let d = 0; d < dayCount; d++) {
278
+ const day = new Date(start);
279
+ day.setDate(day.getDate() + d);
280
+ const dayOfWeek = day.getDay();
281
+ const baseCount = dayOfWeek === 0 || dayOfWeek === 6 ? randInt(1, 2) : randInt(3, 8);
282
+ for (let t = 0; t < baseCount; t++) {
283
+ const pair = exports.FOREX_CURRENCY_PAIRS.find((p) => p.id === pick2(selectedPairs)) || pick2(exports.FOREX_CURRENCY_PAIRS);
284
+ const side = Math.random() > 0.5 ? "BUY" : "SELL";
285
+ const lots = parseFloat(rand(0.1, 2.5).toFixed(2));
286
+ const rfqPrice = pair.basePrice * (1 + rand(-3e-3, 3e-3));
287
+ const quoteSpread = rand(0.5, 2) * pair.pipSize;
288
+ const quotePrice = side === "BUY" ? rfqPrice + quoteSpread : rfqPrice - quoteSpread;
289
+ const matched = Math.random() < 0.85;
290
+ if (!matched) continue;
291
+ const matchPrice = quotePrice * (1 + rand(-5e-5, 5e-5));
292
+ const settlePrice = matchPrice * (1 + rand(-2e-5, 2e-5));
293
+ const pips = (settlePrice - rfqPrice) / pair.pipSize * (side === "BUY" ? 1 : -1);
294
+ const pnl = pips * pair.pipSize * lots * 1e5;
295
+ const isWin = Math.random() < exports.FOREX_AGENT.winRate / 100;
296
+ const finalPnl = isWin ? Math.abs(pnl) : -Math.abs(pnl) * rand(0.3, 0.8);
297
+ cumulativePnl += finalPnl;
298
+ const clearingFee = Math.abs(finalPnl) * rand(1e-3, 3e-3);
299
+ const hedgingCost = Math.abs(finalPnl) * rand(5e-4, 2e-3);
300
+ const insuranceReserve = Math.abs(finalPnl) * rand(3e-4, 1e-3);
301
+ blockNum += randInt(1, 20);
302
+ const timestamp = day.getTime() + randInt(0, 23) * 36e5 + randInt(0, 36e5);
303
+ trades.push({
304
+ id: genId("FXT"),
305
+ timestamp,
306
+ pairId: pair.id,
307
+ pairSymbol: pair.symbol,
308
+ side,
309
+ rfqPrice,
310
+ quotePrice,
311
+ matchPrice,
312
+ settlePrice,
313
+ lots,
314
+ pips: isWin ? Math.abs(pips) : -Math.abs(pips) * rand(0.3, 0.8),
315
+ pnl: finalPnl,
316
+ status: "SETTLED",
317
+ pvpSettled: true,
318
+ clearingFee,
319
+ hedgingCost,
320
+ insuranceReserve,
321
+ txHash: genTxHash(),
322
+ blockNumber: blockNum,
323
+ cycleDay: d + 1,
324
+ cumulativePnl
325
+ });
326
+ }
327
+ }
328
+ trades.sort((a, b) => a.timestamp - b.timestamp);
329
+ return trades;
330
+ }
331
+ generateLiveTransaction(poolId, type, baseAmount) {
332
+ const params = POOL_PARAMS[poolId];
333
+ let amount;
334
+ switch (type) {
335
+ case "deposit":
336
+ amount = baseAmount ?? rand(params.avgDepositSize * 0.5, params.avgDepositSize * 1.5);
337
+ break;
338
+ case "withdrawal":
339
+ amount = -(baseAmount ?? rand(params.avgWithdrawalSize * 0.5, params.avgWithdrawalSize * 1.5));
340
+ break;
341
+ case "profit_distribution":
342
+ amount = baseAmount ?? rand(500, 5e3);
343
+ break;
344
+ case "fee_collection":
345
+ amount = baseAmount ?? rand(100, 2e3);
346
+ break;
347
+ case "loss_absorption":
348
+ amount = -(baseAmount ?? rand(200, 3e3));
349
+ break;
350
+ default:
351
+ amount = baseAmount ?? rand(-5e3, 5e3);
352
+ }
353
+ const pool = exports.FOREX_POOL_DEFAULTS.find((p) => p.id === poolId);
354
+ const balanceBefore = pool.totalSize;
355
+ return {
356
+ id: genId("ptx"),
357
+ poolId,
358
+ type,
359
+ amount,
360
+ balanceBefore,
361
+ balanceAfter: balanceBefore + amount,
362
+ txHash: genTxHash(),
363
+ blockNumber: this.baseBlockNumber + Math.floor(Date.now() / 12e3),
364
+ timestamp: Date.now(),
365
+ description: this.getTxDescription(type, poolId, Math.abs(amount))
366
+ };
367
+ }
368
+ // ── Private Methods ────────────────────────────────────────────────────
369
+ generatePoolSnapshots(poolId, currentSize) {
370
+ const params = POOL_PARAMS[poolId];
371
+ const snapshots = [];
372
+ const now = /* @__PURE__ */ new Date();
373
+ let balance = currentSize * rand(0.82, 0.88);
374
+ let cumulativePnl = 0;
375
+ for (let i = 59; i >= 0; i--) {
376
+ const day = new Date(now);
377
+ day.setDate(day.getDate() - i);
378
+ const dayOfWeek = day.getDay();
379
+ const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
380
+ const openBalance = balance;
381
+ const activityMultiplier = isWeekend ? 0.2 : 1;
382
+ const isDrawdown = !isWeekend && Math.random() < 0.2;
383
+ let dailyPnlPct;
384
+ if (isDrawdown) {
385
+ dailyPnlPct = -rand(1e-4, params.stddevPnlPct * 2);
386
+ } else {
387
+ dailyPnlPct = this.gaussianRandom(params.meanDailyPnlPct, params.stddevPnlPct);
388
+ }
389
+ dailyPnlPct *= activityMultiplier;
390
+ const dailyPnl = balance * dailyPnlPct;
391
+ cumulativePnl += dailyPnl;
392
+ const depositCount = isWeekend ? randInt(1, Math.ceil(params.depositsPerDay[0] * 0.2)) : randInt(params.depositsPerDay[0], params.depositsPerDay[1]);
393
+ const withdrawalCount = isWeekend ? randInt(0, Math.ceil(params.withdrawalsPerDay[0] * 0.2)) : randInt(params.withdrawalsPerDay[0], params.withdrawalsPerDay[1]);
394
+ const deposits = depositCount * params.avgDepositSize * rand(0.7, 1.3) * activityMultiplier;
395
+ const withdrawals = withdrawalCount * params.avgWithdrawalSize * rand(0.7, 1.3) * activityMultiplier;
396
+ const netFlow = deposits - withdrawals;
397
+ balance += dailyPnl + netFlow;
398
+ const txCount = depositCount + withdrawalCount + Math.round(params.profitDistPerDay * activityMultiplier);
399
+ const utilization = rand(params.utilizationMin, params.utilizationMax);
400
+ const activeUsers = Math.round(rand(80, 400) * activityMultiplier);
401
+ snapshots.push({
402
+ poolId,
403
+ date: formatDate2(day),
404
+ openBalance,
405
+ closeBalance: balance,
406
+ deposits,
407
+ withdrawals,
408
+ netFlow,
409
+ dailyPnl,
410
+ dailyPnlPct,
411
+ cumulativePnl,
412
+ utilization,
413
+ txCount,
414
+ activeUsers
415
+ });
416
+ }
417
+ return snapshots;
418
+ }
419
+ generatePoolTransactions(poolId, snapshots) {
420
+ const params = POOL_PARAMS[poolId];
421
+ const transactions = [];
422
+ for (const snap of snapshots) {
423
+ const day = new Date(snap.date);
424
+ const dayOfWeek = day.getDay();
425
+ const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
426
+ const mult = isWeekend ? 0.2 : 1;
427
+ const depositCount = Math.round(randInt(params.depositsPerDay[0], params.depositsPerDay[1]) * mult);
428
+ const withdrawalCount = Math.round(randInt(params.withdrawalsPerDay[0], params.withdrawalsPerDay[1]) * mult);
429
+ const profitCount = Math.round(params.profitDistPerDay * mult);
430
+ for (let i = 0; i < depositCount; i++) {
431
+ const amount = rand(params.avgDepositSize * 0.3, params.avgDepositSize * 2);
432
+ const ts = day.getTime() + randInt(0, 23) * 36e5 + randInt(0, 36e5);
433
+ transactions.push({
434
+ id: genId("dep"),
435
+ poolId,
436
+ type: "deposit",
437
+ amount,
438
+ balanceBefore: 0,
439
+ balanceAfter: 0,
440
+ txHash: genTxHash(),
441
+ blockNumber: this.baseBlockNumber + Math.floor(ts / 12e3) + randInt(0, 50),
442
+ timestamp: ts,
443
+ description: `Deposit to ${poolId} pool`
444
+ });
445
+ }
446
+ for (let i = 0; i < withdrawalCount; i++) {
447
+ const amount = rand(params.avgWithdrawalSize * 0.3, params.avgWithdrawalSize * 2);
448
+ const ts = day.getTime() + randInt(0, 23) * 36e5 + randInt(0, 36e5);
449
+ transactions.push({
450
+ id: genId("wdr"),
451
+ poolId,
452
+ type: "withdrawal",
453
+ amount: -amount,
454
+ balanceBefore: 0,
455
+ balanceAfter: 0,
456
+ txHash: genTxHash(),
457
+ blockNumber: this.baseBlockNumber + Math.floor(ts / 12e3) + randInt(0, 50),
458
+ timestamp: ts,
459
+ description: `Withdrawal from ${poolId} pool`
460
+ });
461
+ }
462
+ for (let i = 0; i < profitCount; i++) {
463
+ const amount = rand(500, 8e3);
464
+ const ts = day.getTime() + randInt(6, 22) * 36e5 + randInt(0, 36e5);
465
+ transactions.push({
466
+ id: genId("prd"),
467
+ poolId,
468
+ type: "profit_distribution",
469
+ amount,
470
+ balanceBefore: 0,
471
+ balanceAfter: 0,
472
+ txHash: genTxHash(),
473
+ blockNumber: this.baseBlockNumber + Math.floor(ts / 12e3) + randInt(0, 50),
474
+ timestamp: ts,
475
+ description: `Profit distribution from ${poolId} pool`
476
+ });
477
+ }
478
+ if (!isWeekend) {
479
+ const feeCount = randInt(1, 2);
480
+ for (let i = 0; i < feeCount; i++) {
481
+ const amount = rand(100, 3e3);
482
+ const ts = day.getTime() + randInt(8, 20) * 36e5;
483
+ transactions.push({
484
+ id: genId("fee"),
485
+ poolId,
486
+ type: "fee_collection",
487
+ amount,
488
+ balanceBefore: 0,
489
+ balanceAfter: 0,
490
+ txHash: genTxHash(),
491
+ blockNumber: this.baseBlockNumber + Math.floor(ts / 12e3) + randInt(0, 50),
492
+ timestamp: ts,
493
+ description: `Fee collection for ${poolId} pool`
494
+ });
495
+ }
496
+ }
497
+ }
498
+ return transactions;
499
+ }
500
+ gaussianRandom(mean, stddev) {
501
+ let u = 0, v = 0;
502
+ while (u === 0) u = Math.random();
503
+ while (v === 0) v = Math.random();
504
+ const z = Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
505
+ return mean + z * stddev;
506
+ }
507
+ getTxDescription(type, poolId, amount) {
508
+ const fmt = `$${amount.toLocaleString(void 0, { maximumFractionDigits: 0 })}`;
509
+ switch (type) {
510
+ case "deposit":
511
+ return `Deposit ${fmt} to ${poolId} pool`;
512
+ case "withdrawal":
513
+ return `Withdrawal ${fmt} from ${poolId} pool`;
514
+ case "profit_distribution":
515
+ return `Profit distribution ${fmt} from ${poolId}`;
516
+ case "loss_absorption":
517
+ return `Loss absorbed ${fmt} by ${poolId} pool`;
518
+ case "inter_pool_transfer":
519
+ return `Inter-pool transfer ${fmt}`;
520
+ case "fee_collection":
521
+ return `Fee collected ${fmt} in ${poolId}`;
522
+ case "reserve_rebalance":
523
+ return `Reserve rebalance ${fmt} in ${poolId}`;
524
+ default:
525
+ return `${type} ${fmt}`;
526
+ }
527
+ }
528
+ };
529
+ _instance = null;
530
+ exports.ForexPoolDataGenerator = {
531
+ getInstance() {
532
+ if (!_instance) {
533
+ _instance = new ForexPoolDataGeneratorClass();
534
+ }
535
+ return _instance;
536
+ }
537
+ };
538
+ }
539
+ });
540
+
541
+ // src/services/forex/ForexSimulationEngine.ts
542
+ var ForexSimulationEngine_exports = {};
543
+ __export(ForexSimulationEngine_exports, {
544
+ forexSimulationEngine: () => exports.forexSimulationEngine
545
+ });
546
+ function genId2() {
547
+ return `fxlog_${Date.now()}_${++idCounter}`;
548
+ }
549
+ function tradeId() {
550
+ return `FXT_${Date.now().toString(36).toUpperCase()}_${(++idCounter).toString(36).toUpperCase()}`;
551
+ }
552
+ function rand2(min, max) {
553
+ return min + Math.random() * (max - min);
554
+ }
555
+ function randInt2(min, max) {
556
+ return Math.floor(rand2(min, max + 1));
557
+ }
558
+ function pick3(arr) {
559
+ return arr[Math.floor(Math.random() * arr.length)];
560
+ }
561
+ function formatRate(price, pair) {
562
+ if (pair.pipSize >= 0.01) return price.toFixed(3);
563
+ return price.toFixed(5);
564
+ }
565
+ var idCounter, FX_NEWS, ForexSimulationEngine; exports.forexSimulationEngine = void 0;
566
+ var init_ForexSimulationEngine = __esm({
567
+ "src/services/forex/ForexSimulationEngine.ts"() {
568
+ init_forex();
569
+ idCounter = 0;
570
+ FX_NEWS = [
571
+ "ECB signals potential rate adjustment, EUR pairs volatile",
572
+ "BOJ maintains yield curve control, JPY weakens further",
573
+ "Fed minutes reveal hawkish sentiment, USD strengthens",
574
+ "UK CPI data beats expectations, GBP rallies",
575
+ "RBA holds rates steady, AUD consolidates",
576
+ "SNB intervenes in currency markets, CHF stabilizes",
577
+ "Bank of Canada rate decision pending, CAD in focus",
578
+ "Cross-border stablecoin settlement volume hits $2.1B daily",
579
+ "Circle USDC reserves fully backed, attestation report released",
580
+ "DeFi forex protocol TVL reaches new high at $890M",
581
+ "On-chain FX liquidity deepens across major pairs",
582
+ "Institutional adoption of on-chain forex accelerates"
583
+ ];
584
+ ForexSimulationEngine = class {
585
+ constructor() {
586
+ this.listeners = [];
587
+ this.poolTxListeners = [];
588
+ this.cycleTimer = null;
589
+ this.pairStates = /* @__PURE__ */ new Map();
590
+ this.running = false;
591
+ this.openPositions = [];
592
+ this.totalPnl = 0;
593
+ this.totalTrades = 0;
594
+ this.totalPips = 0;
595
+ this.totalLots = 0;
596
+ for (const pair of exports.FOREX_CURRENCY_PAIRS) {
597
+ const jitter = pair.basePrice * rand2(-3e-3, 3e-3);
598
+ const price = pair.basePrice + jitter;
599
+ const halfSpread = pair.spreadPips * pair.pipSize / 2;
600
+ this.pairStates.set(pair.id, {
601
+ pair,
602
+ currentPrice: price,
603
+ bidPrice: price - halfSpread,
604
+ askPrice: price + halfSpread,
605
+ lastSpread: pair.spreadPips
606
+ });
607
+ }
608
+ }
609
+ // ── Public API ─────────────────────────────────────────────────────────────
610
+ start() {
611
+ this.running = true;
612
+ this.scheduleCycle();
613
+ }
614
+ stop() {
615
+ this.running = false;
616
+ if (this.cycleTimer) {
617
+ clearTimeout(this.cycleTimer);
618
+ this.cycleTimer = null;
619
+ }
620
+ }
621
+ onLog(callback) {
622
+ this.listeners.push(callback);
623
+ return () => {
624
+ this.listeners = this.listeners.filter((l) => l !== callback);
625
+ };
626
+ }
627
+ onPoolTransaction(callback) {
628
+ this.poolTxListeners.push(callback);
629
+ return () => {
630
+ this.poolTxListeners = this.poolTxListeners.filter((l) => l !== callback);
631
+ };
632
+ }
633
+ isRunning() {
634
+ return this.running;
635
+ }
636
+ getStats() {
637
+ return {
638
+ totalPnl: this.totalPnl,
639
+ totalTrades: this.totalTrades,
640
+ totalPips: this.totalPips,
641
+ totalLots: this.totalLots,
642
+ positions: this.openPositions.length
643
+ };
644
+ }
645
+ getPairStates() {
646
+ return this.pairStates;
647
+ }
648
+ emitBootSequence() {
649
+ const bootMessages = [
650
+ { msg: "Initializing StableFX Engine v2.1.0...", delay: 0 },
651
+ { msg: "Connecting to Circle StableFX RFQ network...", delay: 500 },
652
+ { msg: "Loading USDC stablecoin pair feeds (6 pairs)...", delay: 1200 },
653
+ { msg: "Calibrating PvP settlement engine...", delay: 2e3 },
654
+ { msg: "Initializing clearing pool ($12.5M)...", delay: 2800 },
655
+ { msg: "Initializing hedging pool ($7.5M)...", delay: 3400 },
656
+ { msg: "Initializing insurance pool ($5.0M)...", delay: 4e3 },
657
+ { msg: "Risk management module online (max exposure: 25%)", delay: 4500 },
658
+ { msg: "=== StableFX Engine ready. Starting RFQ cycles ===", delay: 5e3 }
659
+ ];
660
+ for (const { msg, delay } of bootMessages) {
661
+ setTimeout(() => {
662
+ this.emit({
663
+ id: genId2(),
664
+ timestamp: Date.now(),
665
+ type: "SYSTEM",
666
+ message: msg,
667
+ importance: "medium"
668
+ });
669
+ }, delay);
670
+ }
671
+ }
672
+ destroy() {
673
+ this.stop();
674
+ this.listeners = [];
675
+ this.poolTxListeners = [];
676
+ this.pairStates.clear();
677
+ this.openPositions = [];
678
+ }
679
+ // ── Private Methods ────────────────────────────────────────────────────────
680
+ emit(entry) {
681
+ for (const listener of this.listeners) {
682
+ listener(entry);
683
+ }
684
+ }
685
+ emitPoolTx(tx) {
686
+ for (const listener of this.poolTxListeners) {
687
+ listener(tx);
688
+ }
689
+ }
690
+ generatePoolTxFromEvent(type, data) {
691
+ try {
692
+ const { ForexPoolDataGenerator: ForexPoolDataGenerator2 } = (init_ForexPoolDataGenerator(), __toCommonJS(ForexPoolDataGenerator_exports));
693
+ const generator = ForexPoolDataGenerator2.getInstance();
694
+ if (type === "SETTLE" && data.pnl !== void 0) {
695
+ const tx = generator.generateLiveTransaction("clearing", "fee_collection", Math.abs(data.pnl) * rand2(1e-3, 3e-3));
696
+ this.emitPoolTx(tx);
697
+ } else if (type === "HEDGE") {
698
+ const tx = generator.generateLiveTransaction("hedging", data.pnl && data.pnl < 0 ? "loss_absorption" : "profit_distribution", Math.abs(data.lots || 1) * rand2(50, 200));
699
+ this.emitPoolTx(tx);
700
+ } else if (type === "CLEAR") {
701
+ const tx = generator.generateLiveTransaction("clearing", "profit_distribution", (data.volume || 1e5) * rand2(1e-4, 5e-4));
702
+ this.emitPoolTx(tx);
703
+ }
704
+ } catch {
705
+ }
706
+ }
707
+ scheduleCycle() {
708
+ if (!this.running) return;
709
+ const interval = rand2(8e3, 14e3);
710
+ this.cycleTimer = setTimeout(() => {
711
+ if (this.running) {
712
+ this.runTradeCycle();
713
+ this.scheduleCycle();
714
+ }
715
+ }, interval);
716
+ }
717
+ simulatePrice(pairId) {
718
+ const state = this.pairStates.get(pairId);
719
+ if (!state) return 0;
720
+ const volatility = state.pair.id.includes("JPYC") ? 8e-4 : 4e-4;
721
+ const drift = rand2(-volatility, volatility);
722
+ const newPrice = state.currentPrice * (1 + drift);
723
+ const halfSpread = (state.pair.spreadPips + rand2(-0.3, 0.3)) * state.pair.pipSize / 2;
724
+ state.currentPrice = newPrice;
725
+ state.bidPrice = newPrice - halfSpread;
726
+ state.askPrice = newPrice + halfSpread;
727
+ state.lastSpread = halfSpread * 2 / state.pair.pipSize;
728
+ return newPrice;
729
+ }
730
+ runTradeCycle() {
731
+ const pairState = pick3(Array.from(this.pairStates.values()));
732
+ const pair = pairState.pair;
733
+ const entries = [];
734
+ let delay = 0;
735
+ const price = this.simulatePrice(pair.id);
736
+ const side = Math.random() > 0.5 ? "BUY" : "SELL";
737
+ const lots = parseFloat(rand2(0.1, 2.5).toFixed(2));
738
+ const notional = lots * 1e5;
739
+ const rfqId = tradeId();
740
+ entries.push({
741
+ entry: {
742
+ type: "RFQ",
743
+ message: `RFQ ${rfqId} | ${pair.symbol} ${side} ${lots.toFixed(2)} lots ($${(notional / 1e3).toFixed(0)}K) | Mid: ${formatRate(price, pair)}`,
744
+ data: { rfqId, pair: pair.id, side, lots, price },
745
+ importance: "medium",
746
+ pairId: pair.id
747
+ },
748
+ delay
749
+ });
750
+ delay += rand2(400, 800);
751
+ const quoteSpread = rand2(0.5, 2) * pair.pipSize;
752
+ const quotePrice = side === "BUY" ? price + quoteSpread : price - quoteSpread;
753
+ const quotePips = Math.abs(quotePrice - price) / pair.pipSize;
754
+ entries.push({
755
+ entry: {
756
+ type: "QUOTE",
757
+ message: `QUOTE ${rfqId} | ${pair.symbol} @ ${formatRate(quotePrice, pair)} | Spread: ${quotePips.toFixed(1)} pips | Valid: 3s`,
758
+ data: { rfqId, quotePrice, spread: quotePips },
759
+ importance: "medium",
760
+ pairId: pair.id
761
+ },
762
+ delay
763
+ });
764
+ delay += rand2(500, 1e3);
765
+ const matched = Math.random() < 0.85;
766
+ if (matched) {
767
+ const matchPrice = quotePrice * (1 + rand2(-5e-5, 5e-5));
768
+ entries.push({
769
+ entry: {
770
+ type: "MATCH",
771
+ message: `MATCH ${rfqId} | ${pair.symbol} ${side} @ ${formatRate(matchPrice, pair)} | ${lots.toFixed(2)} lots | Counterparty: LP-${randInt2(1, 8)}`,
772
+ data: { rfqId, matchPrice, counterparty: `LP-${randInt2(1, 8)}` },
773
+ importance: "high",
774
+ pairId: pair.id
775
+ },
776
+ delay
777
+ });
778
+ delay += rand2(1e3, 2500);
779
+ const settlePrice = matchPrice * (1 + rand2(-2e-5, 2e-5));
780
+ const pips = (settlePrice - price) / pair.pipSize * (side === "BUY" ? 1 : -1);
781
+ const pnl = pips * pair.pipSize * lots * 1e5;
782
+ entries.push({
783
+ entry: {
784
+ type: "SETTLE",
785
+ message: `SETTLE ${rfqId} | PvP confirmed | ${pair.symbol} @ ${formatRate(settlePrice, pair)} | P&L: ${pips >= 0 ? "+" : ""}${pips.toFixed(1)} pips ($${pnl >= 0 ? "+" : ""}${pnl.toFixed(2)})`,
786
+ data: { rfqId, settlePrice, pips, pnl, pvp: true },
787
+ importance: "high",
788
+ pairId: pair.id
789
+ },
790
+ delay
791
+ });
792
+ delay += rand2(300, 600);
793
+ entries.push({
794
+ entry: {
795
+ type: "PVP",
796
+ message: `PvP ${rfqId} | Atomic settlement confirmed on-chain | USDC transferred: $${notional.toLocaleString()} | Gas: ~$0.${randInt2(10, 50)}`,
797
+ data: { rfqId, settled: true, gasWei: randInt2(10, 50) },
798
+ importance: "medium",
799
+ pairId: pair.id
800
+ },
801
+ delay
802
+ });
803
+ this.generatePoolTxFromEvent("SETTLE", { pnl });
804
+ this.totalTrades++;
805
+ this.totalPnl += pnl;
806
+ this.totalPips += pips;
807
+ this.totalLots += lots;
808
+ if (Math.random() < 0.4) {
809
+ this.openPositions.push({
810
+ id: rfqId,
811
+ pairId: pair.id,
812
+ side,
813
+ lots,
814
+ pips,
815
+ entryPrice: matchPrice,
816
+ currentPrice: settlePrice,
817
+ pnl,
818
+ openTime: Date.now()
819
+ });
820
+ if (this.openPositions.length > 5) {
821
+ this.openPositions.shift();
822
+ }
823
+ }
824
+ } else {
825
+ entries.push({
826
+ entry: {
827
+ type: "MATCH",
828
+ message: `MATCH FAILED ${rfqId} | ${pair.symbol} | No counterparty at requested price | Requoting...`,
829
+ data: { rfqId, matched: false },
830
+ importance: "low",
831
+ pairId: pair.id
832
+ },
833
+ delay
834
+ });
835
+ }
836
+ if (Math.random() < 0.2) {
837
+ delay += rand2(400, 800);
838
+ const hedgePair = pick3(exports.FOREX_CURRENCY_PAIRS);
839
+ const hedgeLots = parseFloat(rand2(0.5, 5).toFixed(2));
840
+ const hedgeDirection = Math.random() > 0.5 ? "LONG" : "SHORT";
841
+ entries.push({
842
+ entry: {
843
+ type: "HEDGE",
844
+ message: `HEDGE | ${hedgePair.symbol} ${hedgeDirection} ${hedgeLots.toFixed(2)} lots | Pool delta neutralization | Exposure: ${rand2(5, 20).toFixed(1)}%`,
845
+ data: { pair: hedgePair.id, direction: hedgeDirection, lots: hedgeLots },
846
+ importance: "medium"
847
+ },
848
+ delay
849
+ });
850
+ this.generatePoolTxFromEvent("HEDGE", { lots: hedgeLots });
851
+ }
852
+ if (Math.random() < 0.15) {
853
+ delay += rand2(300, 600);
854
+ const clearAmount = randInt2(5e4, 5e5);
855
+ entries.push({
856
+ entry: {
857
+ type: "CLEAR",
858
+ message: `CLEAR | Netting cycle complete | Volume: $${(clearAmount / 1e3).toFixed(0)}K | Pairs settled: ${randInt2(2, 6)} | Pool util: ${rand2(60, 85).toFixed(1)}%`,
859
+ data: { volume: clearAmount, pairsSettled: randInt2(2, 6) },
860
+ importance: "low"
861
+ },
862
+ delay
863
+ });
864
+ this.generatePoolTxFromEvent("CLEAR", { volume: clearAmount });
865
+ }
866
+ if (this.openPositions.length > 0 && Math.random() < 0.25) {
867
+ delay += rand2(300, 600);
868
+ const posUpdates = this.openPositions.slice(0, 3).map((pos) => {
869
+ const pState = this.pairStates.get(pos.pairId);
870
+ if (pState) {
871
+ pos.currentPrice = pState.currentPrice;
872
+ pos.pips = (pos.currentPrice - pos.entryPrice) / pState.pair.pipSize * (pos.side === "BUY" ? 1 : -1);
873
+ pos.pnl = pos.pips * pState.pair.pipSize * pos.lots * 1e5;
874
+ }
875
+ return `${pState?.pair.symbol || pos.pairId} ${pos.side}: ${pos.pips >= 0 ? "+" : ""}${pos.pips.toFixed(1)} pips`;
876
+ });
877
+ entries.push({
878
+ entry: {
879
+ type: "POSITION",
880
+ message: `POSITION | ${posUpdates.join(" | ")} | Open: ${this.openPositions.length}`,
881
+ data: { positions: this.openPositions.length },
882
+ importance: "low"
883
+ },
884
+ delay
885
+ });
886
+ if (this.openPositions.length > 2 && Math.random() < 0.3) {
887
+ const closed = this.openPositions.shift();
888
+ this.totalPnl += closed.pnl * rand2(0.01, 0.03);
889
+ }
890
+ }
891
+ if (Math.random() < 0.3) {
892
+ delay += rand2(300, 600);
893
+ entries.push({
894
+ entry: {
895
+ type: "PNL",
896
+ 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)}`,
897
+ data: { totalPnl: this.totalPnl, totalTrades: this.totalTrades, totalPips: this.totalPips },
898
+ importance: "medium"
899
+ },
900
+ delay
901
+ });
902
+ }
903
+ if (Math.random() < 0.1) {
904
+ delay += rand2(300, 600);
905
+ entries.push({
906
+ entry: {
907
+ type: "SYSTEM",
908
+ message: `[Market] ${pick3(FX_NEWS)}`,
909
+ importance: "medium"
910
+ },
911
+ delay
912
+ });
913
+ }
914
+ for (const { entry, delay: d } of entries) {
915
+ setTimeout(() => {
916
+ if (this.running) {
917
+ this.emit({
918
+ ...entry,
919
+ id: genId2(),
920
+ timestamp: Date.now()
921
+ });
922
+ }
923
+ }, d);
924
+ }
925
+ }
926
+ };
927
+ exports.forexSimulationEngine = new ForexSimulationEngine();
928
+ }
929
+ });
6
930
 
7
931
  // src/config/index.ts
8
932
  var DEFAULT_ENGINE_URL = "https://api.one23.io";
@@ -123,6 +1047,189 @@ var CHAIN_CONFIGS = {
123
1047
  }
124
1048
  };
125
1049
 
1050
+ // src/types/aiTrading.ts
1051
+ var PENALTY_TIERS = [
1052
+ { minProgress: 0.75, maxProgress: 1, rate: 0.5, label: "50%" },
1053
+ { minProgress: 0.5, maxProgress: 0.75, rate: 0.6, label: "60%" },
1054
+ { minProgress: 0.25, maxProgress: 0.5, rate: 0.7, label: "70%" },
1055
+ { minProgress: 0, maxProgress: 0.25, rate: 0.8, label: "80%" }
1056
+ ];
1057
+ function calculateEarlyWithdrawalPenalty(investedAmount, profit, lockProgress) {
1058
+ const totalValue = investedAmount + profit;
1059
+ const isEarlyWithdrawal = lockProgress < 1;
1060
+ let penaltyRate = 0;
1061
+ if (isEarlyWithdrawal) {
1062
+ if (lockProgress >= 0.75) penaltyRate = 0.5;
1063
+ else if (lockProgress >= 0.5) penaltyRate = 0.6;
1064
+ else if (lockProgress >= 0.25) penaltyRate = 0.7;
1065
+ else penaltyRate = 0.8;
1066
+ }
1067
+ const estimatedPenalty = totalValue * penaltyRate;
1068
+ const estimatedRedemption = totalValue - estimatedPenalty;
1069
+ return { completionRate: lockProgress, penaltyRate, estimatedPenalty, estimatedRedemption, isEarlyWithdrawal };
1070
+ }
1071
+ var STRATEGY_CATEGORIES = {
1072
+ conservative: { labelKey: "ai.category_conservative", color: "#10B981", icon: "\u{1F6E1}\uFE0F" },
1073
+ balanced: { labelKey: "ai.category_balanced", color: "#3B82F6", icon: "\u2696\uFE0F" },
1074
+ aggressive: { labelKey: "ai.category_aggressive", color: "#EF4444", icon: "\u{1F680}" },
1075
+ hedge: { labelKey: "ai.category_hedge", color: "#8B5CF6", icon: "\u{1F512}" },
1076
+ arbitrage: { labelKey: "ai.category_arbitrage", color: "#F59E0B", icon: "\u26A1" },
1077
+ trend: { labelKey: "ai.category_trend", color: "#EC4899", icon: "\u{1F4C8}" },
1078
+ grid: { labelKey: "ai.category_grid", color: "#6366F1", icon: "\u25A6" },
1079
+ dca: { labelKey: "ai.category_dca", color: "#14B8A6", icon: "\u{1F4CA}" }
1080
+ };
1081
+ var RISK_LEVELS = {
1082
+ 1: { labelKey: "ai.risk_very_low", color: "#10B981", bgColor: "#D1FAE5" },
1083
+ 2: { labelKey: "ai.risk_low", color: "#22C55E", bgColor: "#DCFCE7" },
1084
+ 3: { labelKey: "ai.risk_medium", color: "#F59E0B", bgColor: "#FEF3C7" },
1085
+ 4: { labelKey: "ai.risk_high", color: "#F97316", bgColor: "#FFEDD5" },
1086
+ 5: { labelKey: "ai.risk_very_high", color: "#EF4444", bgColor: "#FEE2E2" }
1087
+ };
1088
+ var ORDER_STATUS_CONFIG = {
1089
+ pending: { labelKey: "ai.status_pending", color: "#F59E0B", bgColor: "#FEF3C7" },
1090
+ active: { labelKey: "ai.status_active", color: "#10B981", bgColor: "#D1FAE5" },
1091
+ paused: { labelKey: "ai.status_paused", color: "#6B7280", bgColor: "#F3F4F6" },
1092
+ completed: { labelKey: "ai.status_completed", color: "#3B82F6", bgColor: "#DBEAFE" },
1093
+ cancelled: { labelKey: "ai.status_cancelled", color: "#EF4444", bgColor: "#FEE2E2" },
1094
+ pending_redemption: { labelKey: "ai.status_pending_redemption", color: "#8B5CF6", bgColor: "#EDE9FE" },
1095
+ redeemed: { labelKey: "ai.status_redeemed", color: "#14B8A6", bgColor: "#CCFBF1" }
1096
+ };
1097
+
1098
+ // src/types/console.ts
1099
+ var AI_LOG_COLORS = {
1100
+ SCAN: "#06B6D4",
1101
+ // Cyan
1102
+ THINKING: "#A855F7",
1103
+ // Purple
1104
+ INDICATOR: "#3B82F6",
1105
+ // Blue
1106
+ ANALYSIS: "#6366F1",
1107
+ // Indigo
1108
+ SIGNAL: "#F59E0B",
1109
+ // Amber
1110
+ STRATEGY: "#D946EF",
1111
+ // Fuchsia
1112
+ DECISION: "#F97316",
1113
+ // Orange
1114
+ ORDER: "#EC4899",
1115
+ // Pink
1116
+ FILLED: "#10B981",
1117
+ // Green
1118
+ PNL: "#22C55E",
1119
+ // Emerald
1120
+ RISK: "#EF4444",
1121
+ // Red
1122
+ NEWS: "#14B8A6",
1123
+ // Teal
1124
+ SYSTEM: "#9CA3AF"
1125
+ // Gray
1126
+ };
1127
+ var FOREX_LOG_COLORS = {
1128
+ RFQ: "#06B6D4",
1129
+ // Cyan
1130
+ QUOTE: "#8B5CF6",
1131
+ // Purple
1132
+ MATCH: "#10B981",
1133
+ // Green
1134
+ SETTLE: "#F59E0B",
1135
+ // Amber
1136
+ PVP: "#3B82F6",
1137
+ // Blue
1138
+ HEDGE: "#EC4899",
1139
+ // Pink
1140
+ CLEAR: "#14B8A6",
1141
+ // Teal
1142
+ POSITION: "#6366F1",
1143
+ // Indigo
1144
+ PNL: "#22C55E",
1145
+ // Emerald
1146
+ SYSTEM: "#9CA3AF"
1147
+ // Gray
1148
+ };
1149
+ var RISK_LEVEL_COLORS = {
1150
+ low: { color: "#10B981", bgColor: "#D1FAE5" },
1151
+ medium: { color: "#F59E0B", bgColor: "#FEF3C7" },
1152
+ high: { color: "#F97316", bgColor: "#FFEDD5" },
1153
+ critical: { color: "#EF4444", bgColor: "#FEE2E2" }
1154
+ };
1155
+ var TRADING_STATUS_COLORS = {
1156
+ active: { color: "#10B981", bgColor: "#D1FAE5" },
1157
+ paused: { color: "#F59E0B", bgColor: "#FEF3C7" },
1158
+ stopped: { color: "#EF4444", bgColor: "#FEE2E2" },
1159
+ cooldown: { color: "#6366F1", bgColor: "#E0E7FF" }
1160
+ };
1161
+ var AGENT_STATUS_COLORS = {
1162
+ active: { color: "#10B981", bgColor: "#D1FAE5", label: "Active" },
1163
+ paused: { color: "#F59E0B", bgColor: "#FEF3C7", label: "Paused" },
1164
+ idle: { color: "#6B7280", bgColor: "#F3F4F6", label: "Idle" },
1165
+ error: { color: "#EF4444", bgColor: "#FEE2E2", label: "Error" },
1166
+ initializing: { color: "#3B82F6", bgColor: "#DBEAFE", label: "Starting" }
1167
+ };
1168
+ var DEFAULT_CONSOLE_OPTIONS = {
1169
+ simulation: true,
1170
+ pollInterval: 5e3,
1171
+ maxLogs: 500,
1172
+ autoStart: false
1173
+ };
1174
+ var DEFAULT_RISK_STATUS = {
1175
+ timestamp: Date.now(),
1176
+ totalExposure: 0,
1177
+ maxExposure: 1e5,
1178
+ exposurePercent: 0,
1179
+ dailyPnl: 0,
1180
+ dailyPnlLimit: 5e3,
1181
+ dailyPnlPercent: 0,
1182
+ dailyTradeCount: 0,
1183
+ dailyTradeLimit: 50,
1184
+ currentDrawdown: 0,
1185
+ maxDrawdown: 15,
1186
+ drawdownPercent: 0,
1187
+ openPositions: 0,
1188
+ maxPositions: 10,
1189
+ riskLevel: "low",
1190
+ tradingStatus: "active",
1191
+ warnings: []
1192
+ };
1193
+ var DEFAULT_CONSOLE_METRICS = {
1194
+ nav: 0,
1195
+ navChange24h: 0,
1196
+ navChangePercent24h: 0,
1197
+ totalPnl: 0,
1198
+ realizedPnl: 0,
1199
+ unrealizedPnl: 0,
1200
+ pnlToday: 0,
1201
+ pnl7d: 0,
1202
+ pnl30d: 0,
1203
+ totalTrades: 0,
1204
+ tradesToday: 0,
1205
+ winRate: 0,
1206
+ winCount: 0,
1207
+ lossCount: 0,
1208
+ avgWin: 0,
1209
+ avgLoss: 0,
1210
+ profitFactor: 0,
1211
+ openPositions: 0,
1212
+ totalExposure: 0,
1213
+ avgLeverage: 0
1214
+ };
1215
+ function calculateRiskLevel(exposurePercent, drawdownPercent, dailyPnlPercent) {
1216
+ const worstMetric = Math.max(exposurePercent, drawdownPercent, Math.abs(dailyPnlPercent));
1217
+ if (worstMetric >= 90) return "critical";
1218
+ if (worstMetric >= 70) return "high";
1219
+ if (worstMetric >= 40) return "medium";
1220
+ return "low";
1221
+ }
1222
+ function formatPnl(pnl) {
1223
+ const sign = pnl >= 0 ? "+" : "";
1224
+ if (Math.abs(pnl) >= 1e6) {
1225
+ return `${sign}$${(pnl / 1e6).toFixed(2)}M`;
1226
+ }
1227
+ if (Math.abs(pnl) >= 1e3) {
1228
+ return `${sign}$${(pnl / 1e3).toFixed(2)}K`;
1229
+ }
1230
+ return `${sign}$${pnl.toFixed(2)}`;
1231
+ }
1232
+
126
1233
  // src/services/engine.ts
127
1234
  var OneEngineClient = class {
128
1235
  constructor(options) {
@@ -1686,10 +2793,6 @@ var CHAIN_CONFIG = {
1686
2793
  zksync: { name: "zkSync", icon: "\u2B22", color: "#8C8DFC" },
1687
2794
  scroll: { name: "Scroll", icon: "\u25CE", color: "#FFEEDA" }
1688
2795
  };
1689
- var isDesktop = () => {
1690
- const { width } = reactNative.Dimensions.get("window");
1691
- return reactNative.Platform.OS === "web" && width >= 768;
1692
- };
1693
2796
  var OneChainSelector = ({
1694
2797
  supportedChains,
1695
2798
  selectedChains,
@@ -1699,12 +2802,9 @@ var OneChainSelector = ({
1699
2802
  title,
1700
2803
  subtitle,
1701
2804
  minSelections = 1,
1702
- placeholder = "Select chains...",
1703
2805
  style,
1704
2806
  titleStyle
1705
2807
  }) => {
1706
- const [isOpen, setIsOpen] = react.useState(false);
1707
- const desktop = isDesktop();
1708
2808
  const handleSelect = (chain) => {
1709
2809
  if (multiSelect) {
1710
2810
  if (selectedChains.includes(chain) && selectedChains.length <= minSelections) {
@@ -1715,129 +2815,42 @@ var OneChainSelector = ({
1715
2815
  if (!selectedChains.includes(chain)) {
1716
2816
  onSelectChain(chain);
1717
2817
  }
1718
- setIsOpen(false);
1719
2818
  }
1720
2819
  };
1721
- if (desktop) {
1722
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles.container, style], children: [
1723
- title && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles.title, titleStyle], children: title }),
1724
- subtitle && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.subtitle, children: subtitle }),
1725
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.desktopGrid, children: supportedChains.map((chain) => {
1726
- const chainInfo = CHAIN_CONFIG[chain] || { name: chain, icon: "\u25CF", color: "#888" };
1727
- const isSelected = selectedChains.includes(chain);
1728
- return /* @__PURE__ */ jsxRuntime.jsxs(
1729
- reactNative.TouchableOpacity,
1730
- {
1731
- style: [
1732
- styles.desktopChip,
1733
- isSelected && styles.desktopChipSelected,
1734
- isSelected && { borderColor: accentColor, backgroundColor: accentColor + "12" }
1735
- ],
1736
- onPress: () => handleSelect(chain),
1737
- activeOpacity: 0.7,
1738
- children: [
1739
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles.desktopIconBg, { backgroundColor: chainInfo.color + "20" }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles.desktopIcon, { color: chainInfo.color }], children: chainInfo.icon }) }),
1740
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
1741
- styles.desktopChipText,
1742
- isSelected && { color: accentColor, fontWeight: "600" }
1743
- ], children: chainInfo.name }),
1744
- isSelected && /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles.desktopCheckbox, { backgroundColor: accentColor }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.desktopCheckIcon, children: "\u2713" }) })
1745
- ]
1746
- },
1747
- chain
1748
- );
1749
- }) }),
1750
- multiSelect && selectedChains.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [styles.selectedCount, { color: accentColor }], children: [
1751
- selectedChains.length,
1752
- " chain",
1753
- selectedChains.length > 1 ? "s" : "",
1754
- " selected"
1755
- ] })
1756
- ] });
1757
- }
1758
2820
  return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles.container, style], children: [
1759
2821
  title && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles.title, titleStyle], children: title }),
1760
2822
  subtitle && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.subtitle, children: subtitle }),
1761
- /* @__PURE__ */ jsxRuntime.jsxs(
1762
- reactNative.TouchableOpacity,
1763
- {
1764
- style: [styles.dropdownTrigger, { borderColor: isOpen ? accentColor : "#e5e5e5" }],
1765
- onPress: () => setIsOpen(true),
1766
- activeOpacity: 0.7,
1767
- children: [
1768
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.selectedPreview, children: [
1769
- selectedChains.slice(0, 3).map((chain) => {
1770
- const chainInfo = CHAIN_CONFIG[chain] || { icon: "\u25CF", color: "#888" };
1771
- return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles.previewChip, { backgroundColor: chainInfo.color + "20" }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles.previewIcon, { color: chainInfo.color }], children: chainInfo.icon }) }, chain);
1772
- }),
1773
- selectedChains.length > 3 && /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.previewMore, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles.previewMoreText, children: [
1774
- "+",
1775
- selectedChains.length - 3
1776
- ] }) }),
1777
- selectedChains.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.placeholderText, children: placeholder })
1778
- ] }),
1779
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.dropdownArrow, children: isOpen ? "\u25B2" : "\u25BC" })
1780
- ]
1781
- }
1782
- ),
1783
- multiSelect && selectedChains.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [styles.selectedCount, { color: accentColor }], children: [
2823
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.chainsContainer, children: supportedChains.map((chain) => {
2824
+ const chainInfo = CHAIN_CONFIG[chain] || { name: chain, icon: "\u25CF", color: "#888" };
2825
+ const isSelected = selectedChains.includes(chain);
2826
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2827
+ reactNative.TouchableOpacity,
2828
+ {
2829
+ style: [
2830
+ styles.chainChip,
2831
+ isSelected && styles.chainChipSelected,
2832
+ isSelected && { borderColor: accentColor, backgroundColor: accentColor + "15" }
2833
+ ],
2834
+ onPress: () => handleSelect(chain),
2835
+ activeOpacity: 0.7,
2836
+ children: [
2837
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles.chainIconBg, { backgroundColor: chainInfo.color + "20" }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles.chainIcon, { color: chainInfo.color }], children: chainInfo.icon }) }),
2838
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
2839
+ styles.chainText,
2840
+ isSelected && { color: accentColor, fontWeight: "600" }
2841
+ ], children: chainInfo.name }),
2842
+ isSelected && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles.checkmark, { color: accentColor }], children: "\u2713" })
2843
+ ]
2844
+ },
2845
+ chain
2846
+ );
2847
+ }) }),
2848
+ multiSelect && selectedChains.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.selectedInfo, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles.selectedText, children: [
1784
2849
  selectedChains.length,
1785
2850
  " chain",
1786
2851
  selectedChains.length > 1 ? "s" : "",
1787
2852
  " selected"
1788
- ] }),
1789
- /* @__PURE__ */ jsxRuntime.jsx(
1790
- reactNative.Modal,
1791
- {
1792
- visible: isOpen,
1793
- transparent: true,
1794
- animationType: "fade",
1795
- onRequestClose: () => setIsOpen(false),
1796
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { style: styles.modalOverlay, onPress: () => setIsOpen(false), children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.modalContent, children: [
1797
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.modalHeader, children: [
1798
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.modalTitle, children: title || "Select Chains" }),
1799
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { onPress: () => setIsOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.modalClose, children: "\u2715" }) })
1800
- ] }),
1801
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.ScrollView, { style: styles.optionsList, showsVerticalScrollIndicator: false, children: supportedChains.map((chain) => {
1802
- const chainInfo = CHAIN_CONFIG[chain] || { name: chain, icon: "\u25CF", color: "#888" };
1803
- const isSelected = selectedChains.includes(chain);
1804
- return /* @__PURE__ */ jsxRuntime.jsxs(
1805
- reactNative.TouchableOpacity,
1806
- {
1807
- style: [
1808
- styles.optionItem,
1809
- isSelected && styles.optionItemSelected,
1810
- isSelected && { backgroundColor: accentColor + "10", borderColor: accentColor }
1811
- ],
1812
- onPress: () => handleSelect(chain),
1813
- activeOpacity: 0.7,
1814
- children: [
1815
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles.optionIconBg, { backgroundColor: chainInfo.color + "20" }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles.optionIcon, { color: chainInfo.color }], children: chainInfo.icon }) }),
1816
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
1817
- styles.optionText,
1818
- isSelected && { color: accentColor, fontWeight: "600" }
1819
- ], children: chainInfo.name }),
1820
- isSelected ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles.checkbox, { backgroundColor: accentColor }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.checkboxIcon, children: "\u2713" }) }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.checkboxEmpty })
1821
- ]
1822
- },
1823
- chain
1824
- );
1825
- }) }),
1826
- multiSelect && /* @__PURE__ */ jsxRuntime.jsx(
1827
- reactNative.TouchableOpacity,
1828
- {
1829
- style: [styles.doneButton, { backgroundColor: accentColor }],
1830
- onPress: () => setIsOpen(false),
1831
- children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles.doneButtonText, children: [
1832
- "Done (",
1833
- selectedChains.length,
1834
- ")"
1835
- ] })
1836
- }
1837
- )
1838
- ] }) })
1839
- }
1840
- )
2853
+ ] }) })
1841
2854
  ] });
1842
2855
  };
1843
2856
  var styles = reactNative.StyleSheet.create({
@@ -1855,207 +2868,51 @@ var styles = reactNative.StyleSheet.create({
1855
2868
  color: "#666",
1856
2869
  marginBottom: 12
1857
2870
  },
1858
- // Desktop styles
1859
- desktopGrid: {
2871
+ chainsContainer: {
1860
2872
  flexDirection: "row",
1861
2873
  flexWrap: "wrap",
1862
- gap: 10
1863
- },
1864
- desktopChip: {
1865
- flexDirection: "row",
1866
- alignItems: "center",
1867
- paddingHorizontal: 14,
1868
- paddingVertical: 10,
1869
- backgroundColor: "#fff",
1870
- borderRadius: 10,
1871
- borderWidth: 2,
1872
- borderColor: "#e8e8e8",
1873
- gap: 10,
1874
- cursor: "pointer"
1875
- },
1876
- desktopChipSelected: {
1877
- borderWidth: 2
1878
- },
1879
- desktopIconBg: {
1880
- width: 32,
1881
- height: 32,
1882
- borderRadius: 16,
1883
- alignItems: "center",
1884
- justifyContent: "center"
1885
- },
1886
- desktopIcon: {
1887
- fontSize: 14,
1888
- fontWeight: "700"
1889
- },
1890
- desktopChipText: {
1891
- fontSize: 14,
1892
- color: "#444"
1893
- },
1894
- desktopCheckbox: {
1895
- width: 20,
1896
- height: 20,
1897
- borderRadius: 10,
1898
- alignItems: "center",
1899
- justifyContent: "center",
1900
- marginLeft: 4
1901
- },
1902
- desktopCheckIcon: {
1903
- fontSize: 12,
1904
- color: "#fff",
1905
- fontWeight: "700"
2874
+ gap: 8
1906
2875
  },
1907
- // Mobile dropdown styles
1908
- dropdownTrigger: {
2876
+ chainChip: {
1909
2877
  flexDirection: "row",
1910
2878
  alignItems: "center",
1911
- justifyContent: "space-between",
1912
- paddingHorizontal: 14,
1913
- paddingVertical: 12,
2879
+ paddingHorizontal: 12,
2880
+ paddingVertical: 8,
1914
2881
  backgroundColor: "#fff",
1915
2882
  borderRadius: 12,
1916
2883
  borderWidth: 2,
1917
2884
  borderColor: "#e5e5e5",
1918
- minHeight: 52
2885
+ gap: 8
1919
2886
  },
1920
- selectedPreview: {
1921
- flex: 1,
1922
- flexDirection: "row",
1923
- alignItems: "center",
1924
- gap: 6
2887
+ chainChipSelected: {
2888
+ borderWidth: 2
1925
2889
  },
1926
- previewChip: {
1927
- width: 32,
1928
- height: 32,
1929
- borderRadius: 16,
2890
+ chainIconBg: {
2891
+ width: 28,
2892
+ height: 28,
2893
+ borderRadius: 14,
1930
2894
  alignItems: "center",
1931
2895
  justifyContent: "center"
1932
2896
  },
1933
- previewIcon: {
2897
+ chainIcon: {
1934
2898
  fontSize: 14,
1935
2899
  fontWeight: "700"
1936
2900
  },
1937
- previewMore: {
1938
- paddingHorizontal: 8,
1939
- paddingVertical: 4,
1940
- backgroundColor: "#f0f0f0",
1941
- borderRadius: 8
1942
- },
1943
- previewMoreText: {
1944
- fontSize: 12,
1945
- color: "#666",
1946
- fontWeight: "600"
1947
- },
1948
- placeholderText: {
2901
+ chainText: {
1949
2902
  fontSize: 14,
1950
- color: "#999"
1951
- },
1952
- dropdownArrow: {
1953
- fontSize: 12,
1954
- color: "#888",
1955
- marginLeft: 8
1956
- },
1957
- selectedCount: {
1958
- fontSize: 12,
1959
- marginTop: 6,
1960
- fontWeight: "500"
1961
- },
1962
- // Modal styles
1963
- modalOverlay: {
1964
- flex: 1,
1965
- backgroundColor: "rgba(0, 0, 0, 0.5)",
1966
- justifyContent: "center",
1967
- alignItems: "center"
1968
- },
1969
- modalContent: {
1970
- width: "85%",
1971
- maxWidth: 340,
1972
- maxHeight: "70%",
1973
- backgroundColor: "#fff",
1974
- borderRadius: 16,
1975
- overflow: "hidden"
1976
- },
1977
- modalHeader: {
1978
- flexDirection: "row",
1979
- justifyContent: "space-between",
1980
- alignItems: "center",
1981
- paddingHorizontal: 16,
1982
- paddingVertical: 14,
1983
- borderBottomWidth: 1,
1984
- borderBottomColor: "#f0f0f0"
1985
- },
1986
- modalTitle: {
1987
- fontSize: 18,
1988
- fontWeight: "700",
1989
- color: "#1a1a1a"
1990
- },
1991
- modalClose: {
1992
- fontSize: 20,
1993
- color: "#888",
1994
- padding: 4
1995
- },
1996
- optionsList: {
1997
- padding: 8
1998
- },
1999
- optionItem: {
2000
- flexDirection: "row",
2001
- alignItems: "center",
2002
- paddingHorizontal: 12,
2003
- paddingVertical: 12,
2004
- borderRadius: 10,
2005
- borderWidth: 1,
2006
- borderColor: "transparent",
2007
- marginBottom: 6,
2008
- gap: 12
2009
- },
2010
- optionItemSelected: {
2011
- borderWidth: 1
2012
- },
2013
- optionIconBg: {
2014
- width: 36,
2015
- height: 36,
2016
- borderRadius: 18,
2017
- alignItems: "center",
2018
- justifyContent: "center"
2903
+ color: "#666"
2019
2904
  },
2020
- optionIcon: {
2905
+ checkmark: {
2021
2906
  fontSize: 16,
2022
2907
  fontWeight: "700"
2023
2908
  },
2024
- optionText: {
2025
- flex: 1,
2026
- fontSize: 15,
2027
- color: "#333"
2028
- },
2029
- checkbox: {
2030
- width: 24,
2031
- height: 24,
2032
- borderRadius: 12,
2033
- alignItems: "center",
2034
- justifyContent: "center"
2035
- },
2036
- checkboxIcon: {
2037
- fontSize: 14,
2038
- color: "#fff",
2039
- fontWeight: "700"
2040
- },
2041
- checkboxEmpty: {
2042
- width: 24,
2043
- height: 24,
2044
- borderRadius: 12,
2045
- borderWidth: 2,
2046
- borderColor: "#ddd"
2047
- },
2048
- doneButton: {
2049
- marginHorizontal: 16,
2050
- marginVertical: 12,
2051
- paddingVertical: 14,
2052
- borderRadius: 10,
2053
- alignItems: "center"
2909
+ selectedInfo: {
2910
+ marginTop: 8,
2911
+ paddingVertical: 4
2054
2912
  },
2055
- doneButtonText: {
2056
- fontSize: 16,
2057
- fontWeight: "600",
2058
- color: "#fff"
2913
+ selectedText: {
2914
+ fontSize: 12,
2915
+ color: "#888"
2059
2916
  }
2060
2917
  });
2061
2918
  var OneTierSelector = ({
@@ -2325,30 +3182,23 @@ var styles3 = reactNative.StyleSheet.create({
2325
3182
  textAlign: "center"
2326
3183
  }
2327
3184
  });
2328
- var PAIR_CONFIG = {
2329
- "BTC": { symbol: "BTC/USDT", name: "Bitcoin", icon: "\u20BF", color: "#F7931A" },
2330
- "ETH": { symbol: "ETH/USDT", name: "Ethereum", icon: "\u039E", color: "#627EEA" },
2331
- "BNB": { symbol: "BNB/USDT", name: "BNB", icon: "\u25C6", color: "#F3BA2F" },
2332
- "SOL": { symbol: "SOL/USDT", name: "Solana", icon: "\u25CE", color: "#9945FF" },
2333
- "XRP": { symbol: "XRP/USDT", name: "Ripple", icon: "\u2715", color: "#23292F" },
2334
- "DOGE": { symbol: "DOGE/USDT", name: "Dogecoin", icon: "\xD0", color: "#C2A633" },
2335
- "ADA": { symbol: "ADA/USDT", name: "Cardano", icon: "\u20B3", color: "#0033AD" },
2336
- "AVAX": { symbol: "AVAX/USDT", name: "Avalanche", icon: "\u25B2", color: "#E84142" },
2337
- "DOT": { symbol: "DOT/USDT", name: "Polkadot", icon: "\u25CF", color: "#E6007A" },
2338
- "MATIC": { symbol: "MATIC/USDT", name: "Polygon", icon: "\u2B21", color: "#8247E5" },
2339
- "LINK": { symbol: "LINK/USDT", name: "Chainlink", icon: "\u25C7", color: "#375BD2" },
2340
- "UNI": { symbol: "UNI/USDT", name: "Uniswap", icon: "\u{1F984}", color: "#FF007A" },
2341
- "ATOM": { symbol: "ATOM/USDT", name: "Cosmos", icon: "\u269B", color: "#2E3148" },
2342
- "LTC": { symbol: "LTC/USDT", name: "Litecoin", icon: "\u0141", color: "#345D9D" },
2343
- "ARB": { symbol: "ARB/USDT", name: "Arbitrum", icon: "\u25C6", color: "#28A0F0" },
2344
- "OP": { symbol: "OP/USDT", name: "Optimism", icon: "\u25C9", color: "#FF0420" }
2345
- };
2346
- var PAIR_ICONS = Object.fromEntries(
2347
- Object.entries(PAIR_CONFIG).map(([key, value]) => [`${key}/USDT`, value.icon])
2348
- );
2349
- var isDesktop2 = () => {
2350
- const { width } = reactNative.Dimensions.get("window");
2351
- return reactNative.Platform.OS === "web" && width >= 768;
3185
+ var PAIR_ICONS = {
3186
+ "BTC/USDT": "\u20BF",
3187
+ "ETH/USDT": "\u039E",
3188
+ "SOL/USDT": "\u25CE",
3189
+ "BNB/USDT": "\u25C6",
3190
+ "XRP/USDT": "\u2715",
3191
+ "DOGE/USDT": "\xD0",
3192
+ "ADA/USDT": "\u25C8",
3193
+ "AVAX/USDT": "\u25B2",
3194
+ "DOT/USDT": "\u25CF",
3195
+ "MATIC/USDT": "\u2B21",
3196
+ "LINK/USDT": "\u25C7",
3197
+ "UNI/USDT": "\u{1F984}",
3198
+ "ATOM/USDT": "\u269B",
3199
+ "LTC/USDT": "\u0141",
3200
+ "ARB/USDT": "\u25C6",
3201
+ "OP/USDT": "\u25C9"
2352
3202
  };
2353
3203
  var OnePairSelector = ({
2354
3204
  supportedPairs,
@@ -2359,12 +3209,9 @@ var OnePairSelector = ({
2359
3209
  subtitle,
2360
3210
  minSelections = 1,
2361
3211
  maxSelections = 0,
2362
- placeholder = "Select trading pairs...",
2363
3212
  style,
2364
3213
  titleStyle
2365
3214
  }) => {
2366
- const [isOpen, setIsOpen] = react.useState(false);
2367
- const desktop = isDesktop2();
2368
3215
  const handleToggle = (pair) => {
2369
3216
  const isSelected = selectedPairs.includes(pair);
2370
3217
  if (isSelected && selectedPairs.length <= minSelections) {
@@ -2375,155 +3222,43 @@ var OnePairSelector = ({
2375
3222
  }
2376
3223
  onTogglePair(pair);
2377
3224
  };
2378
- const getPairInfo = (pair) => {
2379
- return PAIR_CONFIG[pair] || { symbol: `${pair}/USDT`, name: pair, icon: "\u25CF", color: "#888" };
2380
- };
2381
- if (desktop) {
2382
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles4.container, style], children: [
2383
- title && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.title, titleStyle], children: title }),
2384
- subtitle && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.subtitle, children: subtitle }),
2385
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles4.desktopGrid, children: supportedPairs.map((pair) => {
2386
- const pairInfo = getPairInfo(pair);
2387
- const isSelected = selectedPairs.includes(pair);
2388
- const isDisabled = !isSelected && maxSelections > 0 && selectedPairs.length >= maxSelections;
2389
- return /* @__PURE__ */ jsxRuntime.jsxs(
2390
- reactNative.TouchableOpacity,
2391
- {
2392
- style: [
2393
- styles4.desktopChip,
2394
- isSelected && styles4.desktopChipSelected,
2395
- isSelected && { borderColor: accentColor, backgroundColor: accentColor + "12" },
2396
- isDisabled && styles4.desktopChipDisabled
2397
- ],
2398
- onPress: () => handleToggle(pair),
2399
- activeOpacity: isDisabled ? 1 : 0.7,
2400
- children: [
2401
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles4.desktopIconBg, { backgroundColor: pairInfo.color + "20" }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.desktopIcon, { color: pairInfo.color }], children: pairInfo.icon }) }),
2402
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { children: [
2403
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
2404
- styles4.desktopChipText,
2405
- isSelected && { color: accentColor, fontWeight: "600" },
2406
- isDisabled && styles4.desktopTextDisabled
2407
- ], children: pair }),
2408
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.desktopChipSubtext, isDisabled && styles4.desktopTextDisabled], children: pairInfo.name })
2409
- ] }),
2410
- isSelected && /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles4.desktopCheckbox, { backgroundColor: accentColor }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.desktopCheckIcon, children: "\u2713" }) })
2411
- ]
2412
- },
2413
- pair
2414
- );
2415
- }) }),
2416
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.infoRow, children: [
2417
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [styles4.selectedCount, { color: accentColor }], children: [
2418
- selectedPairs.length,
2419
- " pair",
2420
- selectedPairs.length !== 1 ? "s" : "",
2421
- " selected"
2422
- ] }),
2423
- (minSelections > 0 || maxSelections > 0) && /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles4.limitText, children: [
2424
- minSelections > 0 && `min: ${minSelections}`,
2425
- minSelections > 0 && maxSelections > 0 && " / ",
2426
- maxSelections > 0 && `max: ${maxSelections}`
2427
- ] })
2428
- ] })
2429
- ] });
2430
- }
2431
3225
  return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles4.container, style], children: [
2432
3226
  title && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.title, titleStyle], children: title }),
2433
3227
  subtitle && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.subtitle, children: subtitle }),
2434
- /* @__PURE__ */ jsxRuntime.jsxs(
2435
- reactNative.TouchableOpacity,
2436
- {
2437
- style: [styles4.dropdownTrigger, { borderColor: isOpen ? accentColor : "#e5e5e5" }],
2438
- onPress: () => setIsOpen(true),
2439
- activeOpacity: 0.7,
2440
- children: [
2441
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.selectedPreview, children: [
2442
- selectedPairs.slice(0, 4).map((pair) => {
2443
- const pairInfo = getPairInfo(pair);
2444
- return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles4.previewChip, { backgroundColor: pairInfo.color + "20" }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.previewIcon, { color: pairInfo.color }], children: pairInfo.icon }) }, pair);
2445
- }),
2446
- selectedPairs.length > 4 && /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles4.previewMore, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles4.previewMoreText, children: [
2447
- "+",
2448
- selectedPairs.length - 4
2449
- ] }) }),
2450
- selectedPairs.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.placeholderText, children: placeholder })
2451
- ] }),
2452
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.dropdownArrow, children: isOpen ? "\u25B2" : "\u25BC" })
2453
- ]
2454
- }
2455
- ),
2456
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.infoRow, children: [
2457
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [styles4.selectedCount, { color: accentColor }], children: [
2458
- selectedPairs.length,
2459
- " pair",
2460
- selectedPairs.length !== 1 ? "s" : "",
2461
- " selected"
2462
- ] }),
2463
- (minSelections > 0 || maxSelections > 0) && /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles4.limitText, children: [
2464
- minSelections > 0 && `min: ${minSelections}`,
2465
- minSelections > 0 && maxSelections > 0 && " / ",
2466
- maxSelections > 0 && `max: ${maxSelections}`
2467
- ] })
2468
- ] }),
2469
- /* @__PURE__ */ jsxRuntime.jsx(
2470
- reactNative.Modal,
2471
- {
2472
- visible: isOpen,
2473
- transparent: true,
2474
- animationType: "fade",
2475
- onRequestClose: () => setIsOpen(false),
2476
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { style: styles4.modalOverlay, onPress: () => setIsOpen(false), children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.modalContent, children: [
2477
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.modalHeader, children: [
2478
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.modalTitle, children: title || "Select Trading Pairs" }),
2479
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { onPress: () => setIsOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.modalClose, children: "\u2715" }) })
2480
- ] }),
2481
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.ScrollView, { style: styles4.optionsList, showsVerticalScrollIndicator: false, children: supportedPairs.map((pair) => {
2482
- const pairInfo = getPairInfo(pair);
2483
- const isSelected = selectedPairs.includes(pair);
2484
- const isDisabled = !isSelected && maxSelections > 0 && selectedPairs.length >= maxSelections;
2485
- return /* @__PURE__ */ jsxRuntime.jsxs(
2486
- reactNative.TouchableOpacity,
2487
- {
2488
- style: [
2489
- styles4.optionItem,
2490
- isSelected && styles4.optionItemSelected,
2491
- isSelected && { backgroundColor: accentColor + "10", borderColor: accentColor },
2492
- isDisabled && styles4.optionItemDisabled
2493
- ],
2494
- onPress: () => handleToggle(pair),
2495
- activeOpacity: isDisabled ? 1 : 0.7,
2496
- children: [
2497
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles4.optionIconBg, { backgroundColor: pairInfo.color + "20" }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.optionIcon, { color: pairInfo.color }], children: pairInfo.icon }) }),
2498
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.optionTextContainer, children: [
2499
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
2500
- styles4.optionSymbol,
2501
- isSelected && { color: accentColor, fontWeight: "600" },
2502
- isDisabled && styles4.optionTextDisabled
2503
- ], children: pair }),
2504
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.optionName, isDisabled && styles4.optionTextDisabled], children: pairInfo.name })
2505
- ] }),
2506
- isSelected ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles4.checkbox, { backgroundColor: accentColor }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.checkboxIcon, children: "\u2713" }) }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles4.checkboxEmpty, isDisabled && styles4.checkboxDisabled] })
2507
- ]
2508
- },
2509
- pair
2510
- );
2511
- }) }),
2512
- /* @__PURE__ */ jsxRuntime.jsx(
2513
- reactNative.TouchableOpacity,
2514
- {
2515
- style: [styles4.doneButton, { backgroundColor: accentColor }],
2516
- onPress: () => setIsOpen(false),
2517
- children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles4.doneButtonText, children: [
2518
- "Done (",
2519
- selectedPairs.length,
2520
- ")"
2521
- ] })
2522
- }
2523
- )
2524
- ] }) })
2525
- }
2526
- )
3228
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles4.pairsContainer, children: supportedPairs.map((pair) => {
3229
+ const isSelected = selectedPairs.includes(pair);
3230
+ const icon = PAIR_ICONS[pair] || "\u25CF";
3231
+ const baseSymbol = pair.split("/")[0];
3232
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3233
+ reactNative.TouchableOpacity,
3234
+ {
3235
+ style: [
3236
+ styles4.pairChip,
3237
+ isSelected && styles4.pairChipSelected,
3238
+ isSelected && { backgroundColor: accentColor + "15", borderColor: accentColor }
3239
+ ],
3240
+ onPress: () => handleToggle(pair),
3241
+ activeOpacity: 0.7,
3242
+ children: [
3243
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.pairIcon, children: icon }),
3244
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
3245
+ styles4.pairText,
3246
+ isSelected && { color: accentColor, fontWeight: "600" }
3247
+ ], children: baseSymbol }),
3248
+ isSelected && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.checkmark, { color: accentColor }], children: "\u2713" })
3249
+ ]
3250
+ },
3251
+ pair
3252
+ );
3253
+ }) }),
3254
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles4.selectedInfo, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles4.selectedText, children: [
3255
+ selectedPairs.length,
3256
+ " pair",
3257
+ selectedPairs.length !== 1 ? "s" : "",
3258
+ " selected",
3259
+ minSelections > 0 && ` (min: ${minSelections})`,
3260
+ maxSelections > 0 && ` (max: ${maxSelections})`
3261
+ ] }) })
2527
3262
  ] });
2528
3263
  };
2529
3264
  var styles4 = reactNative.StyleSheet.create({
@@ -2541,248 +3276,1432 @@ var styles4 = reactNative.StyleSheet.create({
2541
3276
  color: "#666",
2542
3277
  marginBottom: 12
2543
3278
  },
2544
- // Desktop styles
2545
- desktopGrid: {
3279
+ pairsContainer: {
2546
3280
  flexDirection: "row",
2547
3281
  flexWrap: "wrap",
2548
- gap: 10
3282
+ gap: 8
2549
3283
  },
2550
- desktopChip: {
3284
+ pairChip: {
2551
3285
  flexDirection: "row",
2552
3286
  alignItems: "center",
2553
- paddingHorizontal: 14,
2554
- paddingVertical: 10,
3287
+ paddingHorizontal: 12,
3288
+ paddingVertical: 8,
2555
3289
  backgroundColor: "#fff",
2556
- borderRadius: 10,
2557
- borderWidth: 2,
2558
- borderColor: "#e8e8e8",
2559
- gap: 10,
2560
- cursor: "pointer",
2561
- minWidth: 140
3290
+ borderRadius: 8,
3291
+ borderWidth: 1,
3292
+ borderColor: "#e5e5e5",
3293
+ gap: 6
2562
3294
  },
2563
- desktopChipSelected: {
3295
+ pairChipSelected: {
2564
3296
  borderWidth: 2
2565
3297
  },
2566
- desktopChipDisabled: {
2567
- opacity: 0.5
2568
- },
2569
- desktopIconBg: {
2570
- width: 36,
2571
- height: 36,
2572
- borderRadius: 18,
2573
- alignItems: "center",
2574
- justifyContent: "center"
2575
- },
2576
- desktopIcon: {
2577
- fontSize: 16,
2578
- fontWeight: "700"
3298
+ pairIcon: {
3299
+ fontSize: 14
2579
3300
  },
2580
- desktopChipText: {
3301
+ pairText: {
2581
3302
  fontSize: 14,
2582
- fontWeight: "500",
2583
- color: "#333"
2584
- },
2585
- desktopChipSubtext: {
2586
- fontSize: 11,
2587
- color: "#888",
2588
- marginTop: 1
2589
- },
2590
- desktopTextDisabled: {
2591
- color: "#bbb"
2592
- },
2593
- desktopCheckbox: {
2594
- width: 20,
2595
- height: 20,
2596
- borderRadius: 10,
2597
- alignItems: "center",
2598
- justifyContent: "center",
2599
- marginLeft: "auto"
2600
- },
2601
- desktopCheckIcon: {
2602
- fontSize: 12,
2603
- color: "#fff",
2604
- fontWeight: "700"
2605
- },
2606
- // Mobile dropdown styles
2607
- dropdownTrigger: {
2608
- flexDirection: "row",
2609
- alignItems: "center",
2610
- justifyContent: "space-between",
2611
- paddingHorizontal: 14,
2612
- paddingVertical: 12,
2613
- backgroundColor: "#fff",
2614
- borderRadius: 12,
2615
- borderWidth: 2,
2616
- borderColor: "#e5e5e5",
2617
- minHeight: 52
2618
- },
2619
- selectedPreview: {
2620
- flex: 1,
2621
- flexDirection: "row",
2622
- alignItems: "center",
2623
- gap: 6
2624
- },
2625
- previewChip: {
2626
- width: 32,
2627
- height: 32,
2628
- borderRadius: 16,
2629
- alignItems: "center",
2630
- justifyContent: "center"
3303
+ color: "#666"
2631
3304
  },
2632
- previewIcon: {
3305
+ checkmark: {
2633
3306
  fontSize: 14,
2634
3307
  fontWeight: "700"
2635
3308
  },
2636
- previewMore: {
2637
- paddingHorizontal: 8,
2638
- paddingVertical: 4,
2639
- backgroundColor: "#f0f0f0",
2640
- borderRadius: 8
3309
+ selectedInfo: {
3310
+ marginTop: 8,
3311
+ paddingVertical: 4
2641
3312
  },
2642
- previewMoreText: {
3313
+ selectedText: {
2643
3314
  fontSize: 12,
2644
- color: "#666",
2645
- fontWeight: "600"
2646
- },
2647
- placeholderText: {
2648
- fontSize: 14,
2649
- color: "#999"
2650
- },
2651
- dropdownArrow: {
2652
- fontSize: 12,
2653
- color: "#888",
2654
- marginLeft: 8
2655
- },
2656
- infoRow: {
2657
- flexDirection: "row",
2658
- justifyContent: "space-between",
2659
- alignItems: "center",
2660
- marginTop: 6
2661
- },
2662
- selectedCount: {
2663
- fontSize: 12,
2664
- fontWeight: "500"
2665
- },
2666
- limitText: {
2667
- fontSize: 11,
2668
3315
  color: "#888"
2669
- },
2670
- // Modal styles
2671
- modalOverlay: {
2672
- flex: 1,
2673
- backgroundColor: "rgba(0, 0, 0, 0.5)",
2674
- justifyContent: "center",
2675
- alignItems: "center"
2676
- },
2677
- modalContent: {
2678
- width: "85%",
2679
- maxWidth: 340,
2680
- maxHeight: "75%",
2681
- backgroundColor: "#fff",
2682
- borderRadius: 16,
2683
- overflow: "hidden"
2684
- },
2685
- modalHeader: {
2686
- flexDirection: "row",
2687
- justifyContent: "space-between",
2688
- alignItems: "center",
2689
- paddingHorizontal: 16,
2690
- paddingVertical: 14,
2691
- borderBottomWidth: 1,
2692
- borderBottomColor: "#f0f0f0"
2693
- },
2694
- modalTitle: {
2695
- fontSize: 18,
2696
- fontWeight: "700",
2697
- color: "#1a1a1a"
2698
- },
2699
- modalClose: {
2700
- fontSize: 20,
2701
- color: "#888",
2702
- padding: 4
2703
- },
2704
- optionsList: {
2705
- padding: 8
2706
- },
2707
- optionItem: {
3316
+ }
3317
+ });
3318
+ var OneForexPoolCard = ({
3319
+ pool,
3320
+ poolName,
3321
+ showMetrics = true,
3322
+ accentColor,
3323
+ style,
3324
+ dark = true
3325
+ }) => {
3326
+ const color = accentColor || pool.color;
3327
+ const bg = dark ? "#111111" : "#ffffff";
3328
+ const border = dark ? "#1a1a1a" : "#e5e5e5";
3329
+ const textPrimary = dark ? "#ffffff" : "#1a1a1a";
3330
+ const textSecondary = dark ? "#9ca3af" : "#666666";
3331
+ const textMuted = dark ? "#666666" : "#999999";
3332
+ const barBg = dark ? "#1a1a1a" : "#e5e5e5";
3333
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles5.container, { backgroundColor: bg, borderColor: border }, style], children: [
3334
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles5.header, children: [
3335
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles5.dot, { backgroundColor: color }] }),
3336
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles5.name, { color: textPrimary }], children: poolName || pool.nameKey }),
3337
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [styles5.alloc, { color: textSecondary }], children: [
3338
+ (pool.allocation * 100).toFixed(0),
3339
+ "%"
3340
+ ] })
3341
+ ] }),
3342
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles5.barOuter, { backgroundColor: barBg }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles5.barFill, { width: `${pool.utilization * 100}%`, backgroundColor: color }] }) }),
3343
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles5.statsRow, children: [
3344
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [styles5.statValue, { color: textSecondary }], children: [
3345
+ "$",
3346
+ (pool.totalSize / 1e6).toFixed(1),
3347
+ "M"
3348
+ ] }),
3349
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [styles5.statLabel, { color: textMuted }], children: [
3350
+ (pool.utilization * 100).toFixed(1),
3351
+ "% util"
3352
+ ] })
3353
+ ] }),
3354
+ showMetrics && /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles5.metricsRow, { borderTopColor: border }], children: [
3355
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles5.metricItem, children: [
3356
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles5.metricLabel, { color: textMuted }], children: "APY 7d" }),
3357
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [styles5.metricValue, { color: "#10B981" }], children: [
3358
+ pool.apy7d.toFixed(1),
3359
+ "%"
3360
+ ] })
3361
+ ] }),
3362
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles5.metricItem, children: [
3363
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles5.metricLabel, { color: textMuted }], children: "24h Flow" }),
3364
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [styles5.metricValue, { color: pool.netFlow24h >= 0 ? "#10B981" : "#EF4444" }], children: [
3365
+ pool.netFlow24h >= 0 ? "+" : "",
3366
+ "$",
3367
+ (pool.netFlow24h / 1e3).toFixed(0),
3368
+ "K"
3369
+ ] })
3370
+ ] }),
3371
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles5.metricItem, children: [
3372
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles5.metricLabel, { color: textMuted }], children: "Txs" }),
3373
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles5.metricValue, { color: textPrimary }], children: pool.txCount24h })
3374
+ ] })
3375
+ ] })
3376
+ ] });
3377
+ };
3378
+ var styles5 = reactNative.StyleSheet.create({
3379
+ container: { borderRadius: 8, borderWidth: 1, padding: 14 },
3380
+ header: { flexDirection: "row", alignItems: "center", marginBottom: 8, gap: 8 },
3381
+ dot: { width: 8, height: 8, borderRadius: 4 },
3382
+ name: { fontSize: 13, fontWeight: "600", flex: 1 },
3383
+ alloc: { fontSize: 12 },
3384
+ barOuter: { height: 6, borderRadius: 3, overflow: "hidden", marginBottom: 6 },
3385
+ barFill: { height: "100%", borderRadius: 3 },
3386
+ statsRow: { flexDirection: "row", justifyContent: "space-between" },
3387
+ statValue: { fontSize: 12, fontWeight: "600" },
3388
+ statLabel: { fontSize: 11 },
3389
+ metricsRow: { flexDirection: "row", justifyContent: "space-between", paddingTop: 8, marginTop: 8, borderTopWidth: 1 },
3390
+ metricItem: { alignItems: "center", flex: 1 },
3391
+ metricLabel: { fontSize: 9, textTransform: "uppercase", letterSpacing: 0.5, marginBottom: 2 },
3392
+ metricValue: { fontSize: 12, fontWeight: "600" }
3393
+ });
3394
+
3395
+ // src/components/ai/OneForexCapitalSplit.tsx
3396
+ init_forex();
3397
+ var OneForexCapitalSplit = ({
3398
+ amount,
3399
+ labels = {},
3400
+ showPoolBreakdown = true,
3401
+ style,
3402
+ dark = false
3403
+ }) => {
3404
+ const allocs = computePoolAllocations(amount);
3405
+ const bg = dark ? "#111111" : "#ffffff";
3406
+ const border = dark ? "#1a1a1a" : "#e5e5e5";
3407
+ const textPrimary = dark ? "#ffffff" : "#1a1a1a";
3408
+ const textSecondary = dark ? "#9ca3af" : "#666666";
3409
+ const itemBg = dark ? "#0a0a0a" : "#f5f5f5";
3410
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles6.container, { backgroundColor: bg, borderColor: border }, style], children: [
3411
+ labels.title && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles6.title, { color: textPrimary }], children: labels.title }),
3412
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles6.splitRow, children: [
3413
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles6.splitItem, { backgroundColor: itemBg }], children: [
3414
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles6.dot, { backgroundColor: "#0EA5E9" }] }),
3415
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles6.splitLabel, { color: textSecondary }], children: labels.tradingCapital || "Active Trading (RFQ)" }),
3416
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles6.splitPct, { color: textSecondary }], children: "50%" }),
3417
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [styles6.splitAmt, { color: textPrimary }], children: [
3418
+ "$",
3419
+ allocs.tradingCapital.toLocaleString()
3420
+ ] })
3421
+ ] }),
3422
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles6.splitItem, { backgroundColor: itemBg }], children: [
3423
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles6.dot, { backgroundColor: "#8B5CF6" }] }),
3424
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles6.splitLabel, { color: textSecondary }], children: labels.poolReserves || "Pool Reserves" }),
3425
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles6.splitPct, { color: textSecondary }], children: "50%" }),
3426
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [styles6.splitAmt, { color: textPrimary }], children: [
3427
+ "$",
3428
+ allocs.totalPoolReserves.toLocaleString()
3429
+ ] })
3430
+ ] })
3431
+ ] }),
3432
+ showPoolBreakdown && amount > 0 && /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles6.breakdown, { borderTopColor: border }], children: exports.FOREX_POOL_DEFAULTS.map((pool) => {
3433
+ const poolAmt = allocs[pool.id];
3434
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles6.poolRow, children: [
3435
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles6.poolDot, { backgroundColor: pool.color }] }),
3436
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles6.poolName, { color: textSecondary }], children: labels?.[pool.id] || pool.nameKey }),
3437
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles6.poolBar, { backgroundColor: dark ? "#1a1a1a" : "#e5e5e5" }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles6.poolBarFill, { width: `${pool.allocation * 100}%`, backgroundColor: pool.color }] }) }),
3438
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [styles6.poolAmt, { color: textPrimary }], children: [
3439
+ "$",
3440
+ poolAmt.toLocaleString()
3441
+ ] })
3442
+ ] }, pool.id);
3443
+ }) })
3444
+ ] });
3445
+ };
3446
+ var styles6 = reactNative.StyleSheet.create({
3447
+ container: { borderRadius: 8, borderWidth: 1, padding: 14 },
3448
+ title: { fontSize: 14, fontWeight: "600", marginBottom: 12 },
3449
+ splitRow: { gap: 8 },
3450
+ splitItem: { flexDirection: "row", alignItems: "center", paddingVertical: 10, paddingHorizontal: 12, borderRadius: 8 },
3451
+ dot: { width: 10, height: 10, borderRadius: 5, marginRight: 8 },
3452
+ splitLabel: { flex: 1, fontSize: 13, fontWeight: "500" },
3453
+ splitPct: { fontSize: 12, fontWeight: "600", marginRight: 12 },
3454
+ splitAmt: { fontSize: 14, fontWeight: "700" },
3455
+ breakdown: { marginTop: 12, paddingTop: 12, borderTopWidth: 1 },
3456
+ poolRow: { flexDirection: "row", alignItems: "center", marginBottom: 8 },
3457
+ poolDot: { width: 8, height: 8, borderRadius: 4, marginRight: 8 },
3458
+ poolName: { width: 80, fontSize: 12 },
3459
+ poolBar: { flex: 1, height: 6, borderRadius: 3, overflow: "hidden", marginHorizontal: 8 },
3460
+ poolBarFill: { height: "100%", borderRadius: 3 },
3461
+ poolAmt: { width: 70, fontSize: 12, fontWeight: "600", textAlign: "right" }
3462
+ });
3463
+ var MONO = reactNative.Platform.OS === "ios" ? "Courier New" : "monospace";
3464
+ var OneForexConsoleView = ({
3465
+ logs,
3466
+ maxItems = 100,
3467
+ autoScroll = true,
3468
+ style,
3469
+ height = 400
3470
+ }) => {
3471
+ const scrollRef = react.useRef(null);
3472
+ const visibleLogs = logs.slice(-maxItems);
3473
+ react.useEffect(() => {
3474
+ if (autoScroll && scrollRef.current) {
3475
+ setTimeout(() => scrollRef.current?.scrollToEnd({ animated: true }), 50);
3476
+ }
3477
+ }, [logs.length, autoScroll]);
3478
+ const formatTime = (ts) => {
3479
+ const d = new Date(ts);
3480
+ return `${d.getHours().toString().padStart(2, "0")}:${d.getMinutes().toString().padStart(2, "0")}:${d.getSeconds().toString().padStart(2, "0")}`;
3481
+ };
3482
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles7.container, { height }, style], children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.ScrollView, { ref: scrollRef, style: styles7.scroll, contentContainerStyle: styles7.scrollContent, children: [
3483
+ visibleLogs.map((log) => /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles7.logRow, children: [
3484
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles7.timestamp, children: formatTime(log.timestamp) }),
3485
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles7.type, { color: FOREX_LOG_COLORS[log.type] || "#9CA3AF" }], children: log.type.padEnd(8) }),
3486
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
3487
+ styles7.message,
3488
+ log.importance === "high" && styles7.messageHigh
3489
+ ], numberOfLines: 2, children: log.message })
3490
+ ] }, log.id)),
3491
+ visibleLogs.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles7.emptyText, children: "Waiting for trading activity..." })
3492
+ ] }) });
3493
+ };
3494
+ var T = {
3495
+ base: "#0A0A0C",
3496
+ border: "#2A2A35",
3497
+ muted: "#555560",
3498
+ secondary: "#9CA3AF"
3499
+ };
3500
+ var styles7 = reactNative.StyleSheet.create({
3501
+ container: { backgroundColor: T.base, borderRadius: 8, borderWidth: 1, borderColor: T.border, overflow: "hidden" },
3502
+ scroll: { flex: 1 },
3503
+ scrollContent: { padding: 8 },
3504
+ logRow: { flexDirection: "row", paddingVertical: 3 },
3505
+ timestamp: { fontFamily: MONO, fontSize: 10, color: T.muted, width: 60, marginRight: 6 },
3506
+ type: { fontFamily: MONO, fontSize: 10, fontWeight: "700", width: 65, marginRight: 6 },
3507
+ message: { fontFamily: MONO, fontSize: 10, color: T.secondary, flex: 1 },
3508
+ messageHigh: { color: "#ffffff", fontWeight: "600" },
3509
+ emptyText: { fontFamily: MONO, fontSize: 11, color: T.muted, textAlign: "center", paddingVertical: 40 }
3510
+ });
3511
+
3512
+ // src/components/ai/OneForexPairSelector.tsx
3513
+ init_forex();
3514
+ var OneForexPairSelector = ({
3515
+ selectedPairs,
3516
+ onTogglePair,
3517
+ accentColor = "#0EA5E9",
3518
+ title,
3519
+ subtitle,
3520
+ pairs = exports.FOREX_CURRENCY_PAIRS,
3521
+ style
3522
+ }) => {
3523
+ const handleToggle = (pairId) => {
3524
+ if (selectedPairs.includes(pairId) && selectedPairs.length <= 1) return;
3525
+ onTogglePair(pairId);
3526
+ };
3527
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles8.container, style], children: [
3528
+ title && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles8.title, children: title }),
3529
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles8.subtitle, children: subtitle }),
3530
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles8.pairGrid, children: pairs.map((pair) => {
3531
+ const isSelected = selectedPairs.includes(pair.id);
3532
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3533
+ reactNative.TouchableOpacity,
3534
+ {
3535
+ style: [
3536
+ styles8.pairBtn,
3537
+ isSelected && styles8.pairBtnActive,
3538
+ isSelected && { borderColor: accentColor, backgroundColor: accentColor + "08" }
3539
+ ],
3540
+ onPress: () => handleToggle(pair.id),
3541
+ activeOpacity: 0.7,
3542
+ children: [
3543
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles8.pairFlag, children: pair.flag }),
3544
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles8.pairInfo, children: [
3545
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles8.pairSymbol, isSelected && { color: accentColor, fontWeight: "600" }], children: pair.symbol }),
3546
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles8.pairName, children: pair.name })
3547
+ ] }),
3548
+ isSelected && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles8.check, { color: accentColor }], children: "\u2713" })
3549
+ ]
3550
+ },
3551
+ pair.id
3552
+ );
3553
+ }) }),
3554
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles8.selectedInfo, children: [
3555
+ selectedPairs.length,
3556
+ " pair",
3557
+ selectedPairs.length !== 1 ? "s" : "",
3558
+ " selected (min: 1)"
3559
+ ] })
3560
+ ] });
3561
+ };
3562
+ var styles8 = reactNative.StyleSheet.create({
3563
+ container: { marginBottom: 16 },
3564
+ title: { fontSize: 16, fontWeight: "600", color: "#1a1a1a", marginBottom: 4 },
3565
+ subtitle: { fontSize: 12, color: "#666", marginBottom: 12 },
3566
+ pairGrid: { gap: 8 },
3567
+ pairBtn: {
2708
3568
  flexDirection: "row",
2709
3569
  alignItems: "center",
2710
3570
  paddingHorizontal: 12,
2711
3571
  paddingVertical: 12,
2712
- borderRadius: 10,
2713
- borderWidth: 1,
2714
- borderColor: "transparent",
2715
- marginBottom: 6,
2716
- gap: 12
2717
- },
2718
- optionItemSelected: {
2719
- borderWidth: 1
2720
- },
2721
- optionItemDisabled: {
2722
- opacity: 0.5
2723
- },
2724
- optionIconBg: {
2725
- width: 40,
2726
- height: 40,
2727
- borderRadius: 20,
2728
- alignItems: "center",
2729
- justifyContent: "center"
2730
- },
2731
- optionIcon: {
2732
- fontSize: 18,
2733
- fontWeight: "700"
2734
- },
2735
- optionTextContainer: {
2736
- flex: 1
2737
- },
2738
- optionSymbol: {
2739
- fontSize: 15,
2740
- fontWeight: "500",
2741
- color: "#333"
2742
- },
2743
- optionName: {
2744
- fontSize: 12,
2745
- color: "#888",
2746
- marginTop: 1
2747
- },
2748
- optionTextDisabled: {
2749
- color: "#bbb"
2750
- },
2751
- checkbox: {
2752
- width: 24,
2753
- height: 24,
2754
- borderRadius: 12,
2755
- alignItems: "center",
2756
- justifyContent: "center"
2757
- },
2758
- checkboxIcon: {
2759
- fontSize: 14,
2760
- color: "#fff",
2761
- fontWeight: "700"
2762
- },
2763
- checkboxEmpty: {
2764
- width: 24,
2765
- height: 24,
2766
- borderRadius: 12,
2767
- borderWidth: 2,
2768
- borderColor: "#ddd"
3572
+ borderRadius: 8,
3573
+ borderWidth: 1.5,
3574
+ borderColor: "#e5e5e5",
3575
+ backgroundColor: "#fff",
3576
+ gap: 10
2769
3577
  },
2770
- checkboxDisabled: {
2771
- borderColor: "#eee"
3578
+ pairBtnActive: { borderWidth: 2 },
3579
+ pairFlag: { fontSize: 20 },
3580
+ pairInfo: { flex: 1 },
3581
+ pairSymbol: { fontSize: 14, color: "#666" },
3582
+ pairName: { fontSize: 11, color: "#999" },
3583
+ check: { fontSize: 16, fontWeight: "700" },
3584
+ selectedInfo: { fontSize: 12, color: "#888", marginTop: 8 }
3585
+ });
3586
+ var MONO2 = reactNative.Platform.OS === "ios" ? "Courier New" : "monospace";
3587
+ var OneForexTradeHistory = ({
3588
+ trades,
3589
+ maxItems = 50,
3590
+ showSettlementDetails = true,
3591
+ showTxHash = true,
3592
+ emptyText = "No trade history yet",
3593
+ style
3594
+ }) => {
3595
+ const visibleTrades = trades.slice(-maxItems).reverse();
3596
+ if (visibleTrades.length === 0) {
3597
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles9.empty, style], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles9.emptyText, children: emptyText }) });
3598
+ }
3599
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.ScrollView, { style: [styles9.container, style], contentContainerStyle: styles9.scrollContent, children: visibleTrades.map((trade) => /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles9.card, children: [
3600
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles9.header, children: [
3601
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles9.pair, children: trade.pairSymbol }),
3602
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [
3603
+ styles9.sideBadge,
3604
+ { backgroundColor: trade.side === "BUY" ? "#10B98118" : "#EF444418", borderColor: trade.side === "BUY" ? "#10B98140" : "#EF444440" }
3605
+ ], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles9.sideText, { color: trade.side === "BUY" ? "#10B981" : "#EF4444" }], children: trade.side }) }),
3606
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [styles9.pnl, { color: trade.pnl >= 0 ? "#10B981" : "#EF4444" }], children: [
3607
+ trade.pnl >= 0 ? "+" : "",
3608
+ "$",
3609
+ trade.pnl.toFixed(2)
3610
+ ] })
3611
+ ] }),
3612
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles9.details, children: [
3613
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles9.detail, children: [
3614
+ trade.lots.toFixed(2),
3615
+ " lots | ",
3616
+ trade.pips >= 0 ? "+" : "",
3617
+ trade.pips.toFixed(1),
3618
+ " pips"
3619
+ ] }),
3620
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles9.time, children: new Date(trade.timestamp).toLocaleString() })
3621
+ ] }),
3622
+ showSettlementDetails && trade.clearingFee !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles9.settlement, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles9.settlementText, children: [
3623
+ "CLR: $",
3624
+ trade.clearingFee.toFixed(2),
3625
+ " | HDG: $",
3626
+ (trade.hedgingCost || 0).toFixed(2),
3627
+ " | INS: $",
3628
+ (trade.insuranceReserve || 0).toFixed(2)
3629
+ ] }) }),
3630
+ showTxHash && trade.txHash && /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles9.txHash, children: [
3631
+ trade.txHash.slice(0, 10),
3632
+ "...",
3633
+ trade.txHash.slice(-6)
3634
+ ] })
3635
+ ] }, trade.id)) });
3636
+ };
3637
+ var styles9 = reactNative.StyleSheet.create({
3638
+ container: { flex: 1 },
3639
+ scrollContent: { paddingBottom: 16 },
3640
+ empty: { alignItems: "center", justifyContent: "center", padding: 40 },
3641
+ emptyText: { fontSize: 14, color: "#666" },
3642
+ card: { backgroundColor: "#111111", borderRadius: 6, borderWidth: 1, borderColor: "#1a1a1a", padding: 12, marginBottom: 8 },
3643
+ header: { flexDirection: "row", alignItems: "center", gap: 8 },
3644
+ pair: { fontSize: 13, fontWeight: "600", color: "#ffffff" },
3645
+ sideBadge: { paddingHorizontal: 6, paddingVertical: 2, borderRadius: 3, borderWidth: 1 },
3646
+ sideText: { fontSize: 9, fontWeight: "700", letterSpacing: 0.5 },
3647
+ pnl: { fontFamily: MONO2, marginLeft: "auto", fontSize: 13, fontWeight: "700" },
3648
+ details: { flexDirection: "row", justifyContent: "space-between", marginTop: 6 },
3649
+ detail: { fontFamily: MONO2, fontSize: 11, color: "#9ca3af" },
3650
+ time: { fontSize: 11, color: "#666" },
3651
+ settlement: { marginTop: 6, paddingTop: 6, borderTopWidth: 1, borderTopColor: "#1a1a1a" },
3652
+ settlementText: { fontFamily: MONO2, fontSize: 10, color: "#666" },
3653
+ txHash: { fontFamily: MONO2, fontSize: 9, color: "#444", marginTop: 2 }
3654
+ });
3655
+
3656
+ // src/hooks/useForexTrading.ts
3657
+ init_forex();
3658
+ var _forexAccessToken = null;
3659
+ var _forexEngineUrl = "https://api.one23.io";
3660
+ function setForexAccessToken(token) {
3661
+ _forexAccessToken = token;
3662
+ }
3663
+ function clearForexAccessToken() {
3664
+ _forexAccessToken = null;
3665
+ }
3666
+ function setForexEngineUrl(url) {
3667
+ _forexEngineUrl = url;
3668
+ }
3669
+ async function forexApi(path, options) {
3670
+ try {
3671
+ const headers = {
3672
+ "Content-Type": "application/json"
3673
+ };
3674
+ if (_forexAccessToken) {
3675
+ headers["Authorization"] = `Bearer ${_forexAccessToken}`;
3676
+ }
3677
+ const res = await fetch(`${_forexEngineUrl}${path}`, { ...options, headers });
3678
+ if (!res.ok) return null;
3679
+ const json = await res.json();
3680
+ return json?.data ?? json;
3681
+ } catch {
3682
+ return null;
3683
+ }
3684
+ }
3685
+ function useForexPools(options) {
3686
+ const [pools, setPools] = react.useState(exports.FOREX_POOL_DEFAULTS);
3687
+ const [isLoading, setIsLoading] = react.useState(false);
3688
+ const [error, setError] = react.useState(null);
3689
+ const fetchPools = react.useCallback(async () => {
3690
+ setIsLoading(true);
3691
+ try {
3692
+ const data = await forexApi("/api/forex/pools");
3693
+ if (data?.pools) {
3694
+ setPools(data.pools.map((p) => ({
3695
+ id: p.type ?? p.id,
3696
+ nameKey: `forex.pool_${p.type ?? p.id}`,
3697
+ descriptionKey: `forex.pool_${p.type ?? p.id}_desc`,
3698
+ allocation: p.allocation ?? (p.type === "clearing" ? 0.5 : p.type === "hedging" ? 0.3 : 0.2),
3699
+ totalSize: p.totalSize ?? p.total_size ?? 0,
3700
+ utilization: p.utilization ?? 0,
3701
+ color: p.type === "clearing" ? "#3B82F6" : p.type === "hedging" ? "#F59E0B" : "#10B981",
3702
+ apy7d: p.apy7d ?? 0,
3703
+ apy30d: p.apy30d ?? 0,
3704
+ netFlow24h: p.netFlow24h ?? 0,
3705
+ txCount24h: p.txCount24h ?? 0,
3706
+ txCountTotal: p.txCountTotal ?? 0,
3707
+ totalDeposits: p.totalDeposits ?? 0,
3708
+ totalWithdrawals: p.totalWithdrawals ?? 0,
3709
+ profitDistributed: p.profitDistributed ?? 0,
3710
+ lastUpdated: p.lastUpdated ?? Date.now()
3711
+ })));
3712
+ }
3713
+ setError(null);
3714
+ } catch (err) {
3715
+ setError(err instanceof Error ? err.message : "Failed to fetch pools");
3716
+ } finally {
3717
+ setIsLoading(false);
3718
+ }
3719
+ }, []);
3720
+ react.useEffect(() => {
3721
+ fetchPools();
3722
+ if (options?.refreshInterval) {
3723
+ const timer = setInterval(fetchPools, options.refreshInterval);
3724
+ return () => clearInterval(timer);
3725
+ }
3726
+ }, [fetchPools, options?.refreshInterval]);
3727
+ return { pools, isLoading, error, refresh: fetchPools };
3728
+ }
3729
+ function useForexInvestments(options) {
3730
+ const [investments, setInvestments] = react.useState([]);
3731
+ const [isLoading, setIsLoading] = react.useState(false);
3732
+ const [error, setError] = react.useState(null);
3733
+ const fetchInvestments = react.useCallback(async () => {
3734
+ setIsLoading(true);
3735
+ try {
3736
+ const data = await forexApi("/api/forex/investments");
3737
+ if (data?.investments) {
3738
+ setInvestments(data.investments.map(mapInvestment));
3739
+ }
3740
+ setError(null);
3741
+ } catch {
3742
+ setError("Failed to fetch investments");
3743
+ } finally {
3744
+ setIsLoading(false);
3745
+ }
3746
+ }, []);
3747
+ const createInvestment = react.useCallback(async (params) => {
3748
+ setIsLoading(true);
3749
+ try {
3750
+ const data = await forexApi("/api/forex/investments", {
3751
+ method: "POST",
3752
+ body: JSON.stringify(params)
3753
+ });
3754
+ if (data?.investment) {
3755
+ const inv2 = mapInvestment(data.investment);
3756
+ setInvestments((prev) => [inv2, ...prev]);
3757
+ return inv2;
3758
+ }
3759
+ const inv = createLocalInvestment(params);
3760
+ setInvestments((prev) => [inv, ...prev]);
3761
+ return inv;
3762
+ } catch {
3763
+ const inv = createLocalInvestment(params);
3764
+ setInvestments((prev) => [inv, ...prev]);
3765
+ return inv;
3766
+ } finally {
3767
+ setIsLoading(false);
3768
+ }
3769
+ }, []);
3770
+ const redeemInvestment = react.useCallback(async (investmentId) => {
3771
+ try {
3772
+ await forexApi(`/api/forex/investments/${investmentId}/redeem`, { method: "POST" });
3773
+ setInvestments((prev) => prev.map(
3774
+ (inv) => inv.id === investmentId ? { ...inv, status: "redeemed" } : inv
3775
+ ));
3776
+ return true;
3777
+ } catch {
3778
+ return false;
3779
+ }
3780
+ }, []);
3781
+ react.useEffect(() => {
3782
+ fetchInvestments();
3783
+ if (options?.refreshInterval) {
3784
+ const timer = setInterval(fetchInvestments, options.refreshInterval);
3785
+ return () => clearInterval(timer);
3786
+ }
3787
+ }, [fetchInvestments, options?.refreshInterval]);
3788
+ const portfolioSummary = react.useMemo(() => {
3789
+ const active = investments.filter((i) => i.status === "active");
3790
+ return {
3791
+ totalInvested: active.reduce((s, i) => s + i.amount, 0),
3792
+ totalValue: active.reduce((s, i) => s + i.currentValue, 0),
3793
+ totalProfit: active.reduce((s, i) => s + i.profit, 0),
3794
+ activeCount: active.length
3795
+ };
3796
+ }, [investments]);
3797
+ return { investments, isLoading, error, createInvestment, redeemInvestment, refresh: fetchInvestments, portfolioSummary };
3798
+ }
3799
+ function useForexSimulation(options) {
3800
+ const maxLogs = options?.maxLogs ?? 500;
3801
+ const [logs, setLogs] = react.useState([]);
3802
+ const [poolTxs, setPoolTxs] = react.useState([]);
3803
+ const [isRunning, setIsRunning] = react.useState(false);
3804
+ const [stats, setStats] = react.useState({ totalPnl: 0, totalTrades: 0, totalPips: 0, totalLots: 0 });
3805
+ const engineRef = react.useRef(null);
3806
+ const getEngine = react.useCallback(() => {
3807
+ if (!engineRef.current) {
3808
+ try {
3809
+ const { forexSimulationEngine: forexSimulationEngine2 } = (init_ForexSimulationEngine(), __toCommonJS(ForexSimulationEngine_exports));
3810
+ engineRef.current = forexSimulationEngine2;
3811
+ } catch {
3812
+ }
3813
+ }
3814
+ return engineRef.current;
3815
+ }, []);
3816
+ const start = react.useCallback(() => {
3817
+ const engine = getEngine();
3818
+ if (!engine) return;
3819
+ if (!engine.isRunning()) engine.start();
3820
+ setIsRunning(true);
3821
+ }, [getEngine]);
3822
+ const stop = react.useCallback(() => {
3823
+ const engine = getEngine();
3824
+ if (engine) engine.stop();
3825
+ setIsRunning(false);
3826
+ }, [getEngine]);
3827
+ const clearLogs = react.useCallback(() => {
3828
+ setLogs([]);
3829
+ setPoolTxs([]);
3830
+ }, []);
3831
+ react.useEffect(() => {
3832
+ const engine = getEngine();
3833
+ if (!engine) return;
3834
+ const unsubLog = engine.onLog((entry) => {
3835
+ setLogs((prev) => {
3836
+ const next = [...prev, entry];
3837
+ return next.length > maxLogs ? next.slice(-maxLogs) : next;
3838
+ });
3839
+ const s = engine.getStats();
3840
+ setStats({ totalPnl: s.totalPnl, totalTrades: s.totalTrades, totalPips: s.totalPips, totalLots: s.totalLots });
3841
+ });
3842
+ const unsubTx = engine.onPoolTransaction((tx) => {
3843
+ setPoolTxs((prev) => [...prev.slice(-999), tx]);
3844
+ });
3845
+ return () => {
3846
+ unsubLog();
3847
+ unsubTx();
3848
+ };
3849
+ }, [getEngine, maxLogs]);
3850
+ return { logs, poolTransactions: poolTxs, isRunning, stats, start, stop, clearLogs };
3851
+ }
3852
+ function useForexPoolData() {
3853
+ const [snapshots, setSnapshots] = react.useState({ clearing: [], hedging: [], insurance: [] });
3854
+ const [transactions, setTransactions] = react.useState([]);
3855
+ const [isInitialized, setIsInitialized] = react.useState(false);
3856
+ const initialize = react.useCallback(() => {
3857
+ if (isInitialized) return;
3858
+ try {
3859
+ const { ForexPoolDataGenerator: ForexPoolDataGenerator2 } = (init_ForexPoolDataGenerator(), __toCommonJS(ForexPoolDataGenerator_exports));
3860
+ const gen = ForexPoolDataGenerator2.getInstance();
3861
+ setSnapshots(gen.generateAllSnapshots());
3862
+ setTransactions(gen.generateAllTransactions());
3863
+ setIsInitialized(true);
3864
+ } catch {
3865
+ }
3866
+ }, [isInitialized]);
3867
+ return { snapshots, transactions, isInitialized, initialize };
3868
+ }
3869
+ function useForexTrading(options) {
3870
+ const pools = useForexPools({ refreshInterval: options?.poolRefreshInterval });
3871
+ const investments = useForexInvestments({ refreshInterval: options?.investmentRefreshInterval });
3872
+ const simulation = useForexSimulation();
3873
+ const poolData = useForexPoolData();
3874
+ return {
3875
+ pools,
3876
+ investments,
3877
+ simulation,
3878
+ poolData,
3879
+ capitalSplit: exports.FOREX_CAPITAL_SPLIT,
3880
+ agent: exports.FOREX_AGENT,
3881
+ currencyPairs: (init_forex(), __toCommonJS(forex_exports)).FOREX_CURRENCY_PAIRS,
3882
+ cycleOptions: (init_forex(), __toCommonJS(forex_exports)).FOREX_CYCLE_OPTIONS,
3883
+ computePoolAllocations,
3884
+ estimateProfit: estimateForexProfit
3885
+ };
3886
+ }
3887
+ function mapInvestment(raw) {
3888
+ const cycleDays = raw.cycleDays ?? raw.cycle_days ?? 90;
3889
+ const cycleOption = exports.FOREX_CYCLE_OPTIONS.find((c) => c.days === cycleDays) || exports.FOREX_CYCLE_OPTIONS[2];
3890
+ const amount = typeof raw.amount === "string" ? parseFloat(raw.amount) : raw.amount ?? 0;
3891
+ const allocs = computePoolAllocations(amount);
3892
+ return {
3893
+ id: raw.id,
3894
+ userId: raw.userId ?? raw.user_id,
3895
+ amount,
3896
+ currentValue: raw.currentValue ?? raw.current_value ?? amount,
3897
+ profit: raw.profit ?? 0,
3898
+ status: raw.status ?? "active",
3899
+ selectedPairs: raw.selectedPairs ?? raw.selected_pairs ?? [],
3900
+ cycleDays,
3901
+ cycleOption,
3902
+ feeRate: raw.feeRate ?? cycleOption.feeRate,
3903
+ commissionRate: raw.commissionRate ?? cycleOption.commissionRate,
3904
+ startDate: raw.startDate ?? raw.start_date ?? (/* @__PURE__ */ new Date()).toISOString(),
3905
+ endDate: raw.endDate ?? raw.end_date ?? "",
3906
+ tradingCapital: raw.tradingCapital ?? allocs.tradingCapital,
3907
+ totalPoolReserves: raw.totalPoolReserves ?? allocs.totalPoolReserves,
3908
+ poolAllocations: raw.poolAllocations ?? {
3909
+ clearing: allocs.clearing,
3910
+ hedging: allocs.hedging,
3911
+ insurance: allocs.insurance
3912
+ },
3913
+ tradeWeight: raw.tradeWeight ?? 0,
3914
+ totalLots: raw.totalLots ?? 0,
3915
+ totalPips: raw.totalPips ?? 0,
3916
+ totalTrades: raw.totalTrades ?? 0,
3917
+ positions: raw.positions ?? [],
3918
+ tradeHistory: raw.tradeHistory ?? [],
3919
+ redeemedAt: raw.redeemedAt,
3920
+ createdAt: raw.createdAt,
3921
+ updatedAt: raw.updatedAt
3922
+ };
3923
+ }
3924
+ function createLocalInvestment(params) {
3925
+ const { amount, selectedPairs, cycleDays } = params;
3926
+ const cycleOption = exports.FOREX_CYCLE_OPTIONS.find((c) => c.days === cycleDays) || exports.FOREX_CYCLE_OPTIONS[2];
3927
+ const allocs = computePoolAllocations(amount);
3928
+ const now = /* @__PURE__ */ new Date();
3929
+ const endDate = new Date(now);
3930
+ endDate.setDate(endDate.getDate() + cycleDays);
3931
+ return {
3932
+ id: `fx_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
3933
+ amount,
3934
+ currentValue: amount,
3935
+ profit: 0,
3936
+ status: "active",
3937
+ selectedPairs,
3938
+ cycleDays,
3939
+ cycleOption,
3940
+ startDate: now.toISOString(),
3941
+ endDate: endDate.toISOString(),
3942
+ tradingCapital: allocs.tradingCapital,
3943
+ totalPoolReserves: allocs.totalPoolReserves,
3944
+ poolAllocations: { clearing: allocs.clearing, hedging: allocs.hedging, insurance: allocs.insurance },
3945
+ tradeWeight: 0,
3946
+ totalLots: 0,
3947
+ totalPips: 0,
3948
+ totalTrades: 0,
3949
+ positions: [],
3950
+ tradeHistory: []
3951
+ };
3952
+ }
3953
+
3954
+ // src/react-native.ts
3955
+ init_ForexSimulationEngine();
3956
+ init_ForexPoolDataGenerator();
3957
+
3958
+ // src/services/forex/BotSimulationEngine.ts
3959
+ var STRATEGY_PERSONALITIES = [
3960
+ {
3961
+ id: "balanced-01",
3962
+ name: "Balanced Alpha",
3963
+ shortName: "BAL",
3964
+ color: "#3B82F6",
3965
+ scanIntervalMin: 25e3,
3966
+ // Slower: 25-40s between cycles
3967
+ scanIntervalMax: 4e4,
3968
+ tradeFrequency: 0.4,
3969
+ positionSizeMin: 15,
3970
+ positionSizeMax: 35,
3971
+ leverageMin: 3,
3972
+ leverageMax: 10,
3973
+ primaryIndicators: ["RSI", "MACD"],
3974
+ riskTolerance: "medium",
3975
+ preferredPairs: ["BTC/USDT", "ETH/USDT", "SOL/USDT"],
3976
+ rsiBias: 50
2772
3977
  },
2773
- doneButton: {
2774
- marginHorizontal: 16,
2775
- marginVertical: 12,
2776
- paddingVertical: 14,
2777
- borderRadius: 10,
2778
- alignItems: "center"
3978
+ {
3979
+ id: "conservative-01",
3980
+ name: "Conservative Shield",
3981
+ shortName: "CON",
3982
+ color: "#10B981",
3983
+ scanIntervalMin: 35e3,
3984
+ // Slower: 35-55s between cycles
3985
+ scanIntervalMax: 55e3,
3986
+ tradeFrequency: 0.25,
3987
+ positionSizeMin: 10,
3988
+ positionSizeMax: 20,
3989
+ leverageMin: 2,
3990
+ leverageMax: 5,
3991
+ primaryIndicators: ["Bollinger", "Volume"],
3992
+ riskTolerance: "low",
3993
+ preferredPairs: ["BTC/USDT", "ETH/USDT"],
3994
+ rsiBias: 45
2779
3995
  },
2780
- doneButtonText: {
2781
- fontSize: 16,
2782
- fontWeight: "600",
2783
- color: "#fff"
3996
+ {
3997
+ id: "aggressive-01",
3998
+ name: "Aggressive Momentum",
3999
+ shortName: "AGG",
4000
+ color: "#EF4444",
4001
+ scanIntervalMin: 18e3,
4002
+ // Slower: 18-30s between cycles
4003
+ scanIntervalMax: 3e4,
4004
+ tradeFrequency: 0.5,
4005
+ positionSizeMin: 25,
4006
+ positionSizeMax: 50,
4007
+ leverageMin: 5,
4008
+ leverageMax: 20,
4009
+ primaryIndicators: ["RSI", "MACD", "EMA", "Volume"],
4010
+ riskTolerance: "high",
4011
+ preferredPairs: ["BTC/USDT", "ETH/USDT", "SOL/USDT", "DOGE/USDT", "AVAX/USDT"],
4012
+ rsiBias: 55
4013
+ }
4014
+ ];
4015
+ var PAIR_PRICES = {
4016
+ "BTC/USDT": 67500,
4017
+ "ETH/USDT": 3450,
4018
+ "BNB/USDT": 605,
4019
+ "SOL/USDT": 178,
4020
+ "XRP/USDT": 0.62,
4021
+ "DOGE/USDT": 0.165,
4022
+ "ADA/USDT": 0.45,
4023
+ "AVAX/USDT": 38.5,
4024
+ "ARB/USDT": 1.18,
4025
+ "MATIC/USDT": 0.72,
4026
+ "LINK/USDT": 14.5,
4027
+ "UNI/USDT": 7.8,
4028
+ "AAVE/USDT": 92,
4029
+ "OP/USDT": 2.45,
4030
+ "APT/USDT": 8.9,
4031
+ "INJ/USDT": 24.5,
4032
+ "TIA/USDT": 11.2,
4033
+ "SUI/USDT": 1.65,
4034
+ "DOT/USDT": 7.2,
4035
+ "ATOM/USDT": 9.8,
4036
+ "FIL/USDT": 5.6,
4037
+ "LTC/USDT": 72,
4038
+ "NEAR/USDT": 5.1,
4039
+ "FTM/USDT": 0.42
4040
+ };
4041
+ var CHAIN_INFO = {
4042
+ ethereum: { name: "Ethereum", shortName: "ETH", icon: "\u039E" },
4043
+ arbitrum: { name: "Arbitrum", shortName: "ARB", icon: "\u25C6" },
4044
+ bsc: { name: "BSC", shortName: "BSC", icon: "\u25C6" },
4045
+ base: { name: "Base", shortName: "BASE", icon: "\u25CF" },
4046
+ polygon: { name: "Polygon", shortName: "POLY", icon: "\u2B21" },
4047
+ optimism: { name: "Optimism", shortName: "OP", icon: "\u25C9" },
4048
+ avalanche: { name: "Avalanche", shortName: "AVAX", icon: "\u25B2" },
4049
+ linea: { name: "Linea", shortName: "LINEA", icon: "\u2550" },
4050
+ zksync: { name: "zkSync", shortName: "ZK", icon: "\u2B22" },
4051
+ scroll: { name: "Scroll", shortName: "SCRL", icon: "\u25CE" }
4052
+ };
4053
+ var NEWS_HEADLINES = [
4054
+ "Fed signals potential rate pause, crypto markets react positively",
4055
+ "Major institutional investor increases BTC allocation by 15%",
4056
+ "On-chain data shows whale accumulation pattern forming",
4057
+ "DeFi TVL reaches new monthly high across major protocols",
4058
+ "Exchange outflows surge as holders move to cold storage",
4059
+ "Options market signals increased volatility expected this week",
4060
+ "Mining difficulty adjustment approaching, hash rate stable",
4061
+ "Regulatory clarity in EU boosts market sentiment",
4062
+ "Stablecoin supply expanding, potential bullish indicator",
4063
+ "Social sentiment score shifts to extreme greed zone",
4064
+ "Cross-chain bridge volume hits record daily high",
4065
+ "Layer 2 adoption metrics show 40% MoM growth"
4066
+ ];
4067
+ var idCounter2 = 0;
4068
+ function genId3() {
4069
+ return `log_${Date.now()}_${++idCounter2}`;
4070
+ }
4071
+ function rand3(min, max) {
4072
+ return min + Math.random() * (max - min);
4073
+ }
4074
+ function randInt3(min, max) {
4075
+ return Math.floor(rand3(min, max + 1));
4076
+ }
4077
+ function pick4(arr) {
4078
+ return arr[Math.floor(Math.random() * arr.length)];
4079
+ }
4080
+ function clamp(val, min, max) {
4081
+ return Math.max(min, Math.min(max, val));
4082
+ }
4083
+ function formatPrice(price) {
4084
+ if (price >= 1e3) return price.toFixed(2);
4085
+ if (price >= 1) return price.toFixed(3);
4086
+ return price.toFixed(5);
4087
+ }
4088
+ var BotSimulationEngine = class {
4089
+ constructor() {
4090
+ this.listeners = [];
4091
+ this.botTimers = /* @__PURE__ */ new Map();
4092
+ this.botStates = /* @__PURE__ */ new Map();
4093
+ this.priceState = /* @__PURE__ */ new Map();
4094
+ this.indicatorState = /* @__PURE__ */ new Map();
4095
+ this.running = false;
4096
+ this.userPairs = [];
4097
+ this.userChains = [];
4098
+ for (const [pair, base] of Object.entries(PAIR_PRICES)) {
4099
+ this.priceState.set(pair, base * (1 + rand3(-0.02, 0.02)));
4100
+ }
2784
4101
  }
2785
- });
4102
+ // ── Public API ─────────────────────────────────────────────────────────────
4103
+ getStrategies() {
4104
+ return STRATEGY_PERSONALITIES;
4105
+ }
4106
+ start(strategyIds, userPairs, userChains) {
4107
+ this.running = true;
4108
+ this.userPairs = (userPairs || []).map((p) => p.includes("/") ? p : `${p}/USDT`).filter((p) => p in PAIR_PRICES);
4109
+ this.userChains = (userChains || []).filter((c) => c in CHAIN_INFO);
4110
+ const strategies = strategyIds ? STRATEGY_PERSONALITIES.filter((s) => strategyIds.includes(s.id)) : STRATEGY_PERSONALITIES;
4111
+ for (const strategy of strategies) {
4112
+ this.initBotState(strategy);
4113
+ this.scheduleCycle(strategy);
4114
+ }
4115
+ }
4116
+ stop(strategyIds) {
4117
+ const ids = strategyIds || Array.from(this.botTimers.keys());
4118
+ for (const id of ids) {
4119
+ const timer = this.botTimers.get(id);
4120
+ if (timer) {
4121
+ clearTimeout(timer);
4122
+ this.botTimers.delete(id);
4123
+ }
4124
+ }
4125
+ if (!strategyIds) {
4126
+ this.running = false;
4127
+ }
4128
+ }
4129
+ onLog(callback) {
4130
+ this.listeners.push(callback);
4131
+ return () => {
4132
+ this.listeners = this.listeners.filter((l) => l !== callback);
4133
+ };
4134
+ }
4135
+ getBotState(strategyId) {
4136
+ return this.botStates.get(strategyId);
4137
+ }
4138
+ getAllBotStates() {
4139
+ return this.botStates;
4140
+ }
4141
+ isRunning() {
4142
+ return this.running;
4143
+ }
4144
+ emitBootSequence() {
4145
+ const bootMessages = [
4146
+ { msg: "Initializing ONE Trading Engine v3.2.1...", delay: 0 },
4147
+ { msg: "Loading market data feeds...", delay: 500 },
4148
+ { msg: "Connecting to exchange WebSocket streams...", delay: 1200 },
4149
+ { msg: "Calibrating indicator engines (RSI, MACD, EMA, Bollinger)...", delay: 2e3 },
4150
+ { msg: "Loading strategy personalities: balanced-01, conservative-01, aggressive-01", delay: 2800 },
4151
+ { msg: "Risk management module initialized (max drawdown: 15%)", delay: 3600 },
4152
+ { msg: "Portfolio allocation engine ready", delay: 4200 },
4153
+ { msg: "=== All systems online. Starting trading cycles ===", delay: 5e3 }
4154
+ ];
4155
+ for (const { msg, delay } of bootMessages) {
4156
+ setTimeout(() => {
4157
+ this.emit({
4158
+ id: genId3(),
4159
+ timestamp: Date.now(),
4160
+ strategyId: "system",
4161
+ strategyName: "SYSTEM",
4162
+ type: "SYSTEM",
4163
+ message: msg,
4164
+ importance: "medium"
4165
+ });
4166
+ }, delay);
4167
+ }
4168
+ }
4169
+ destroy() {
4170
+ this.stop();
4171
+ this.listeners = [];
4172
+ this.botStates.clear();
4173
+ this.priceState.clear();
4174
+ this.indicatorState.clear();
4175
+ this.userPairs = [];
4176
+ this.userChains = [];
4177
+ }
4178
+ // ── Private Methods ────────────────────────────────────────────────────────
4179
+ emit(entry) {
4180
+ for (const listener of this.listeners) {
4181
+ listener(entry);
4182
+ }
4183
+ }
4184
+ getActivePairs(strategy) {
4185
+ return this.userPairs.length > 0 ? this.userPairs : strategy.preferredPairs;
4186
+ }
4187
+ getActiveChain() {
4188
+ const chains = this.userChains.length > 0 ? this.userChains : ["ethereum", "arbitrum", "bsc"];
4189
+ return pick4(chains);
4190
+ }
4191
+ getChainLabel(chainId) {
4192
+ const info = CHAIN_INFO[chainId];
4193
+ return info ? info.shortName : chainId;
4194
+ }
4195
+ initBotState(strategy) {
4196
+ const activePairs = this.getActivePairs(strategy);
4197
+ const pair = pick4(activePairs);
4198
+ const price = this.priceState.get(pair) || PAIR_PRICES[pair] || 5e4;
4199
+ const indicators = this.generateIndicators(strategy, price);
4200
+ this.indicatorState.set(strategy.id, indicators);
4201
+ this.botStates.set(strategy.id, {
4202
+ strategyId: strategy.id,
4203
+ strategyName: strategy.name,
4204
+ isRunning: true,
4205
+ currentPair: pair,
4206
+ currentPrice: price,
4207
+ indicators,
4208
+ openPositions: [],
4209
+ totalPnl: rand3(-50, 200),
4210
+ totalTrades: randInt3(5, 25),
4211
+ winRate: rand3(0.48, 0.68),
4212
+ lastSignal: "HOLD",
4213
+ lastSignalConfidence: 0
4214
+ });
4215
+ }
4216
+ scheduleCycle(strategy) {
4217
+ if (!this.running) return;
4218
+ const interval = rand3(strategy.scanIntervalMin, strategy.scanIntervalMax);
4219
+ const timer = setTimeout(() => {
4220
+ if (this.running) {
4221
+ this.runBotCycle(strategy);
4222
+ this.scheduleCycle(strategy);
4223
+ }
4224
+ }, interval);
4225
+ this.botTimers.set(strategy.id, timer);
4226
+ }
4227
+ async runBotCycle(strategy) {
4228
+ const state = this.botStates.get(strategy.id);
4229
+ if (!state) return;
4230
+ const activePairs = this.getActivePairs(strategy);
4231
+ const pair = pick4(activePairs);
4232
+ const price = this.simulatePrice(pair);
4233
+ const indicators = this.generateIndicators(strategy, price);
4234
+ this.indicatorState.set(strategy.id, indicators);
4235
+ state.currentPair = pair;
4236
+ state.currentPrice = price;
4237
+ state.indicators = indicators;
4238
+ const entries = [];
4239
+ let delay = 0;
4240
+ const chain = this.getActiveChain();
4241
+ const chainLabel = this.getChainLabel(chain);
4242
+ entries.push({
4243
+ entry: {
4244
+ strategyId: strategy.id,
4245
+ strategyName: strategy.shortName,
4246
+ type: "SCAN",
4247
+ message: `Scanning ${pair} on ${chainLabel} | Price: $${formatPrice(price)}`,
4248
+ data: { pair, chain, chainLabel },
4249
+ importance: "low"
4250
+ },
4251
+ delay
4252
+ });
4253
+ delay += rand3(800, 1500);
4254
+ const thinkingMessages = this.generateThinkingProcess(strategy, pair, price);
4255
+ for (const thinking of thinkingMessages) {
4256
+ entries.push({
4257
+ entry: {
4258
+ strategyId: strategy.id,
4259
+ strategyName: strategy.shortName,
4260
+ type: "THINKING",
4261
+ message: thinking,
4262
+ importance: "low"
4263
+ },
4264
+ delay
4265
+ });
4266
+ delay += rand3(600, 1200);
4267
+ }
4268
+ const indicatorParts = [];
4269
+ if (strategy.primaryIndicators.includes("RSI") || strategy.primaryIndicators.includes("MACD")) {
4270
+ indicatorParts.push(`RSI: ${indicators.rsi.toFixed(1)}`);
4271
+ }
4272
+ if (strategy.primaryIndicators.includes("MACD") || strategy.primaryIndicators.includes("RSI")) {
4273
+ indicatorParts.push(`MACD: ${indicators.macd.histogram > 0 ? "+" : ""}${indicators.macd.histogram.toFixed(3)}`);
4274
+ }
4275
+ if (strategy.primaryIndicators.includes("EMA")) {
4276
+ indicatorParts.push(`EMA: ${indicators.ema.short.toFixed(1)}/${indicators.ema.long.toFixed(1)}`);
4277
+ if (indicators.ema.crossover !== "none") {
4278
+ indicatorParts.push(`[${indicators.ema.crossover.toUpperCase()} CROSS]`);
4279
+ }
4280
+ }
4281
+ if (strategy.primaryIndicators.includes("Bollinger")) {
4282
+ indicatorParts.push(`BB: ${indicators.bollinger.position.toFixed(1)}% width=${indicators.bollinger.width.toFixed(2)}`);
4283
+ }
4284
+ if (strategy.primaryIndicators.includes("Volume")) {
4285
+ indicatorParts.push(`Vol: ${indicators.volume.ratio.toFixed(2)}x avg`);
4286
+ }
4287
+ entries.push({
4288
+ entry: {
4289
+ strategyId: strategy.id,
4290
+ strategyName: strategy.shortName,
4291
+ type: "INDICATOR",
4292
+ message: indicatorParts.join(" | "),
4293
+ data: { indicators },
4294
+ importance: "low"
4295
+ },
4296
+ delay
4297
+ });
4298
+ delay += rand3(800, 1500);
4299
+ if (Math.random() < 0.12) {
4300
+ const sentiment = Math.random() > 0.4 ? "Bullish" : "Bearish";
4301
+ entries.push({
4302
+ entry: {
4303
+ strategyId: strategy.id,
4304
+ strategyName: strategy.shortName,
4305
+ type: "NEWS",
4306
+ message: `[${sentiment}] ${pick4(NEWS_HEADLINES)}`,
4307
+ importance: "medium"
4308
+ },
4309
+ delay
4310
+ });
4311
+ delay += rand3(1e3, 1800);
4312
+ }
4313
+ if (Math.random() < 0.4) {
4314
+ const analysis = this.generateAnalysis(strategy, indicators, pair);
4315
+ entries.push({
4316
+ entry: {
4317
+ strategyId: strategy.id,
4318
+ strategyName: strategy.shortName,
4319
+ type: "ANALYSIS",
4320
+ message: analysis,
4321
+ importance: "medium"
4322
+ },
4323
+ delay
4324
+ });
4325
+ delay += rand3(1e3, 2e3);
4326
+ }
4327
+ const signal = this.evaluateSignal(strategy, indicators);
4328
+ state.lastSignal = signal.direction;
4329
+ state.lastSignalConfidence = signal.confidence;
4330
+ if (signal.direction !== "HOLD") {
4331
+ const strategyContext = this.generateStrategyContext(strategy, signal, indicators, pair);
4332
+ entries.push({
4333
+ entry: {
4334
+ strategyId: strategy.id,
4335
+ strategyName: strategy.shortName,
4336
+ type: "STRATEGY",
4337
+ message: strategyContext,
4338
+ data: {
4339
+ strategy: strategy.name,
4340
+ riskTolerance: strategy.riskTolerance,
4341
+ primaryIndicators: strategy.primaryIndicators,
4342
+ signal: signal.direction,
4343
+ confidence: signal.confidence
4344
+ },
4345
+ importance: "high"
4346
+ },
4347
+ delay
4348
+ });
4349
+ delay += rand3(1500, 2500);
4350
+ entries.push({
4351
+ entry: {
4352
+ strategyId: strategy.id,
4353
+ strategyName: strategy.shortName,
4354
+ type: "SIGNAL",
4355
+ message: `${signal.direction} signal detected | Confidence: ${(signal.confidence * 100).toFixed(1)}% | ${signal.reason}`,
4356
+ data: { signal },
4357
+ importance: "high"
4358
+ },
4359
+ delay
4360
+ });
4361
+ delay += rand3(1200, 2e3);
4362
+ const decision = this.makeTradeDecision(strategy, signal, state);
4363
+ if (decision.execute) {
4364
+ entries.push({
4365
+ entry: {
4366
+ strategyId: strategy.id,
4367
+ strategyName: strategy.shortName,
4368
+ type: "DECISION",
4369
+ message: `Execute ${signal.direction} | Size: ${decision.positionSize.toFixed(1)}% | Leverage: ${decision.leverage}x | Risk/Reward: 1:${decision.riskReward.toFixed(1)}`,
4370
+ data: {
4371
+ strategyName: strategy.name,
4372
+ strategyId: strategy.id,
4373
+ riskTolerance: strategy.riskTolerance,
4374
+ signalReason: signal.reason,
4375
+ confidence: signal.confidence
4376
+ },
4377
+ importance: "high"
4378
+ },
4379
+ delay
4380
+ });
4381
+ delay += rand3(1e3, 1800);
4382
+ const orderId = `ORD_${Date.now().toString(36).toUpperCase()}`;
4383
+ const orderPrice = signal.direction === "LONG" ? price * (1 - rand3(1e-4, 5e-4)) : price * (1 + rand3(1e-4, 5e-4));
4384
+ entries.push({
4385
+ entry: {
4386
+ strategyId: strategy.id,
4387
+ strategyName: strategy.shortName,
4388
+ type: "ORDER",
4389
+ message: `Submitting ${signal.direction} order | ${pair} @ $${formatPrice(orderPrice)} on ${chainLabel} | ID: ${orderId}`,
4390
+ data: {
4391
+ orderId,
4392
+ pair,
4393
+ side: signal.direction,
4394
+ price: orderPrice,
4395
+ leverage: decision.leverage,
4396
+ chain,
4397
+ chainLabel,
4398
+ strategyName: strategy.name,
4399
+ strategyContext,
4400
+ signalReason: signal.reason
4401
+ },
4402
+ importance: "high"
4403
+ },
4404
+ delay
4405
+ });
4406
+ delay += rand3(2e3, 4e3);
4407
+ const fillPrice = orderPrice * (1 + rand3(-3e-4, 3e-4));
4408
+ const slippage = Math.abs(fillPrice - orderPrice) / orderPrice * 100;
4409
+ entries.push({
4410
+ entry: {
4411
+ strategyId: strategy.id,
4412
+ strategyName: strategy.shortName,
4413
+ type: "FILLED",
4414
+ message: `Order FILLED | ${pair} ${signal.direction} @ $${formatPrice(fillPrice)} on ${chainLabel} | Slippage: ${slippage.toFixed(4)}% | ID: ${orderId}`,
4415
+ data: {
4416
+ orderId,
4417
+ fillPrice,
4418
+ slippage,
4419
+ chain,
4420
+ chainLabel,
4421
+ strategyName: strategy.name,
4422
+ executedBy: strategy.id
4423
+ },
4424
+ importance: "high"
4425
+ },
4426
+ delay
4427
+ });
4428
+ const position = {
4429
+ id: orderId,
4430
+ pair,
4431
+ side: signal.direction,
4432
+ entryPrice: fillPrice,
4433
+ currentPrice: price,
4434
+ size: decision.positionSize,
4435
+ leverage: decision.leverage,
4436
+ pnl: 0,
4437
+ pnlPercent: 0
4438
+ };
4439
+ state.openPositions = [...state.openPositions.slice(-2), position];
4440
+ state.totalTrades++;
4441
+ } else {
4442
+ entries.push({
4443
+ entry: {
4444
+ strategyId: strategy.id,
4445
+ strategyName: strategy.shortName,
4446
+ type: "DECISION",
4447
+ message: `SKIP - ${decision.reason}`,
4448
+ importance: "medium"
4449
+ },
4450
+ delay
4451
+ });
4452
+ }
4453
+ }
4454
+ if (state.openPositions.length > 0 && Math.random() < 0.5) {
4455
+ delay += rand3(1500, 2500);
4456
+ let totalPositionPnl = 0;
4457
+ const pnlParts = [];
4458
+ for (const pos of state.openPositions) {
4459
+ pos.currentPrice = this.simulatePrice(pos.pair);
4460
+ const priceDiff = pos.side === "LONG" ? (pos.currentPrice - pos.entryPrice) / pos.entryPrice : (pos.entryPrice - pos.currentPrice) / pos.entryPrice;
4461
+ pos.pnlPercent = priceDiff * pos.leverage * 100;
4462
+ pos.pnl = priceDiff * pos.leverage * pos.size;
4463
+ totalPositionPnl += pos.pnl;
4464
+ pnlParts.push(`${pos.pair} ${pos.side}: ${pos.pnlPercent >= 0 ? "+" : ""}${pos.pnlPercent.toFixed(2)}%`);
4465
+ }
4466
+ state.totalPnl += totalPositionPnl * rand3(0.01, 0.05);
4467
+ if (state.openPositions.length > 1 && Math.random() < 0.3) {
4468
+ const closed = state.openPositions.shift();
4469
+ const finalPnl = closed.pnlPercent;
4470
+ if (finalPnl > 0) {
4471
+ state.winRate = state.winRate * 0.95 + 0.05;
4472
+ } else {
4473
+ state.winRate = state.winRate * 0.95;
4474
+ }
4475
+ state.winRate = clamp(state.winRate, 0.35, 0.75);
4476
+ pnlParts.push(`CLOSED ${closed.pair}: ${finalPnl >= 0 ? "+" : ""}${finalPnl.toFixed(2)}%`);
4477
+ }
4478
+ entries.push({
4479
+ entry: {
4480
+ strategyId: strategy.id,
4481
+ strategyName: strategy.shortName,
4482
+ type: "PNL",
4483
+ message: pnlParts.join(" | "),
4484
+ data: { totalPnl: state.totalPnl, positions: state.openPositions.length },
4485
+ importance: "medium"
4486
+ },
4487
+ delay
4488
+ });
4489
+ }
4490
+ if (Math.random() < 0.2) {
4491
+ delay += rand3(1e3, 2e3);
4492
+ const exposure = state.openPositions.reduce((sum, p) => sum + p.size * p.leverage, 0);
4493
+ const maxDrawdown = rand3(2, 12);
4494
+ entries.push({
4495
+ entry: {
4496
+ strategyId: strategy.id,
4497
+ strategyName: strategy.shortName,
4498
+ type: "RISK",
4499
+ message: `Portfolio exposure: ${exposure.toFixed(1)}% | Max drawdown: ${maxDrawdown.toFixed(1)}% | Open positions: ${state.openPositions.length} | Win rate: ${(state.winRate * 100).toFixed(1)}%`,
4500
+ importance: exposure > 80 ? "high" : "low"
4501
+ },
4502
+ delay
4503
+ });
4504
+ }
4505
+ for (const { entry, delay: d } of entries) {
4506
+ setTimeout(() => {
4507
+ if (this.running) {
4508
+ this.emit({
4509
+ ...entry,
4510
+ id: genId3(),
4511
+ timestamp: Date.now()
4512
+ });
4513
+ }
4514
+ }, d);
4515
+ }
4516
+ }
4517
+ simulatePrice(pair) {
4518
+ const current = this.priceState.get(pair) || PAIR_PRICES[pair] || 5e4;
4519
+ const volatility = pair.includes("DOGE") ? 5e-3 : pair.includes("BTC") ? 2e-3 : 3e-3;
4520
+ const drift = rand3(-volatility, volatility);
4521
+ const newPrice = current * (1 + drift);
4522
+ this.priceState.set(pair, newPrice);
4523
+ return newPrice;
4524
+ }
4525
+ generateIndicators(strategy, price) {
4526
+ const prev = this.indicatorState.get(strategy.id);
4527
+ const prevRsi = prev?.rsi ?? strategy.rsiBias;
4528
+ const rsiMean = strategy.rsiBias;
4529
+ const rsiDrift = rand3(-8, 8);
4530
+ const rsiReversion = (rsiMean - prevRsi) * 0.15;
4531
+ const rsi = clamp(prevRsi + rsiDrift + rsiReversion, 8, 95);
4532
+ const macdBias = rsi > 65 ? 0.3 : rsi < 35 ? -0.3 : 0;
4533
+ const prevHist = prev?.macd.histogram ?? 0;
4534
+ const histogram = clamp(prevHist * 0.7 + rand3(-0.5, 0.5) + macdBias, -2, 2);
4535
+ const macdValue = histogram * rand3(0.8, 1.5);
4536
+ const macdSignal = macdValue - histogram;
4537
+ const prevShort = prev?.ema.short ?? price;
4538
+ const prevLong = prev?.ema.long ?? price;
4539
+ const emaShort = prevShort * 0.9 + price * 0.1;
4540
+ const emaLong = prevLong * 0.95 + price * 0.05;
4541
+ let crossover = "none";
4542
+ if (prevShort <= prevLong && emaShort > emaLong) crossover = "golden";
4543
+ else if (prevShort >= prevLong && emaShort < emaLong) crossover = "death";
4544
+ const bbMiddle = price;
4545
+ const bbWidth = price * rand3(0.01, 0.04);
4546
+ const bbUpper = bbMiddle + bbWidth;
4547
+ const bbLower = bbMiddle - bbWidth;
4548
+ const bbPosition = (price - bbLower) / (bbUpper - bbLower) * 100;
4549
+ const volRatio = rand3(0.3, 2.5);
4550
+ const volCurrent = rand3(1e5, 5e6);
4551
+ return {
4552
+ rsi,
4553
+ macd: { value: macdValue, signal: macdSignal, histogram },
4554
+ ema: { short: emaShort, long: emaLong, crossover },
4555
+ bollinger: { upper: bbUpper, middle: bbMiddle, lower: bbLower, width: bbWidth / price, position: bbPosition },
4556
+ volume: { current: volCurrent, average: volCurrent / volRatio, ratio: volRatio }
4557
+ };
4558
+ }
4559
+ generateThinkingProcess(strategy, pair, price) {
4560
+ const thoughts = [];
4561
+ const pairBase = pair.split("/")[0];
4562
+ const thinkingTemplates = [
4563
+ `Analyzing ${pairBase} market structure...`,
4564
+ `Checking ${strategy.primaryIndicators.join(", ")} confluence...`,
4565
+ `Evaluating risk parameters for ${strategy.riskTolerance} tolerance...`,
4566
+ `Scanning order book depth at $${formatPrice(price)}...`,
4567
+ `Cross-referencing with historical patterns...`,
4568
+ `Calculating optimal entry zone...`,
4569
+ `Assessing market sentiment indicators...`,
4570
+ `Monitoring whale activity on ${pairBase}...`,
4571
+ `Comparing momentum across timeframes...`,
4572
+ `Validating support/resistance levels...`
4573
+ ];
4574
+ const numThoughts = randInt3(1, 3);
4575
+ const shuffled = [...thinkingTemplates].sort(() => Math.random() - 0.5);
4576
+ for (let i = 0; i < numThoughts; i++) {
4577
+ thoughts.push(shuffled[i]);
4578
+ }
4579
+ return thoughts;
4580
+ }
4581
+ generateStrategyContext(strategy, signal, indicators, pair) {
4582
+ const contexts = [];
4583
+ contexts.push(`[${strategy.name}]`);
4584
+ const riskLevel = strategy.riskTolerance === "high" ? "aggressive" : strategy.riskTolerance === "low" ? "conservative" : "balanced";
4585
+ contexts.push(`Risk: ${riskLevel}`);
4586
+ if (indicators.rsi < 35 || indicators.rsi > 65) {
4587
+ contexts.push(`RSI ${indicators.rsi < 35 ? "oversold" : "overbought"} (${indicators.rsi.toFixed(1)})`);
4588
+ }
4589
+ if (indicators.ema.crossover !== "none") {
4590
+ contexts.push(`EMA ${indicators.ema.crossover} cross`);
4591
+ }
4592
+ if (Math.abs(indicators.macd.histogram) > 0.3) {
4593
+ contexts.push(`MACD ${indicators.macd.histogram > 0 ? "bullish" : "bearish"} momentum`);
4594
+ }
4595
+ const confLevel = signal.confidence > 0.7 ? "HIGH" : signal.confidence > 0.5 ? "MEDIUM" : "LOW";
4596
+ contexts.push(`Confidence: ${confLevel}`);
4597
+ return contexts.join(" | ");
4598
+ }
4599
+ generateAnalysis(strategy, indicators, pair) {
4600
+ const analyses = [];
4601
+ if (indicators.rsi > 70) {
4602
+ analyses.push(`RSI at ${indicators.rsi.toFixed(1)} - overbought territory, watching for reversal`);
4603
+ } else if (indicators.rsi < 30) {
4604
+ analyses.push(`RSI at ${indicators.rsi.toFixed(1)} - oversold, potential bounce setup`);
4605
+ } else if (indicators.rsi > 55) {
4606
+ analyses.push(`RSI trending bullish at ${indicators.rsi.toFixed(1)}`);
4607
+ } else {
4608
+ analyses.push(`RSI neutral at ${indicators.rsi.toFixed(1)}, no clear direction`);
4609
+ }
4610
+ if (indicators.macd.histogram > 0.5) {
4611
+ analyses.push("MACD histogram expanding positive - momentum building");
4612
+ } else if (indicators.macd.histogram < -0.5) {
4613
+ analyses.push("MACD histogram expanding negative - bearish pressure");
4614
+ }
4615
+ if (indicators.ema.crossover === "golden") {
4616
+ analyses.push("EMA golden cross detected - strong bullish signal");
4617
+ } else if (indicators.ema.crossover === "death") {
4618
+ analyses.push("EMA death cross detected - bearish warning");
4619
+ }
4620
+ if (indicators.bollinger.position > 90) {
4621
+ analyses.push(`Price near upper Bollinger band (${indicators.bollinger.position.toFixed(0)}%) - potential resistance`);
4622
+ } else if (indicators.bollinger.position < 10) {
4623
+ analyses.push(`Price near lower Bollinger band (${indicators.bollinger.position.toFixed(0)}%) - potential support`);
4624
+ }
4625
+ if (indicators.volume.ratio > 1.8) {
4626
+ analyses.push(`Volume spike ${indicators.volume.ratio.toFixed(1)}x average - high activity`);
4627
+ }
4628
+ return analyses.length > 0 ? analyses.join(" | ") : `${pair} consolidating - waiting for clearer setup`;
4629
+ }
4630
+ evaluateSignal(strategy, indicators) {
4631
+ let bullScore = 0;
4632
+ let bearScore = 0;
4633
+ const reasons = [];
4634
+ if (indicators.rsi < 30) {
4635
+ bullScore += 2;
4636
+ reasons.push("RSI oversold");
4637
+ } else if (indicators.rsi < 40) {
4638
+ bullScore += 1;
4639
+ reasons.push("RSI low");
4640
+ } else if (indicators.rsi > 70) {
4641
+ bearScore += 2;
4642
+ reasons.push("RSI overbought");
4643
+ } else if (indicators.rsi > 60) {
4644
+ bearScore += 1;
4645
+ reasons.push("RSI high");
4646
+ }
4647
+ if (indicators.macd.histogram > 0.3) {
4648
+ bullScore += 1.5;
4649
+ reasons.push("MACD bullish");
4650
+ } else if (indicators.macd.histogram < -0.3) {
4651
+ bearScore += 1.5;
4652
+ reasons.push("MACD bearish");
4653
+ }
4654
+ if (indicators.ema.crossover === "golden") {
4655
+ bullScore += 2.5;
4656
+ reasons.push("Golden cross");
4657
+ } else if (indicators.ema.crossover === "death") {
4658
+ bearScore += 2.5;
4659
+ reasons.push("Death cross");
4660
+ } else if (indicators.ema.short > indicators.ema.long) {
4661
+ bullScore += 0.5;
4662
+ } else {
4663
+ bearScore += 0.5;
4664
+ }
4665
+ if (indicators.bollinger.position < 15) {
4666
+ bullScore += 1;
4667
+ reasons.push("BB support");
4668
+ } else if (indicators.bollinger.position > 85) {
4669
+ bearScore += 1;
4670
+ reasons.push("BB resistance");
4671
+ }
4672
+ if (indicators.volume.ratio > 1.5) {
4673
+ if (bullScore > bearScore) bullScore += 1;
4674
+ else bearScore += 1;
4675
+ reasons.push("Volume confirms");
4676
+ }
4677
+ const netScore = bullScore - bearScore;
4678
+ const confidence = Math.min(Math.abs(netScore) / 6, 0.95);
4679
+ const threshold = strategy.riskTolerance === "high" ? 1.5 : strategy.riskTolerance === "medium" ? 2 : 2.5;
4680
+ if (Math.random() > strategy.tradeFrequency) {
4681
+ return { direction: "HOLD", confidence: 0, reason: "Cycle skip" };
4682
+ }
4683
+ if (netScore > threshold) {
4684
+ return { direction: "LONG", confidence, reason: reasons.slice(0, 3).join(", ") };
4685
+ } else if (netScore < -threshold) {
4686
+ return { direction: "SHORT", confidence, reason: reasons.slice(0, 3).join(", ") };
4687
+ }
4688
+ return { direction: "HOLD", confidence: 0, reason: "No clear signal" };
4689
+ }
4690
+ makeTradeDecision(strategy, signal, state) {
4691
+ if (state.openPositions.length >= 3) {
4692
+ return { execute: false, positionSize: 0, leverage: 0, riskReward: 0, reason: "Max positions reached (3)" };
4693
+ }
4694
+ const minConfidence = strategy.riskTolerance === "high" ? 0.3 : strategy.riskTolerance === "medium" ? 0.45 : 0.6;
4695
+ if (signal.confidence < minConfidence) {
4696
+ return { execute: false, positionSize: 0, leverage: 0, riskReward: 0, reason: `Confidence too low (${(signal.confidence * 100).toFixed(0)}% < ${(minConfidence * 100).toFixed(0)}%)` };
4697
+ }
4698
+ const positionSize = rand3(strategy.positionSizeMin, strategy.positionSizeMax);
4699
+ const leverage = randInt3(strategy.leverageMin, strategy.leverageMax);
4700
+ const riskReward = rand3(1.2, 3.5);
4701
+ return { execute: true, positionSize, leverage, riskReward, reason: "" };
4702
+ }
4703
+ };
4704
+ var botSimulationEngine = new BotSimulationEngine();
2786
4705
 
2787
4706
  // src/react-native.ts
2788
4707
  function createCachedEngineClient(storage, options) {
@@ -2965,29 +4884,54 @@ function getExplorerUrl(chainId, hash, type = "tx") {
2965
4884
  return `${baseUrl}/${type}/${hash}`;
2966
4885
  }
2967
4886
 
4887
+ exports.AGENT_STATUS_COLORS = AGENT_STATUS_COLORS;
4888
+ exports.AI_LOG_COLORS = AI_LOG_COLORS;
2968
4889
  exports.CHAIN_CONFIG = CHAIN_CONFIG;
2969
4890
  exports.CHAIN_CONFIGS = CHAIN_CONFIGS;
2970
4891
  exports.COINGECKO_IDS = COINGECKO_IDS;
4892
+ exports.DEFAULT_CONSOLE_METRICS = DEFAULT_CONSOLE_METRICS;
4893
+ exports.DEFAULT_CONSOLE_OPTIONS = DEFAULT_CONSOLE_OPTIONS;
4894
+ exports.DEFAULT_RISK_STATUS = DEFAULT_RISK_STATUS;
2971
4895
  exports.DEFAULT_SHARE_RATES = DEFAULT_SHARE_RATES;
4896
+ exports.FOREX_LOG_COLORS = FOREX_LOG_COLORS;
4897
+ exports.ORDER_STATUS_CONFIG = ORDER_STATUS_CONFIG;
2972
4898
  exports.OneChainSelector = OneChainSelector;
2973
4899
  exports.OneCycleSelector = OneCycleSelector;
2974
4900
  exports.OneEngineClient = OneEngineClient;
4901
+ exports.OneForexCapitalSplit = OneForexCapitalSplit;
4902
+ exports.OneForexConsoleView = OneForexConsoleView;
4903
+ exports.OneForexPairSelector = OneForexPairSelector;
4904
+ exports.OneForexPoolCard = OneForexPoolCard;
4905
+ exports.OneForexTradeHistory = OneForexTradeHistory;
2975
4906
  exports.OnePairSelector = OnePairSelector;
2976
4907
  exports.OneSDKError = OneSDKError;
2977
4908
  exports.OneTierSelector = OneTierSelector;
2978
4909
  exports.PAIR_ICONS = PAIR_ICONS;
4910
+ exports.PENALTY_TIERS = PENALTY_TIERS;
2979
4911
  exports.PriceService = PriceService;
4912
+ exports.RISK_LEVELS = RISK_LEVELS;
4913
+ exports.RISK_LEVEL_COLORS = RISK_LEVEL_COLORS;
4914
+ exports.STRATEGY_CATEGORIES = STRATEGY_CATEGORIES;
2980
4915
  exports.TOKEN_NAMES = TOKEN_NAMES;
4916
+ exports.TRADING_STATUS_COLORS = TRADING_STATUS_COLORS;
4917
+ exports.botSimulationEngine = botSimulationEngine;
4918
+ exports.calculateEarlyWithdrawalPenalty = calculateEarlyWithdrawalPenalty;
4919
+ exports.calculateForexNetProfit = calculateForexNetProfit;
4920
+ exports.calculateRiskLevel = calculateRiskLevel;
2981
4921
  exports.capitalize = capitalize;
2982
4922
  exports.checksumAddress = checksumAddress;
4923
+ exports.clearForexAccessToken = clearForexAccessToken;
4924
+ exports.computePoolAllocations = computePoolAllocations;
2983
4925
  exports.createCachedEngineClient = createCachedEngineClient;
2984
4926
  exports.createDeepLinkHandler = createDeepLinkHandler;
2985
4927
  exports.createOneEngineClient = createOneEngineClient;
4928
+ exports.estimateForexProfit = estimateForexProfit;
2986
4929
  exports.formatCryptoAmount = formatCryptoAmount;
2987
4930
  exports.formatDate = formatDate;
2988
4931
  exports.formatDateTime = formatDateTime;
2989
4932
  exports.formatNumber = formatNumber;
2990
4933
  exports.formatPercent = formatPercent;
4934
+ exports.formatPnl = formatPnl;
2991
4935
  exports.formatRelativeTime = formatRelativeTime;
2992
4936
  exports.formatTokenAmount = formatTokenAmount;
2993
4937
  exports.formatUSD = formatUSD;
@@ -3004,9 +4948,16 @@ exports.parseQRCode = parseQRCode;
3004
4948
  exports.pick = pick;
3005
4949
  exports.priceService = priceService;
3006
4950
  exports.retry = retry;
4951
+ exports.setForexAccessToken = setForexAccessToken;
4952
+ exports.setForexEngineUrl = setForexEngineUrl;
3007
4953
  exports.shortenAddress = shortenAddress;
3008
4954
  exports.sleep = sleep;
3009
4955
  exports.slugify = slugify;
3010
4956
  exports.truncate = truncate;
4957
+ exports.useForexInvestments = useForexInvestments;
4958
+ exports.useForexPoolData = useForexPoolData;
4959
+ exports.useForexPools = useForexPools;
4960
+ exports.useForexSimulation = useForexSimulation;
4961
+ exports.useForexTrading = useForexTrading;
3011
4962
  //# sourceMappingURL=react-native.js.map
3012
4963
  //# sourceMappingURL=react-native.js.map