@elizaos/plugin-social-alpha 2.0.3-beta.5 → 2.0.3-beta.7

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 (151) hide show
  1. package/dist/clients.d.ts +354 -0
  2. package/dist/clients.d.ts.map +1 -0
  3. package/dist/clients.js +670 -0
  4. package/dist/clients.js.map +1 -0
  5. package/dist/config.d.ts +144 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +122 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/events.d.ts +5 -0
  10. package/dist/events.d.ts.map +1 -0
  11. package/dist/events.js +426 -0
  12. package/dist/events.js.map +1 -0
  13. package/dist/frontend/LeaderboardView.helpers.d.ts +6 -0
  14. package/dist/frontend/LeaderboardView.helpers.d.ts.map +1 -0
  15. package/dist/frontend/LeaderboardView.helpers.js +59 -0
  16. package/dist/frontend/LeaderboardView.helpers.js.map +1 -0
  17. package/dist/frontend/SocialAlphaSpatialView.d.ts +52 -0
  18. package/dist/frontend/SocialAlphaSpatialView.d.ts.map +1 -0
  19. package/dist/frontend/SocialAlphaSpatialView.js +72 -0
  20. package/dist/frontend/SocialAlphaSpatialView.js.map +1 -0
  21. package/dist/frontend/SocialAlphaView.d.ts +35 -0
  22. package/dist/frontend/SocialAlphaView.d.ts.map +1 -0
  23. package/dist/frontend/SocialAlphaView.js +125 -0
  24. package/dist/frontend/SocialAlphaView.js.map +1 -0
  25. package/dist/index.d.ts +24 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +73 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/mockPriceService.d.ts +22 -0
  30. package/dist/mockPriceService.d.ts.map +1 -0
  31. package/dist/mockPriceService.js +21 -0
  32. package/dist/mockPriceService.js.map +1 -0
  33. package/dist/providers/socialAlphaProvider.d.ts +15 -0
  34. package/dist/providers/socialAlphaProvider.d.ts.map +1 -0
  35. package/dist/providers/socialAlphaProvider.js +261 -0
  36. package/dist/providers/socialAlphaProvider.js.map +1 -0
  37. package/dist/register-terminal-view.d.ts +15 -0
  38. package/dist/register-terminal-view.d.ts.map +1 -0
  39. package/dist/register-terminal-view.js +21 -0
  40. package/dist/register-terminal-view.js.map +1 -0
  41. package/dist/register.d.ts +10 -0
  42. package/dist/register.d.ts.map +1 -0
  43. package/dist/register.js +5 -0
  44. package/dist/register.js.map +1 -0
  45. package/dist/reports.d.ts +57 -0
  46. package/dist/reports.d.ts.map +1 -0
  47. package/dist/reports.js +455 -0
  48. package/dist/reports.js.map +1 -0
  49. package/dist/routes.d.ts +3 -0
  50. package/dist/routes.d.ts.map +1 -0
  51. package/dist/routes.js +59 -0
  52. package/dist/routes.js.map +1 -0
  53. package/dist/schemas.d.ts +151 -0
  54. package/dist/schemas.d.ts.map +1 -0
  55. package/dist/schemas.js +258 -0
  56. package/dist/schemas.js.map +1 -0
  57. package/dist/service.d.ts +306 -0
  58. package/dist/service.d.ts.map +1 -0
  59. package/dist/service.js +3078 -0
  60. package/dist/service.js.map +1 -0
  61. package/dist/services/balancedTrustScoreCalculator.d.ts +61 -0
  62. package/dist/services/balancedTrustScoreCalculator.d.ts.map +1 -0
  63. package/dist/services/balancedTrustScoreCalculator.js +207 -0
  64. package/dist/services/balancedTrustScoreCalculator.js.map +1 -0
  65. package/dist/services/historicalPriceService.d.ts +59 -0
  66. package/dist/services/historicalPriceService.d.ts.map +1 -0
  67. package/dist/services/historicalPriceService.js +291 -0
  68. package/dist/services/historicalPriceService.js.map +1 -0
  69. package/dist/services/index.d.ts +12 -0
  70. package/dist/services/index.d.ts.map +1 -0
  71. package/dist/services/index.js +17 -0
  72. package/dist/services/index.js.map +1 -0
  73. package/dist/services/priceEnrichmentService.d.ts +109 -0
  74. package/dist/services/priceEnrichmentService.d.ts.map +1 -0
  75. package/dist/services/priceEnrichmentService.js +780 -0
  76. package/dist/services/priceEnrichmentService.js.map +1 -0
  77. package/dist/services/simulationActorsV2.d.ts +54 -0
  78. package/dist/services/simulationActorsV2.d.ts.map +1 -0
  79. package/dist/services/simulationActorsV2.js +362 -0
  80. package/dist/services/simulationActorsV2.js.map +1 -0
  81. package/dist/services/simulationRunner.d.ts +113 -0
  82. package/dist/services/simulationRunner.d.ts.map +1 -0
  83. package/dist/services/simulationRunner.js +771 -0
  84. package/dist/services/simulationRunner.js.map +1 -0
  85. package/dist/services/tokenSimulationService.d.ts +34 -0
  86. package/dist/services/tokenSimulationService.d.ts.map +1 -0
  87. package/dist/services/tokenSimulationService.js +297 -0
  88. package/dist/services/tokenSimulationService.js.map +1 -0
  89. package/dist/services/trustScoreOptimizer.d.ts +110 -0
  90. package/dist/services/trustScoreOptimizer.d.ts.map +1 -0
  91. package/dist/services/trustScoreOptimizer.js +635 -0
  92. package/dist/services/trustScoreOptimizer.js.map +1 -0
  93. package/dist/simulationActors.d.ts +35 -0
  94. package/dist/simulationActors.d.ts.map +1 -0
  95. package/dist/simulationActors.js +160 -0
  96. package/dist/simulationActors.js.map +1 -0
  97. package/dist/social-alpha-view-bundle.d.ts +2 -0
  98. package/dist/social-alpha-view-bundle.d.ts.map +1 -0
  99. package/dist/social-alpha-view-bundle.js +5 -0
  100. package/dist/social-alpha-view-bundle.js.map +1 -0
  101. package/dist/types.d.ts +937 -0
  102. package/dist/types.d.ts.map +1 -0
  103. package/dist/types.js +46 -0
  104. package/dist/types.js.map +1 -0
  105. package/dist/views/brand/background/clouds_background.jpg +0 -0
  106. package/dist/views/brand/banners/eliza_banner.svg +20 -0
  107. package/dist/views/brand/banners/elizacloud_banner.svg +20 -0
  108. package/dist/views/brand/banners/elizaos_banner.svg +20 -0
  109. package/dist/views/brand/concepts/billboard_concept_1200.jpg +0 -0
  110. package/dist/views/brand/concepts/chibi_usb_concept_900.jpg +0 -0
  111. package/dist/views/brand/concepts/concept_minipc_900.jpg +0 -0
  112. package/dist/views/brand/concepts/concept_phone_800.jpg +0 -0
  113. package/dist/views/brand/concepts/concept_usbdrive_900.jpg +0 -0
  114. package/dist/views/brand/favicons/android-chrome-192x192.png +0 -0
  115. package/dist/views/brand/favicons/android-chrome-512x512.png +0 -0
  116. package/dist/views/brand/favicons/apple-touch-icon.png +0 -0
  117. package/dist/views/brand/favicons/favicon-16x16.png +0 -0
  118. package/dist/views/brand/favicons/favicon-32x32.png +0 -0
  119. package/dist/views/brand/favicons/favicon.ico +0 -0
  120. package/dist/views/brand/favicons/favicon.svg +17 -0
  121. package/dist/views/brand/logos/elizaOS_text_black.svg +3 -0
  122. package/dist/views/brand/logos/elizaOS_text_white.svg +3 -0
  123. package/dist/views/brand/logos/eliza_logotext.svg +26 -0
  124. package/dist/views/brand/logos/eliza_logotext_black.svg +26 -0
  125. package/dist/views/brand/logos/eliza_text_black.svg +3 -0
  126. package/dist/views/brand/logos/eliza_text_white.svg +3 -0
  127. package/dist/views/brand/logos/elizacloud_logotext.svg +26 -0
  128. package/dist/views/brand/logos/elizacloud_logotext_black.svg +26 -0
  129. package/dist/views/brand/logos/elizacloud_text_black.svg +3 -0
  130. package/dist/views/brand/logos/elizacloud_text_white.svg +3 -0
  131. package/dist/views/brand/logos/elizaos_logotext.svg +26 -0
  132. package/dist/views/brand/logos/elizaos_logotext_black.svg +26 -0
  133. package/dist/views/brand/logos/logo_blue_blackbg.svg +18 -0
  134. package/dist/views/brand/logos/logo_blue_nobg.svg +17 -0
  135. package/dist/views/brand/logos/logo_orange_blackbg.svg +18 -0
  136. package/dist/views/brand/logos/logo_orange_nobg.svg +17 -0
  137. package/dist/views/brand/logos/logo_white_blackbg.svg +25 -0
  138. package/dist/views/brand/logos/logo_white_bluebg.svg +25 -0
  139. package/dist/views/brand/logos/logo_white_graybg.svg +18 -0
  140. package/dist/views/brand/logos/logo_white_nobg.svg +24 -0
  141. package/dist/views/brand/logos/logo_white_orangebg.svg +25 -0
  142. package/dist/views/brand/ogembeds/eliza_ogembed.png +0 -0
  143. package/dist/views/brand/ogembeds/eliza_ogembed.svg +20 -0
  144. package/dist/views/brand/ogembeds/elizacloud_ogembed.png +0 -0
  145. package/dist/views/brand/ogembeds/elizacloud_ogembed.svg +20 -0
  146. package/dist/views/brand/ogembeds/elizaos_ogembed.png +0 -0
  147. package/dist/views/brand/ogembeds/elizaos_ogembed.svg +20 -0
  148. package/dist/views/bundle.js +268 -0
  149. package/dist/views/bundle.js.map +1 -0
  150. package/dist/views/site.webmanifest +19 -0
  151. package/package.json +5 -5
@@ -0,0 +1,771 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as path from "node:path";
3
+ import { v4 as uuidv4 } from "uuid";
4
+ import { Conviction, SupportedChain } from "../types.js";
5
+ import {
6
+ TokenSimulationService
7
+ } from "./tokenSimulationService.js";
8
+ var TokenScenario = /* @__PURE__ */ ((TokenScenario2) => {
9
+ TokenScenario2["RUG_PULL_FAST"] = "rug_fast";
10
+ TokenScenario2["RUG_PULL_SLOW"] = "rug_slow";
11
+ TokenScenario2["SCAM_TOKEN"] = "scam";
12
+ TokenScenario2["RUNNER_MOON"] = "runner_moon";
13
+ TokenScenario2["RUNNER_STEADY"] = "runner_steady";
14
+ TokenScenario2["SUCCESSFUL"] = "successful";
15
+ TokenScenario2["MEDIOCRE"] = "mediocre";
16
+ TokenScenario2["STAGNANT"] = "stagnant";
17
+ TokenScenario2["BLUE_CHIP"] = "bluechip";
18
+ TokenScenario2["PUMP_AND_DUMP"] = "pump_dump";
19
+ TokenScenario2["SLOW_BLEED"] = "slow_bleed";
20
+ return TokenScenario2;
21
+ })(TokenScenario || {});
22
+ class SimulationRunner {
23
+ tokenService;
24
+ constructor() {
25
+ this.tokenService = new TokenSimulationService();
26
+ }
27
+ async runSimulation(config) {
28
+ console.log("\u{1F680} Starting comprehensive market simulation...");
29
+ const calls = [];
30
+ const tokens = /* @__PURE__ */ new Map();
31
+ const priceHistory = /* @__PURE__ */ new Map();
32
+ const actorPerformance = /* @__PURE__ */ new Map();
33
+ for (const actor of config.actors) {
34
+ const _simulatedActor = {
35
+ id: actor.id,
36
+ username: actor.username,
37
+ archetype: actor.archetype,
38
+ trustScore: actor.expectedTrustScore,
39
+ callHistory: [],
40
+ preferences: {
41
+ favoriteTokenTypes: this.mapScenarioToTypes(actor.tokenPreferences),
42
+ callFrequency: actor.callFrequency,
43
+ timingBias: actor.timingBias
44
+ }
45
+ };
46
+ actorPerformance.set(actor.id, {
47
+ totalCalls: 0,
48
+ profitableCalls: 0,
49
+ totalProfit: 0,
50
+ averageProfit: 0
51
+ });
52
+ }
53
+ const generatedTokens = this.generateTokens(config);
54
+ for (const token of generatedTokens) {
55
+ tokens.set(token.address, token);
56
+ priceHistory.set(token.address, []);
57
+ }
58
+ let currentTime = new Date(config.startTime);
59
+ const endTime = new Date(config.endTime);
60
+ let stepCount = 0;
61
+ while (currentTime <= endTime) {
62
+ stepCount++;
63
+ for (const [address, token] of tokens) {
64
+ const timeSinceLaunch = (currentTime.getTime() - token.launchTime.getTime()) / (1e3 * 60 * 60);
65
+ if (timeSinceLaunch >= 0) {
66
+ const price = this.calculateTokenPrice(token, timeSinceLaunch);
67
+ priceHistory.get(address)?.push({
68
+ timestamp: currentTime,
69
+ price: price.price,
70
+ volume: price.volume,
71
+ liquidity: price.liquidity,
72
+ marketCap: price.marketCap
73
+ });
74
+ }
75
+ }
76
+ const stepCalls = this.generateCallsForTimeStep(
77
+ currentTime,
78
+ tokens,
79
+ priceHistory,
80
+ config
81
+ );
82
+ calls.push(...stepCalls);
83
+ currentTime = new Date(
84
+ currentTime.getTime() + config.timeStepMinutes * 60 * 1e3
85
+ );
86
+ }
87
+ console.log(
88
+ `\u2705 Simulation complete: ${stepCount} time steps, ${calls.length} calls generated`
89
+ );
90
+ await this.calculateActualProfits(calls, tokens, priceHistory);
91
+ for (const call of calls) {
92
+ const perf = actorPerformance.get(call.userId);
93
+ if (!perf) continue;
94
+ perf.totalCalls++;
95
+ if (call.simulationMetadata.actualProfit && call.simulationMetadata.actualProfit > 0) {
96
+ perf.profitableCalls++;
97
+ }
98
+ perf.totalProfit += call.simulationMetadata.actualProfit || 0;
99
+ }
100
+ for (const [_actorId, perf] of actorPerformance) {
101
+ perf.averageProfit = perf.totalCalls > 0 ? perf.totalProfit / perf.totalCalls : 0;
102
+ }
103
+ const result = {
104
+ calls,
105
+ tokens,
106
+ priceHistory,
107
+ actorPerformance
108
+ };
109
+ if (config.cacheResults) {
110
+ await this.cacheResults(result, config);
111
+ }
112
+ return result;
113
+ }
114
+ calculateTokenPrice(token, hoursSinceLaunch) {
115
+ let price = token.initialPrice;
116
+ if (token.priceTrajectory) {
117
+ const step = Math.floor(hoursSinceLaunch / 24);
118
+ price = token.priceTrajectory(step);
119
+ }
120
+ const priceRatio = price / token.initialPrice;
121
+ const marketCap = token.initialMarketCap * priceRatio;
122
+ const liquidity = token.initialLiquidity * Math.sqrt(priceRatio);
123
+ const volume = marketCap * 0.1 * (1 + Math.random() * 0.5);
124
+ return {
125
+ timestamp: /* @__PURE__ */ new Date(),
126
+ price,
127
+ volume,
128
+ liquidity,
129
+ marketCap
130
+ };
131
+ }
132
+ mapScenarioToTypes(scenarios) {
133
+ const mapping = {
134
+ ["rug_fast" /* RUG_PULL_FAST */]: "rug",
135
+ ["rug_slow" /* RUG_PULL_SLOW */]: "rug",
136
+ ["scam" /* SCAM_TOKEN */]: "scam",
137
+ ["runner_moon" /* RUNNER_MOON */]: "runner",
138
+ ["runner_steady" /* RUNNER_STEADY */]: "runner",
139
+ ["successful" /* SUCCESSFUL */]: "successful",
140
+ ["mediocre" /* MEDIOCRE */]: "mediocre",
141
+ ["stagnant" /* STAGNANT */]: "stagnant",
142
+ ["bluechip" /* BLUE_CHIP */]: "bluechip",
143
+ ["pump_dump" /* PUMP_AND_DUMP */]: "pump_dump",
144
+ ["slow_bleed" /* SLOW_BLEED */]: "slow_bleed"
145
+ };
146
+ return scenarios.map((s) => mapping[s]);
147
+ }
148
+ generateTokens(config) {
149
+ const tokens = [];
150
+ const distribution = config.tokenScenarioDistribution || {
151
+ ["rug_fast" /* RUG_PULL_FAST */]: 0.15,
152
+ ["rug_slow" /* RUG_PULL_SLOW */]: 0.1,
153
+ ["scam" /* SCAM_TOKEN */]: 0.1,
154
+ ["pump_dump" /* PUMP_AND_DUMP */]: 0.15,
155
+ ["mediocre" /* MEDIOCRE */]: 0.2,
156
+ ["successful" /* SUCCESSFUL */]: 0.15,
157
+ ["runner_moon" /* RUNNER_MOON */]: 0.05,
158
+ ["bluechip" /* BLUE_CHIP */]: 0.05,
159
+ ["slow_bleed" /* SLOW_BLEED */]: 0.05
160
+ };
161
+ for (let i = 0; i < config.tokenCount; i++) {
162
+ const scenario = this.selectScenarioByWeight(distribution);
163
+ const token = this.createToken(scenario, i, config);
164
+ tokens.push(token);
165
+ }
166
+ console.log(
167
+ `\u{1F4CA} Generated ${tokens.length} tokens with scenarios:`,
168
+ tokens.reduce(
169
+ (acc, t) => {
170
+ acc[t.scenario] = (acc[t.scenario] || 0) + 1;
171
+ return acc;
172
+ },
173
+ {}
174
+ )
175
+ );
176
+ return tokens;
177
+ }
178
+ selectScenarioByWeight(distribution) {
179
+ const entries = Object.entries(distribution);
180
+ const totalWeight = entries.reduce((sum, [_, weight]) => sum + weight, 0);
181
+ let random = Math.random() * totalWeight;
182
+ for (const [scenario, weight] of entries) {
183
+ random -= weight;
184
+ if (random <= 0) {
185
+ return scenario;
186
+ }
187
+ }
188
+ return "mediocre" /* MEDIOCRE */;
189
+ }
190
+ createToken(scenario, index, config) {
191
+ const launchSpread = config.endTime.getTime() - config.startTime.getTime();
192
+ const launchOffset = Math.random() * launchSpread * 0.8;
193
+ const scenarioConfig = this.getScenarioConfig(scenario);
194
+ const tokenFromService = this.tokenService.createTokenFromScenario(scenarioConfig);
195
+ return {
196
+ address: `0x${uuidv4().replace(/-/g, "")}${index.toString().padStart(8, "0")}`,
197
+ symbol: `SIM${scenario.substring(0, 3).toUpperCase()}${index}`,
198
+ name: `Simulated ${scenario.replace(/_/g, " ")} Token ${index}`,
199
+ scenario,
200
+ launchTime: new Date(config.startTime.getTime() + launchOffset),
201
+ initialPrice: 1e-5 + Math.random() * 1e-4,
202
+ // $0.00001 - $0.0001
203
+ initialMarketCap: 1e4 + Math.random() * 9e4,
204
+ // $10k - $100k
205
+ initialLiquidity: 5e3 + Math.random() * 45e3,
206
+ // $5k - $50k
207
+ priceTrajectory: tokenFromService.priceTrajectory
208
+ };
209
+ }
210
+ getScenarioConfig(scenario) {
211
+ const configs = {
212
+ ["rug_fast" /* RUG_PULL_FAST */]: {
213
+ type: "rug",
214
+ name: "FastRug Token",
215
+ symbol: "FRUG",
216
+ description: "Rugs within 2 days",
217
+ initialPrice: 1e-5,
218
+ initialLiquidity: 5e3,
219
+ initialMarketCap: 1e4,
220
+ rugTiming: 2
221
+ },
222
+ ["rug_slow" /* RUG_PULL_SLOW */]: {
223
+ type: "rug",
224
+ name: "SlowRug Token",
225
+ symbol: "SRUG",
226
+ description: "Builds trust then rugs",
227
+ initialPrice: 5e-5,
228
+ initialLiquidity: 2e4,
229
+ initialMarketCap: 5e4,
230
+ rugTiming: 10
231
+ },
232
+ ["scam" /* SCAM_TOKEN */]: {
233
+ type: "scam",
234
+ name: "Scam Token",
235
+ symbol: "SCAM",
236
+ description: "Low liquidity scam",
237
+ initialPrice: 1e-3,
238
+ initialLiquidity: 500,
239
+ initialMarketCap: 5e3
240
+ },
241
+ ["runner_moon" /* RUNNER_MOON */]: {
242
+ type: "runner",
243
+ name: "MoonShot Token",
244
+ symbol: "MOON",
245
+ description: "50x growth potential",
246
+ initialPrice: 1e-5,
247
+ initialLiquidity: 5e4,
248
+ initialMarketCap: 1e5
249
+ },
250
+ ["runner_steady" /* RUNNER_STEADY */]: {
251
+ type: "runner",
252
+ name: "SteadyGains Token",
253
+ symbol: "GAIN",
254
+ description: "10x steady growth",
255
+ initialPrice: 1e-4,
256
+ initialLiquidity: 3e4,
257
+ initialMarketCap: 2e5
258
+ },
259
+ ["successful" /* SUCCESSFUL */]: {
260
+ type: "successful",
261
+ name: "Solid Project",
262
+ symbol: "SOLID",
263
+ description: "3x growth",
264
+ initialPrice: 1e-3,
265
+ initialLiquidity: 1e5,
266
+ initialMarketCap: 5e5
267
+ },
268
+ ["mediocre" /* MEDIOCRE */]: {
269
+ type: "mediocre",
270
+ name: "Crabwalk Token",
271
+ symbol: "CRAB",
272
+ description: "Sideways movement",
273
+ initialPrice: 0.01,
274
+ initialLiquidity: 5e4,
275
+ initialMarketCap: 3e5
276
+ },
277
+ ["stagnant" /* STAGNANT */]: {
278
+ type: "stagnant",
279
+ name: "Dead Project",
280
+ symbol: "DEAD",
281
+ description: "No volume",
282
+ initialPrice: 5e-3,
283
+ initialLiquidity: 1e4,
284
+ initialMarketCap: 5e4
285
+ },
286
+ ["bluechip" /* BLUE_CHIP */]: {
287
+ type: "bluechip",
288
+ name: "Established Token",
289
+ symbol: "BLUE",
290
+ description: "Stable growth",
291
+ initialPrice: 10,
292
+ initialLiquidity: 5e6,
293
+ initialMarketCap: 1e8
294
+ },
295
+ ["pump_dump" /* PUMP_AND_DUMP */]: {
296
+ type: "pump_dump",
297
+ name: "PumpDump Token",
298
+ symbol: "PUMP",
299
+ description: "20x then dump",
300
+ initialPrice: 1e-5,
301
+ initialLiquidity: 15e3,
302
+ initialMarketCap: 2e4,
303
+ pumpTiming: 3,
304
+ dumpTiming: 5
305
+ },
306
+ ["slow_bleed" /* SLOW_BLEED */]: {
307
+ type: "slow_bleed",
308
+ name: "BleedOut Token",
309
+ symbol: "BLEED",
310
+ description: "Slow decline",
311
+ initialPrice: 0.01,
312
+ initialLiquidity: 4e4,
313
+ initialMarketCap: 2e5
314
+ }
315
+ };
316
+ return configs[scenario];
317
+ }
318
+ generateCallsForTimeStep(currentTime, tokens, priceHistory, config) {
319
+ const calls = [];
320
+ const activeTokens = Array.from(tokens.values()).filter((token) => {
321
+ const isLaunched = token.launchTime <= currentTime;
322
+ const history = priceHistory.get(token.address) || [];
323
+ const latestPrice = history[history.length - 1];
324
+ const isDead = latestPrice && latestPrice.price < token.initialPrice * 0.01;
325
+ return isLaunched && !isDead;
326
+ });
327
+ if (activeTokens.length === 0) return calls;
328
+ for (const actor of config.actors) {
329
+ const shouldCall = this.shouldActorCall(actor, currentTime);
330
+ if (!shouldCall) continue;
331
+ const targetTokens = this.selectTokensForActor(
332
+ actor,
333
+ activeTokens,
334
+ priceHistory,
335
+ currentTime
336
+ );
337
+ for (const token of targetTokens) {
338
+ const tokenPriceHistory = priceHistory.get(token.address);
339
+ if (!tokenPriceHistory) continue;
340
+ const call = this.generateActorCall(
341
+ actor,
342
+ token,
343
+ tokenPriceHistory,
344
+ currentTime
345
+ );
346
+ if (call) {
347
+ calls.push(call);
348
+ }
349
+ }
350
+ }
351
+ return calls;
352
+ }
353
+ shouldActorCall(actor, _currentTime) {
354
+ const frequencyMultiplier = {
355
+ high: 0.7,
356
+ // Increased from 0.3
357
+ medium: 0.4,
358
+ // Increased from 0.1
359
+ low: 0.15
360
+ // Increased from 0.03
361
+ }[actor.callFrequency];
362
+ return Math.random() < frequencyMultiplier;
363
+ }
364
+ selectTokensForActor(actor, activeTokens, priceHistory, currentTime) {
365
+ let candidateTokens = activeTokens;
366
+ if (["elite_analyst", "skilled_trader"].includes(actor.archetype)) {
367
+ candidateTokens = activeTokens.filter((token) => {
368
+ const _history = priceHistory.get(token.address) || [];
369
+ const timeSinceLaunch = (currentTime.getTime() - token.launchTime.getTime()) / (1e3 * 60 * 60);
370
+ if (actor.archetype === "elite_analyst") {
371
+ if ([
372
+ "rug_fast" /* RUG_PULL_FAST */,
373
+ "rug_slow" /* RUG_PULL_SLOW */,
374
+ "scam" /* SCAM_TOKEN */
375
+ ].includes(token.scenario)) {
376
+ return false;
377
+ }
378
+ return timeSinceLaunch < 48 && // Within 2 days of launch
379
+ [
380
+ "successful" /* SUCCESSFUL */,
381
+ "runner_moon" /* RUNNER_MOON */,
382
+ "runner_steady" /* RUNNER_STEADY */,
383
+ "bluechip" /* BLUE_CHIP */
384
+ ].includes(token.scenario);
385
+ } else {
386
+ return timeSinceLaunch < 72 && // Within 3 days
387
+ !["scam" /* SCAM_TOKEN */].includes(token.scenario);
388
+ }
389
+ });
390
+ } else if (actor.archetype === "fomo_trader") {
391
+ candidateTokens = activeTokens.filter((token) => {
392
+ const history = priceHistory.get(token.address) || [];
393
+ if (history.length < 10) return false;
394
+ const recentGain = history[history.length - 1].price / history[history.length - 10].price - 1;
395
+ return recentGain > 0.5;
396
+ });
397
+ } else if (actor.archetype === "pump_chaser") {
398
+ candidateTokens = activeTokens.filter((token) => {
399
+ const history = priceHistory.get(token.address) || [];
400
+ if (history.length < 5) return false;
401
+ const recentGain = history[history.length - 1].price / history[history.length - 5].price - 1;
402
+ return recentGain > 0.3;
403
+ });
404
+ } else if (actor.archetype === "rug_promoter") {
405
+ candidateTokens = activeTokens.filter(
406
+ (token) => actor.tokenPreferences.includes(token.scenario) && token.scenario !== "bluechip" /* BLUE_CHIP */
407
+ // Even rug promoters avoid obvious blue chips
408
+ );
409
+ }
410
+ if (candidateTokens.length === 0) {
411
+ candidateTokens = activeTokens.filter(
412
+ (token) => actor.tokenPreferences.includes(token.scenario)
413
+ );
414
+ }
415
+ if (candidateTokens.length === 0) return [];
416
+ const timedTokens = candidateTokens.filter((token) => {
417
+ const _history = priceHistory.get(token.address) || [];
418
+ const timeSinceLaunch = (currentTime.getTime() - token.launchTime.getTime()) / (1e3 * 60 * 60);
419
+ switch (actor.timingBias) {
420
+ case "early":
421
+ return timeSinceLaunch < 24;
422
+ // First day only
423
+ case "middle":
424
+ return timeSinceLaunch >= 24 && timeSinceLaunch < 120;
425
+ // Day 1-5
426
+ case "late":
427
+ return timeSinceLaunch >= 72;
428
+ // After 3 days
429
+ default:
430
+ return true;
431
+ }
432
+ });
433
+ const finalTokens = timedTokens.length > 0 ? timedTokens : candidateTokens;
434
+ const maxTokens = actor.archetype === "elite_analyst" ? 1 : 2;
435
+ const numTokens = Math.min(
436
+ finalTokens.length,
437
+ Math.floor(Math.random() * maxTokens) + 1
438
+ );
439
+ return finalTokens.sort(() => Math.random() - 0.5).slice(0, numTokens);
440
+ }
441
+ generateActorCall(actor, token, priceHistory, currentTime) {
442
+ const latestPrice = priceHistory[priceHistory.length - 1];
443
+ if (!latestPrice) return null;
444
+ const message = this.generateMessage(
445
+ actor,
446
+ token.symbol,
447
+ token.scenario,
448
+ "positive"
449
+ // Will be overridden based on actor logic
450
+ );
451
+ if (!message) return null;
452
+ const sentiment = this.determineActorSentiment(actor, token, priceHistory);
453
+ const conviction = this.determineActorConviction(
454
+ actor,
455
+ token,
456
+ priceHistory
457
+ );
458
+ return {
459
+ callId: uuidv4(),
460
+ originalMessageId: `sim_msg_${uuidv4()}`,
461
+ userId: actor.id,
462
+ username: actor.username,
463
+ timestamp: currentTime.getTime(),
464
+ content: message,
465
+ tokenMentioned: token.symbol,
466
+ nameMentioned: token.name,
467
+ caMentioned: token.address,
468
+ chain: SupportedChain.SOLANA,
469
+ sentiment,
470
+ conviction,
471
+ llmReasoning: `${actor.username} (${actor.archetype}) analyzing ${token.symbol}`,
472
+ certainty: "high",
473
+ fileSource: "simulation",
474
+ simulationMetadata: {
475
+ tokenScenario: token.scenario,
476
+ actorArchetype: actor.archetype,
477
+ priceAtCall: latestPrice.price,
478
+ marketCapAtCall: latestPrice.marketCap,
479
+ liquidityAtCall: latestPrice.liquidity,
480
+ expectedOutcome: this.predictOutcome(actor, token)
481
+ }
482
+ };
483
+ }
484
+ generateMessage(actor, tokenSymbol, _scenario, _sentiment) {
485
+ const templates = {
486
+ elite_analyst: [
487
+ `$${tokenSymbol} showing strong fundamentals. This is a long-term hold.`,
488
+ `Been researching $${tokenSymbol} - solid team and execution plan. Accumulating here.`
489
+ ],
490
+ skilled_trader: [
491
+ `$${tokenSymbol} looking strong here. Adding to position.`,
492
+ `Good entry point for $${tokenSymbol}. Risk/reward favorable.`
493
+ ],
494
+ pump_chaser: [
495
+ `$${tokenSymbol} is pumping hard! Just aped in!`,
496
+ `Holy shit $${tokenSymbol} is flying! This is going to $1!`
497
+ ],
498
+ rug_promoter: [
499
+ `\u{1F680}\u{1F680} $${tokenSymbol} TO THE MOON! 1000X GEM! GET IN NOW! \u{1F680}\u{1F680}`,
500
+ `$${tokenSymbol} NEXT 100X!!! DEV DOXXED! LIQUIDITY LOCKED! SAFU! \u{1F48E}\u{1F48E}`
501
+ ],
502
+ fomo_trader: [
503
+ `Everyone buying $${tokenSymbol}! I'm in!`,
504
+ `$${tokenSymbol} trending everywhere! Don't want to miss this!`
505
+ ],
506
+ contrarian: [
507
+ `$${tokenSymbol} overhyped. Taking opposite position.`,
508
+ `While everyone's bullish on $${tokenSymbol}, I see weakness.`
509
+ ],
510
+ technical_analyst: [
511
+ `$${tokenSymbol} breaking key resistance. Chart looks bullish.`,
512
+ `RSI oversold on $${tokenSymbol}. Bounce incoming.`
513
+ ],
514
+ newbie: [
515
+ `Is $${tokenSymbol} a good buy? Thinking about getting some.`,
516
+ `Just bought my first $${tokenSymbol}! Hope it goes up!`
517
+ ],
518
+ bot_spammer: [
519
+ `\u{1F48E} $${tokenSymbol} \u{1F48E} BUY NOW \u{1F48E}`,
520
+ `$${tokenSymbol} $${tokenSymbol} $${tokenSymbol} \u{1F680}\u{1F680}\u{1F680}`
521
+ ]
522
+ };
523
+ const archetypeTemplates = templates[actor.archetype];
524
+ return archetypeTemplates[Math.floor(Math.random() * archetypeTemplates.length)];
525
+ }
526
+ determineActorSentiment(actor, token, priceHistory) {
527
+ if (actor.archetype === "elite_analyst") {
528
+ if ([
529
+ "successful" /* SUCCESSFUL */,
530
+ "runner_moon" /* RUNNER_MOON */,
531
+ "runner_steady" /* RUNNER_STEADY */,
532
+ "bluechip" /* BLUE_CHIP */
533
+ ].includes(token.scenario)) {
534
+ return "positive";
535
+ }
536
+ if ([
537
+ "rug_fast" /* RUG_PULL_FAST */,
538
+ "rug_slow" /* RUG_PULL_SLOW */,
539
+ "scam" /* SCAM_TOKEN */
540
+ ].includes(token.scenario)) {
541
+ return "negative";
542
+ }
543
+ return "neutral";
544
+ }
545
+ if (actor.archetype === "skilled_trader") {
546
+ if ([
547
+ "successful" /* SUCCESSFUL */,
548
+ "runner_moon" /* RUNNER_MOON */,
549
+ "runner_steady" /* RUNNER_STEADY */
550
+ ].includes(token.scenario)) {
551
+ return "positive";
552
+ }
553
+ if (["rug_fast" /* RUG_PULL_FAST */, "scam" /* SCAM_TOKEN */].includes(
554
+ token.scenario
555
+ )) {
556
+ return Math.random() < 0.7 ? "negative" : "positive";
557
+ }
558
+ if (token.scenario === "pump_dump" /* PUMP_AND_DUMP */) {
559
+ const timeSinceLaunch = priceHistory.length;
560
+ return timeSinceLaunch < 5 ? "positive" : "negative";
561
+ }
562
+ return "neutral";
563
+ }
564
+ if (actor.archetype === "rug_promoter") {
565
+ if ([
566
+ "rug_fast" /* RUG_PULL_FAST */,
567
+ "rug_slow" /* RUG_PULL_SLOW */,
568
+ "scam" /* SCAM_TOKEN */
569
+ ].includes(token.scenario)) {
570
+ return "positive";
571
+ }
572
+ return "neutral";
573
+ }
574
+ if (actor.archetype === "fomo_trader") {
575
+ return "positive";
576
+ }
577
+ if (actor.archetype === "pump_chaser") {
578
+ const priceChange = priceHistory.length > 5 ? priceHistory[priceHistory.length - 1].price / priceHistory[priceHistory.length - 5].price - 1 : 0;
579
+ return priceChange > 0.1 ? "positive" : "neutral";
580
+ }
581
+ if (actor.archetype === "contrarian") {
582
+ const priceChange = priceHistory.length > 10 ? priceHistory[priceHistory.length - 1].price / priceHistory[priceHistory.length - 10].price - 1 : 0;
583
+ return priceChange > 0.2 ? "negative" : "positive";
584
+ }
585
+ return actor.tokenPreferences.includes(token.scenario) ? "positive" : "neutral";
586
+ }
587
+ determineActorConviction(actor, _token, priceHistory) {
588
+ const baseConviction = {
589
+ elite_analyst: Conviction.HIGH,
590
+ skilled_trader: Conviction.MEDIUM,
591
+ pump_chaser: Conviction.HIGH,
592
+ rug_promoter: Conviction.VERY_HIGH,
593
+ fomo_trader: Conviction.MEDIUM,
594
+ contrarian: Conviction.MEDIUM,
595
+ technical_analyst: Conviction.MEDIUM,
596
+ newbie: Conviction.LOW,
597
+ bot_spammer: Conviction.LOW
598
+ }[actor.archetype] || Conviction.MEDIUM;
599
+ if (["pump_chaser", "fomo_trader"].includes(actor.archetype)) {
600
+ const recentGain = priceHistory.length > 5 ? priceHistory[priceHistory.length - 1].price / priceHistory[priceHistory.length - 5].price - 1 : 0;
601
+ if (recentGain > 0.5) {
602
+ return Conviction.VERY_HIGH;
603
+ }
604
+ }
605
+ return baseConviction;
606
+ }
607
+ predictOutcome(actor, token) {
608
+ const successfulScenarios = [
609
+ "successful" /* SUCCESSFUL */,
610
+ "runner_moon" /* RUNNER_MOON */,
611
+ "bluechip" /* BLUE_CHIP */
612
+ ];
613
+ const isGoodToken = successfulScenarios.includes(token.scenario);
614
+ const isSkilled = [
615
+ "elite_analyst",
616
+ "skilled_trader",
617
+ "contrarian"
618
+ ].includes(actor.archetype);
619
+ if (isSkilled && isGoodToken) return "profit";
620
+ if (!isSkilled && !isGoodToken) return "loss";
621
+ if (actor.archetype === "rug_promoter" && !isGoodToken) return "loss";
622
+ return "neutral";
623
+ }
624
+ calculateActualProfits(calls, tokens, priceHistory) {
625
+ for (const call of calls) {
626
+ const token = tokens.get(call.caMentioned || "");
627
+ if (!token) continue;
628
+ const history = priceHistory.get(token.address) || [];
629
+ const callIndex = history.findIndex(
630
+ (p) => p.timestamp.getTime() === call.timestamp
631
+ );
632
+ if (callIndex === -1 || callIndex === history.length - 1) {
633
+ call.simulationMetadata.actualProfit = 0;
634
+ continue;
635
+ }
636
+ if (call.sentiment === "negative") {
637
+ const entryPrice2 = history[callIndex].price;
638
+ const exitIndex2 = Math.min(callIndex + 24, history.length - 1);
639
+ const exitPrice2 = history[exitIndex2].price;
640
+ const priceDropPercent = (entryPrice2 - exitPrice2) / entryPrice2 * 100;
641
+ call.simulationMetadata.actualProfit = priceDropPercent;
642
+ continue;
643
+ }
644
+ let exitIndex;
645
+ let forcedExit = false;
646
+ if ([
647
+ "rug_fast" /* RUG_PULL_FAST */,
648
+ "rug_slow" /* RUG_PULL_SLOW */,
649
+ "scam" /* SCAM_TOKEN */
650
+ ].includes(token.scenario)) {
651
+ let rugIndex = callIndex;
652
+ for (let i = callIndex + 1; i < history.length; i++) {
653
+ if (history[i].price < history[callIndex].price * 0.1) {
654
+ rugIndex = i;
655
+ forcedExit = true;
656
+ break;
657
+ }
658
+ }
659
+ exitIndex = rugIndex;
660
+ } else if (token.scenario === "pump_dump" /* PUMP_AND_DUMP */) {
661
+ let dumpIndex = callIndex;
662
+ let peakPrice = history[callIndex].price;
663
+ for (let i = callIndex + 1; i < history.length; i++) {
664
+ if (history[i].price > peakPrice) {
665
+ peakPrice = history[i].price;
666
+ } else if (history[i].price < peakPrice * 0.3) {
667
+ dumpIndex = i;
668
+ forcedExit = true;
669
+ break;
670
+ }
671
+ }
672
+ exitIndex = dumpIndex;
673
+ } else {
674
+ if (call.simulationMetadata.actorArchetype === "elite_analyst") {
675
+ exitIndex = Math.min(callIndex + 72, history.length - 1);
676
+ } else if (call.simulationMetadata.actorArchetype === "skilled_trader") {
677
+ exitIndex = Math.min(callIndex + 48, history.length - 1);
678
+ } else if (["pump_chaser", "fomo_trader"].includes(
679
+ call.simulationMetadata.actorArchetype
680
+ )) {
681
+ exitIndex = Math.min(callIndex + 24, history.length - 1);
682
+ } else {
683
+ exitIndex = Math.min(callIndex + 24, history.length - 1);
684
+ }
685
+ }
686
+ const entryPrice = history[callIndex].price;
687
+ const exitPrice = history[exitIndex].price;
688
+ let effectiveEntryPrice = entryPrice;
689
+ if (["fomo_trader", "pump_chaser"].includes(
690
+ call.simulationMetadata.actorArchetype
691
+ )) {
692
+ effectiveEntryPrice = entryPrice * 1.15;
693
+ } else if (call.simulationMetadata.actorArchetype === "rug_promoter") {
694
+ if ([
695
+ "rug_fast" /* RUG_PULL_FAST */,
696
+ "rug_slow" /* RUG_PULL_SLOW */,
697
+ "scam" /* SCAM_TOKEN */
698
+ ].includes(token.scenario)) {
699
+ effectiveEntryPrice = entryPrice * 1.2;
700
+ }
701
+ } else if (call.simulationMetadata.actorArchetype === "elite_analyst") {
702
+ effectiveEntryPrice = entryPrice * 0.98;
703
+ }
704
+ let effectiveExitPrice = exitPrice;
705
+ if (forcedExit && ["pump_chaser", "fomo_trader", "rug_promoter"].includes(
706
+ call.simulationMetadata.actorArchetype
707
+ )) {
708
+ effectiveExitPrice = exitPrice * 0.9;
709
+ }
710
+ const profitPercent = (effectiveExitPrice - effectiveEntryPrice) / effectiveEntryPrice * 100;
711
+ call.simulationMetadata.actualProfit = profitPercent;
712
+ }
713
+ return Promise.resolve();
714
+ }
715
+ async cacheResults(result, config) {
716
+ const outputDir = config.outputDir;
717
+ await fs.mkdir(outputDir, { recursive: true });
718
+ const callsPath = path.join(outputDir, "simulated_calls.json");
719
+ await fs.writeFile(callsPath, JSON.stringify(result.calls, null, 2));
720
+ const tokensPath = path.join(outputDir, "simulated_tokens.json");
721
+ await fs.writeFile(
722
+ tokensPath,
723
+ JSON.stringify(Array.from(result.tokens.entries()), null, 2)
724
+ );
725
+ const pricesPath = path.join(outputDir, "price_history.json");
726
+ await fs.writeFile(
727
+ pricesPath,
728
+ JSON.stringify(Array.from(result.priceHistory.entries()), null, 2)
729
+ );
730
+ const perfPath = path.join(outputDir, "actor_performance.json");
731
+ await fs.writeFile(
732
+ perfPath,
733
+ JSON.stringify(Array.from(result.actorPerformance.entries()), null, 2)
734
+ );
735
+ console.log(`\u{1F4C1} Results cached to ${outputDir}`);
736
+ }
737
+ async loadCachedSimulation(outputDir) {
738
+ try {
739
+ const callsData = await fs.readFile(
740
+ path.join(outputDir, "simulated_calls.json"),
741
+ "utf-8"
742
+ );
743
+ const tokensData = await fs.readFile(
744
+ path.join(outputDir, "simulated_tokens.json"),
745
+ "utf-8"
746
+ );
747
+ const pricesData = await fs.readFile(
748
+ path.join(outputDir, "price_history.json"),
749
+ "utf-8"
750
+ );
751
+ const perfData = await fs.readFile(
752
+ path.join(outputDir, "actor_performance.json"),
753
+ "utf-8"
754
+ );
755
+ return {
756
+ calls: JSON.parse(callsData),
757
+ tokens: new Map(JSON.parse(tokensData)),
758
+ priceHistory: new Map(JSON.parse(pricesData)),
759
+ actorPerformance: new Map(JSON.parse(perfData))
760
+ };
761
+ } catch (error) {
762
+ console.error("Failed to load cached simulation:", error);
763
+ return null;
764
+ }
765
+ }
766
+ }
767
+ export {
768
+ SimulationRunner,
769
+ TokenScenario
770
+ };
771
+ //# sourceMappingURL=simulationRunner.js.map