@elizaos/plugin-social-alpha 2.0.3-beta.6 → 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,455 @@
1
+ function formatPrice(price) {
2
+ return new Intl.NumberFormat("en-US", {
3
+ style: "currency",
4
+ currency: "USD",
5
+ minimumFractionDigits: price < 1 ? 6 : 2,
6
+ maximumFractionDigits: price < 1 ? 6 : 2
7
+ }).format(price);
8
+ }
9
+ function formatPercent(value) {
10
+ return `${value >= 0 ? "+" : ""}${value.toFixed(2)}%`;
11
+ }
12
+ function formatNumber(value) {
13
+ return new Intl.NumberFormat("en-US").format(value);
14
+ }
15
+ function formatDate(dateString) {
16
+ const date = dateString instanceof Date ? dateString : new Date(dateString);
17
+ return date.toLocaleString();
18
+ }
19
+ function normalizeBalance(balanceStr, decimals) {
20
+ const balance = typeof balanceStr === "string" ? BigInt(balanceStr) : balanceStr;
21
+ return Number(balance) / 10 ** decimals;
22
+ }
23
+ function calculateTradeMetrics(transactions, token) {
24
+ let totalBought = 0;
25
+ let totalBoughtValue = 0;
26
+ let totalSold = 0;
27
+ let totalSoldValue = 0;
28
+ let totalTransferIn = 0;
29
+ let totalTransferOut = 0;
30
+ let volumeUsd = 0;
31
+ let firstTradeTime = /* @__PURE__ */ new Date();
32
+ let lastTradeTime = /* @__PURE__ */ new Date(0);
33
+ for (const tx of transactions) {
34
+ const normalizedAmount = normalizeBalance(tx.amount, token.decimals || 0);
35
+ const price = tx.price ? Number.parseFloat(tx.price) : 0;
36
+ const value = normalizedAmount * price;
37
+ if (tx.timestamp < firstTradeTime) firstTradeTime = new Date(tx.timestamp);
38
+ if (tx.timestamp > lastTradeTime) lastTradeTime = new Date(tx.timestamp);
39
+ switch (tx.type) {
40
+ case "BUY":
41
+ totalBought += normalizedAmount;
42
+ totalBoughtValue += value;
43
+ volumeUsd += value;
44
+ break;
45
+ case "SELL":
46
+ totalSold += normalizedAmount;
47
+ totalSoldValue += value;
48
+ volumeUsd += value;
49
+ break;
50
+ case "transfer_in":
51
+ totalTransferIn += normalizedAmount;
52
+ break;
53
+ case "transfer_out":
54
+ totalTransferOut += normalizedAmount;
55
+ break;
56
+ }
57
+ }
58
+ const averageEntryPrice = totalBought > 0 ? totalBoughtValue / totalBought : 0;
59
+ const averageExitPrice = totalSold > 0 ? totalSoldValue / totalSold : 0;
60
+ const realizedPnL = totalSoldValue - totalSold * averageEntryPrice;
61
+ const realizedPnLPercent = averageEntryPrice > 0 ? (averageExitPrice - averageEntryPrice) / averageEntryPrice * 100 : 0;
62
+ return {
63
+ totalBought,
64
+ totalBoughtValue,
65
+ totalSold,
66
+ totalSoldValue,
67
+ totalTransferIn,
68
+ totalTransferOut,
69
+ averageEntryPrice,
70
+ averageExitPrice,
71
+ realizedPnL,
72
+ realizedPnLPercent,
73
+ volumeUsd,
74
+ firstTradeTime,
75
+ lastTradeTime
76
+ };
77
+ }
78
+ function calculatePositionPerformance(position, token, transactions) {
79
+ const normalizedBalance = normalizeBalance(
80
+ position.balance,
81
+ token.decimals || 0
82
+ );
83
+ const initialPrice = Number.parseFloat(position.initialPrice);
84
+ const currentPrice = token.price || 0;
85
+ const trades = calculateTradeMetrics(transactions, token);
86
+ const currentValue = normalizedBalance * currentPrice;
87
+ const initialValue = normalizedBalance * initialPrice;
88
+ const costBasis = normalizedBalance * trades.averageEntryPrice;
89
+ const unrealizedPnL = currentValue - costBasis;
90
+ const unrealizedPnLPercent = trades.averageEntryPrice > 0 ? (currentPrice - trades.averageEntryPrice) / trades.averageEntryPrice * 100 : 0;
91
+ const totalPnL = trades.realizedPnL + unrealizedPnL;
92
+ const totalCost = trades.totalBought * trades.averageEntryPrice;
93
+ const totalPnLPercent = totalCost > 0 ? totalPnL / totalCost * 100 : 0;
94
+ const profitLoss = currentValue - initialValue;
95
+ const profitLossPercentage = profitLoss / initialValue * 100;
96
+ const priceChange = currentPrice - initialPrice;
97
+ const priceChangePercentage = priceChange / initialPrice * 100;
98
+ return {
99
+ ...position,
100
+ token,
101
+ currentValue,
102
+ initialValue,
103
+ profitLoss,
104
+ profitLossPercentage,
105
+ priceChange,
106
+ priceChangePercentage,
107
+ normalizedBalance,
108
+ trades,
109
+ unrealizedPnL,
110
+ unrealizedPnLPercent,
111
+ totalPnL,
112
+ totalPnLPercent
113
+ };
114
+ }
115
+ function formatTokenPerformance(token) {
116
+ return `
117
+ Token: ${token.name || "Unknown"} (${token.symbol || "Unknown"})
118
+ Address: ${token.address || "N/A"}
119
+ Chain: ${token.chain || "Unknown"}
120
+ Last Updated: ${token.updatedAt ? formatDate(token.updatedAt) : "N/A"}
121
+ Price: ${token.price !== void 0 ? formatPrice(token.price) : "N/A"} (24h: ${token.price24hChange !== void 0 ? formatPercent(token.price24hChange) : "N/A"})
122
+ Volume: ${token.volume !== void 0 ? formatPrice(token.volume) : "N/A"} (24h: ${token.volume24hChange !== void 0 ? formatPercent(token.volume24hChange) : "N/A"})
123
+ Liquidity: ${token.liquidity !== void 0 ? formatPrice(token.liquidity) : "N/A"}
124
+ Holders: ${token.holders !== void 0 ? formatNumber(token.holders) : "N/A"} (24h: ${token.holders24hChange !== void 0 ? formatPercent(token.holders24hChange) : "N/A"})
125
+ Trades: ${token.trades !== void 0 ? formatNumber(token.trades) : "N/A"}
126
+ Security Info:
127
+ - Creator: ${token.metadata?.security?.creatorAddress || "N/A"}
128
+ - Creation Time: ${token.metadata?.security?.creationTime ? new Date((token.metadata?.security).creationTime * 1e3).toLocaleString() : "N/A"}
129
+ - Total Supply: ${token.metadata?.security?.totalSupply !== void 0 ? formatNumber((token.metadata?.security).totalSupply) : "N/A"}
130
+ - Top 10 Holders: ${token.metadata?.security?.top10HolderPercent !== void 0 ? formatPercent((token.metadata?.security).top10HolderPercent) : "N/A"}
131
+ - Token Standard: ${token.metadata?.security?.isToken2022 ? "Token-2022" : "SPL Token"}
132
+ `.trim();
133
+ }
134
+ function formatTransactionHistory(transactions, token) {
135
+ return transactions.sort(
136
+ (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
137
+ ).map((tx) => {
138
+ const normalizedAmount = normalizeBalance(tx.amount, token.decimals || 0);
139
+ const price = tx.price ? formatPrice(Number.parseFloat(tx.price)) : "N/A";
140
+ const value = tx.valueUsd ? formatPrice(tx.valueUsd) : "N/A";
141
+ return `
142
+ ${formatDate(tx.timestamp)} - ${tx.type}
143
+ Amount: ${formatNumber(normalizedAmount)} ${token.symbol}
144
+ Price: ${price}
145
+ Value: ${value}
146
+ TX: ${tx.transactionHash}
147
+ `.trim();
148
+ });
149
+ }
150
+ function formatPositionPerformance(position, token, transactions) {
151
+ const perfData = calculatePositionPerformance(position, token, transactions);
152
+ return `
153
+ Position ID: ${position.id}
154
+ Type: ${position.isSimulation ? "Simulation" : "Real"}
155
+ Token: ${token.name} (${token.symbol})
156
+ Wallet: ${position.walletAddress}
157
+
158
+ Trading Summary:
159
+ - Total Bought: ${formatNumber(perfData.trades.totalBought)} ${token.symbol}
160
+ - Total Sold: ${formatNumber(perfData.trades.totalSold)} ${token.symbol}
161
+ - Average Entry: ${formatPrice(perfData.trades.averageEntryPrice)}
162
+ - Average Exit: ${formatPrice(perfData.trades.averageExitPrice)}
163
+ - Trading Volume: ${formatPrice(perfData.trades.volumeUsd)}
164
+ - First Trade: ${formatDate(perfData.trades.firstTradeTime)}
165
+ - Last Trade: ${formatDate(perfData.trades.lastTradeTime)}
166
+
167
+ Performance Metrics:
168
+ - Current Price: ${token.price !== void 0 ? formatPrice(token.price) : "N/A"}
169
+ - Initial Price: ${formatPrice(Number.parseFloat(position.initialPrice))}
170
+ - Price Change: ${formatPrice(perfData.priceChange)} (${formatPercent(perfData.priceChangePercentage)})
171
+
172
+ Position Value:
173
+ - Current Balance: ${formatNumber(perfData.normalizedBalance)} ${token.symbol}
174
+ - Current Value: ${formatPrice(perfData.currentValue)}
175
+ - Realized P&L: ${formatPrice(perfData.trades.realizedPnL)} (${formatPercent(perfData.trades.realizedPnLPercent)})
176
+ - Unrealized P&L: ${formatPrice(perfData.unrealizedPnL)} (${formatPercent(perfData.unrealizedPnLPercent)})
177
+ - Total P&L: ${formatPrice(perfData.totalPnL)} (${formatPercent(perfData.totalPnLPercent)})
178
+
179
+ Market Info:
180
+ - Current Liquidity: ${token.liquidity !== void 0 ? formatPrice(token.liquidity) : "N/A"}
181
+ - 24h Volume: ${token.volume !== void 0 ? formatPrice(token.volume) : "N/A"}
182
+
183
+ Transaction History:
184
+ ${formatTransactionHistory(transactions, token)}
185
+ `.trim();
186
+ }
187
+ function formatFullReport(tokens, positions, transactions) {
188
+ const tokenMap = new Map(tokens.map((token) => [token.address, token]));
189
+ const txMap = /* @__PURE__ */ new Map();
190
+ transactions.forEach((tx) => {
191
+ if (!txMap.has(tx.positionId)) {
192
+ txMap.set(tx.positionId, []);
193
+ }
194
+ txMap.get(tx.positionId)?.push(tx);
195
+ });
196
+ const tokenReports = tokens.map((token) => formatTokenPerformance(token));
197
+ const positionsWithData = positions.flatMap((position) => {
198
+ const token = tokenMap.get(position.tokenAddress);
199
+ return token ? [{ position, token, transactions: txMap.get(position.id) || [] }] : [];
200
+ });
201
+ const positionReports = positionsWithData.map(
202
+ ({ position, token, transactions: transactions2 }) => formatPositionPerformance(position, token, transactions2)
203
+ );
204
+ const { totalCurrentValue, totalRealizedPnL, totalUnrealizedPnL } = positions.reduce(
205
+ (acc, position) => {
206
+ const token = tokenMap.get(position.tokenAddress);
207
+ if (token) {
208
+ const perfData = calculatePositionPerformance(
209
+ position,
210
+ token,
211
+ txMap.get(position.id) || []
212
+ );
213
+ return {
214
+ totalCurrentValue: acc.totalCurrentValue + perfData.currentValue,
215
+ totalRealizedPnL: acc.totalRealizedPnL + perfData.trades.realizedPnL,
216
+ totalUnrealizedPnL: acc.totalUnrealizedPnL + perfData.unrealizedPnL
217
+ };
218
+ }
219
+ return acc;
220
+ },
221
+ {
222
+ totalCurrentValue: 0,
223
+ totalRealizedPnL: 0,
224
+ totalUnrealizedPnL: 0
225
+ }
226
+ );
227
+ const totalPnL = totalRealizedPnL + totalUnrealizedPnL;
228
+ return {
229
+ tokenReports,
230
+ positionReports,
231
+ totalCurrentValue: formatPrice(totalCurrentValue),
232
+ totalRealizedPnL: formatPrice(totalRealizedPnL),
233
+ totalUnrealizedPnL: formatPrice(totalUnrealizedPnL),
234
+ totalPnL: formatPrice(totalPnL),
235
+ positionsWithBalance: positionsWithData
236
+ };
237
+ }
238
+ function formatScore(score) {
239
+ return score.toFixed(2);
240
+ }
241
+ function formatPercentMetric(value) {
242
+ return `${(value * 100).toFixed(1)}%`;
243
+ }
244
+ function calculateMetricTrend(current, metric, history) {
245
+ if (history.length === 0)
246
+ return { trend: 0, description: "No historical data" };
247
+ const sortedHistory = history.slice().sort(
248
+ (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
249
+ );
250
+ const previousValue = sortedHistory[0].metrics[metric];
251
+ const trend = (current[metric] - previousValue) / previousValue * 100;
252
+ let description = "stable";
253
+ if (trend > 5) description = "improving";
254
+ if (trend < -5) description = "declining";
255
+ return { trend, description };
256
+ }
257
+ function calculateTrend(current, historicalValues) {
258
+ if (historicalValues.length === 0) return 0;
259
+ const previousValue = historicalValues[0];
260
+ return (current - previousValue) / previousValue * 100;
261
+ }
262
+ function formatTrendArrow(trend) {
263
+ if (trend > 5) return "\u2191";
264
+ if (trend < -5) return "\u2193";
265
+ return "\u2192";
266
+ }
267
+ function calculatePeriodTrends(history, period = null) {
268
+ if (!period) {
269
+ const monthlyData = history.reduce(
270
+ (acc, record) => {
271
+ const month = new Date(record.timestamp).toISOString().slice(0, 7);
272
+ const currentData = acc.get(month) ?? {
273
+ performances: [],
274
+ successes: 0,
275
+ total: 0
276
+ };
277
+ acc.set(month, {
278
+ performances: [
279
+ ...currentData.performances,
280
+ record.metrics.avgTokenPerformance
281
+ ],
282
+ successes: currentData.successes + record.metrics.successfulRecs,
283
+ total: currentData.total + record.metrics.totalRecommendations
284
+ });
285
+ return acc;
286
+ },
287
+ /* @__PURE__ */ new Map()
288
+ );
289
+ return Array.from(monthlyData.entries()).map(([month, data]) => ({
290
+ period: month,
291
+ avgPerformance: data.performances.reduce((a, b) => a + b, 0) / data.performances.length,
292
+ successRate: data.successes / data.total,
293
+ recommendations: data.total
294
+ })).sort((a, b) => b.period.localeCompare(a.period));
295
+ }
296
+ const cutoffDate = /* @__PURE__ */ new Date();
297
+ cutoffDate.setDate(cutoffDate.getDate() - period.days);
298
+ const periodData = history.filter(
299
+ (record) => new Date(record.timestamp) >= cutoffDate
300
+ );
301
+ if (periodData.length === 0) {
302
+ return [
303
+ {
304
+ period: period.label,
305
+ avgPerformance: 0,
306
+ successRate: 0,
307
+ recommendations: 0
308
+ }
309
+ ];
310
+ }
311
+ const performances = periodData.map(
312
+ (record) => record.metrics.avgTokenPerformance
313
+ );
314
+ const totalRecommendations = periodData.reduce(
315
+ (sum, record) => sum + record.metrics.totalRecommendations,
316
+ 0
317
+ );
318
+ const successfulRecs = periodData.reduce(
319
+ (sum, record) => sum + record.metrics.successfulRecs,
320
+ 0
321
+ );
322
+ return [
323
+ {
324
+ period: period.label,
325
+ avgPerformance: performances.reduce((a, b) => a + b, 0) / performances.length,
326
+ successRate: totalRecommendations > 0 ? successfulRecs / totalRecommendations : 0,
327
+ recommendations: totalRecommendations
328
+ }
329
+ ];
330
+ }
331
+ function formatTrends(trends) {
332
+ return trends.map(
333
+ (trend) => `
334
+ ${trend.period}:
335
+ - Performance: ${formatPercent(trend.avgPerformance)}
336
+ - Success Rate: ${formatPercentMetric(trend.successRate)}
337
+ - Recommendations: ${trend.recommendations}`.trim()
338
+ ).join("\n\n");
339
+ }
340
+ function formatRecommenderProfile(entity, metrics, history) {
341
+ const successRate = metrics.successfulRecs / metrics.totalRecommendations;
342
+ const trustTrend = calculateMetricTrend(metrics, "trustScore", history);
343
+ const performanceTrend = calculateMetricTrend(
344
+ metrics,
345
+ "avgTokenPerformance",
346
+ history
347
+ );
348
+ return `
349
+ Entity Profile: ${entity.metadata?.username || "Unknown"}
350
+ Platform: ${entity.metadata?.platform || "Unknown"}
351
+ ID: ${entity.id}
352
+
353
+ Performance Metrics:
354
+ - Trust Score: ${formatScore(metrics.trustScore)} (${formatPercent(trustTrend.trend)} ${trustTrend.description})
355
+ - Success Rate: ${formatPercentMetric(successRate)}
356
+ - Recommendations: ${metrics.totalRecommendations} total, ${metrics.successfulRecs} successful
357
+ - Avg Token Performance: ${formatPercent(metrics.avgTokenPerformance)} (${formatPercent(performanceTrend.trend)} ${performanceTrend.description})
358
+
359
+ Risk Assessment:
360
+ - Consistency Score: ${formatScore(metrics.consistencyScore)}
361
+
362
+ Activity:
363
+ - Last Active: ${formatDate(metrics.lastUpdated)}
364
+ `.trim();
365
+ }
366
+ function formatRecommenderReport(entity, metrics, history) {
367
+ const sortedHistory = [...history].sort(
368
+ (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
369
+ );
370
+ const dailyTrends = calculatePeriodTrends(sortedHistory, {
371
+ label: "24 Hours",
372
+ days: 1
373
+ });
374
+ const weeklyTrends = calculatePeriodTrends(sortedHistory, {
375
+ label: "7 Days",
376
+ days: 7
377
+ });
378
+ const monthlyTrends = calculatePeriodTrends(sortedHistory);
379
+ const successTrend = calculateTrend(
380
+ metrics.successfulRecs / metrics.totalRecommendations,
381
+ sortedHistory.map(
382
+ (h) => h.metrics.successfulRecs / h.metrics.totalRecommendations
383
+ )
384
+ );
385
+ const performanceTrend = calculateTrend(
386
+ metrics.avgTokenPerformance,
387
+ sortedHistory.map((h) => h.metrics.avgTokenPerformance)
388
+ );
389
+ return `
390
+ Username: ${entity.metadata?.username || "Unknown"}
391
+ Platform: ${entity.metadata?.platform || "Unknown"}
392
+ ID: ${entity.id}
393
+
394
+ === CURRENT METRICS ===
395
+ Trust Score: ${formatScore(metrics.trustScore)}
396
+ Success Rate: ${formatPercentMetric(metrics.successfulRecs / metrics.totalRecommendations)} (${formatTrendArrow(successTrend)})
397
+ Total Recommendations: ${metrics.totalRecommendations}
398
+ Average Token Performance: ${formatPercent(metrics.avgTokenPerformance)} (${formatTrendArrow(performanceTrend)})
399
+
400
+ Risk Analysis:
401
+ - Consistency: ${formatScore(metrics.consistencyScore)}
402
+
403
+ Activity Status:
404
+ - Last Active: ${formatDate(metrics.lastUpdated)}
405
+
406
+ === PERFORMANCE TRENDS ===
407
+ ${formatTrends(dailyTrends)}
408
+
409
+ ${formatTrends(weeklyTrends)}
410
+
411
+ Monthly Average Performance:
412
+ ${formatTrends(monthlyTrends)}`.trim();
413
+ }
414
+ function formatTopRecommendersOverview(recommenders, metrics, history) {
415
+ const sortedRecommenders = [...recommenders].sort((a, b) => {
416
+ if (!a.id || !b.id) return 0;
417
+ const metricsA = metrics.get(a.id);
418
+ const metricsB = metrics.get(b.id);
419
+ if (!metricsA || !metricsB) return 0;
420
+ return metricsB.trustScore - metricsA.trustScore;
421
+ });
422
+ return `
423
+ <top_recommenders>
424
+ ${sortedRecommenders.map((entity) => {
425
+ if (!entity.id) return null;
426
+ const metric = metrics.get(entity.id);
427
+ if (!metric) return null;
428
+ const historicalData = history.get(entity.id) || [];
429
+ const trustTrend = calculateMetricTrend(
430
+ metric,
431
+ "trustScore",
432
+ historicalData
433
+ );
434
+ const performanceTrend = calculateMetricTrend(
435
+ metric,
436
+ "avgTokenPerformance",
437
+ historicalData
438
+ );
439
+ return `
440
+ ${entity.metadata?.username || "Unknown"} (${entity.metadata?.platform || "Unknown"})
441
+ Trust Score: ${formatScore(metric.trustScore)} (${formatPercent(trustTrend.trend)} ${trustTrend.description})
442
+ Performance Score: ${formatScore(metric.avgTokenPerformance)} (${formatPercent(performanceTrend.trend)} ${performanceTrend.description})
443
+ Success Rate: ${formatPercentMetric(metric.successfulRecs / metric.totalRecommendations)}
444
+ Last Active: ${formatDate(metric.lastUpdated)}
445
+ `.trim();
446
+ }).filter((report) => report !== null).join("\n\n")}
447
+ </top_recommenders>`.trim();
448
+ }
449
+ export {
450
+ formatFullReport,
451
+ formatRecommenderProfile,
452
+ formatRecommenderReport,
453
+ formatTopRecommendersOverview
454
+ };
455
+ //# sourceMappingURL=reports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/reports.ts"],"sourcesContent":["import type { Entity } from \"@elizaos/core\";\nimport type {\n\tMetadataJsonValue,\n\tPositionPerformance,\n\tPositionWithBalance,\n\tRecommenderMetrics,\n\tRecommenderMetricsHistory,\n\tTokenPerformance,\n\tTradeMetrics,\n\tTransaction,\n} from \"./types.js\";\n\n/**\n * Formats a price into a currency format.\n *\n * @param {number} price - The price to be formatted.\n * @returns {string} The price formatted as a currency.\n */\nfunction formatPrice(price: number): string {\n\treturn new Intl.NumberFormat(\"en-US\", {\n\t\tstyle: \"currency\",\n\t\tcurrency: \"USD\",\n\t\tminimumFractionDigits: price < 1 ? 6 : 2,\n\t\tmaximumFractionDigits: price < 1 ? 6 : 2,\n\t}).format(price);\n}\n\n/**\n * Formats a number as a percentage string with two decimal places.\n * @param {number} value - The number to be formatted as a percentage.\n * @returns {string} The formatted percentage string.\n */\nfunction formatPercent(value: number): string {\n\treturn `${value >= 0 ? \"+\" : \"\"}${value.toFixed(2)}%`;\n}\n\n/**\n * Formats a given number into a string representation using the \"en-US\" number format.\n *\n * @param {number} value - The number to be formatted.\n * @returns {string} The formatted number as a string.\n */\nfunction formatNumber(value: number): string {\n\treturn new Intl.NumberFormat(\"en-US\").format(value);\n}\n\n/**\n * Formats a given date string or Date object into a locale-specific string representation.\n *\n * @param {string | Date} dateString - The date string to be formatted or a Date object.\n * @returns {string} The formatted date string.\n */\nfunction formatDate(dateString: string | Date): string {\n\tconst date = dateString instanceof Date ? dateString : new Date(dateString);\n\treturn date.toLocaleString();\n}\n\n/**\n * Function to normalize the balance based on the decimals provided.\n * @param {string | bigint} balanceStr - The balance to normalize, can be a string or bigint.\n * @param {number} decimals - The number of decimal places to normalize to.\n * @returns {number} The normalized balance as a number.\n */\nfunction normalizeBalance(\n\tbalanceStr: string | bigint,\n\tdecimals: number,\n): number {\n\tconst balance =\n\t\ttypeof balanceStr === \"string\" ? BigInt(balanceStr) : balanceStr;\n\treturn Number(balance) / 10 ** decimals;\n}\n\n/**\n * Calculate various trade metrics based on transactions and token performance.\n *\n * @param {Transaction[]} transactions - Array of transactions to calculate metrics for.\n * @param {TokenPerformance} token - Token performance object.\n * @returns {TradeMetrics} Object containing calculated trade metrics.\n */\nfunction calculateTradeMetrics(\n\ttransactions: Transaction[],\n\ttoken: TokenPerformance,\n): TradeMetrics {\n\tlet totalBought = 0;\n\tlet totalBoughtValue = 0;\n\tlet totalSold = 0;\n\tlet totalSoldValue = 0;\n\tlet totalTransferIn = 0;\n\tlet totalTransferOut = 0;\n\tlet volumeUsd = 0;\n\tlet firstTradeTime = new Date();\n\tlet lastTradeTime = new Date(0);\n\n\tfor (const tx of transactions) {\n\t\tconst normalizedAmount = normalizeBalance(tx.amount, token.decimals || 0);\n\t\tconst price = tx.price ? Number.parseFloat(tx.price) : 0;\n\t\tconst value = normalizedAmount * price;\n\n\t\tif (tx.timestamp < firstTradeTime) firstTradeTime = new Date(tx.timestamp);\n\t\tif (tx.timestamp > lastTradeTime) lastTradeTime = new Date(tx.timestamp);\n\n\t\tswitch (tx.type) {\n\t\t\tcase \"BUY\":\n\t\t\t\ttotalBought += normalizedAmount;\n\t\t\t\ttotalBoughtValue += value;\n\t\t\t\tvolumeUsd += value;\n\t\t\t\tbreak;\n\t\t\tcase \"SELL\":\n\t\t\t\ttotalSold += normalizedAmount;\n\t\t\t\ttotalSoldValue += value;\n\t\t\t\tvolumeUsd += value;\n\t\t\t\tbreak;\n\t\t\tcase \"transfer_in\":\n\t\t\t\ttotalTransferIn += normalizedAmount;\n\t\t\t\tbreak;\n\t\t\tcase \"transfer_out\":\n\t\t\t\ttotalTransferOut += normalizedAmount;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tconst averageEntryPrice =\n\t\ttotalBought > 0 ? totalBoughtValue / totalBought : 0;\n\tconst averageExitPrice = totalSold > 0 ? totalSoldValue / totalSold : 0;\n\tconst realizedPnL = totalSoldValue - totalSold * averageEntryPrice;\n\tconst realizedPnLPercent =\n\t\taverageEntryPrice > 0\n\t\t\t? ((averageExitPrice - averageEntryPrice) / averageEntryPrice) * 100\n\t\t\t: 0;\n\n\treturn {\n\t\ttotalBought,\n\t\ttotalBoughtValue,\n\t\ttotalSold,\n\t\ttotalSoldValue,\n\t\ttotalTransferIn,\n\t\ttotalTransferOut,\n\t\taverageEntryPrice,\n\t\taverageExitPrice,\n\t\trealizedPnL,\n\t\trealizedPnLPercent,\n\t\tvolumeUsd,\n\t\tfirstTradeTime,\n\t\tlastTradeTime,\n\t};\n}\n\n/**\n * Calculate the performance metrics of a given position.\n *\n * @param {PositionWithBalance} position The position with balance information.\n * @param {TokenPerformance} token The performance metrics of the token.\n * @param {Transaction[]} transactions The list of transactions related to the position.\n * @returns {PositionPerformance} The performance metrics of the position including current value, initial value,\n * profit/loss, profit/loss percentage, price change, price change percentage, normalized balance, trade metrics,\n * unrealized profit/loss, unrealized profit/loss percentage, total profit/loss, and total profit/loss percentage.\n */\n\nfunction calculatePositionPerformance(\n\tposition: PositionWithBalance,\n\ttoken: TokenPerformance,\n\ttransactions: Transaction[],\n): PositionPerformance {\n\tconst normalizedBalance = normalizeBalance(\n\t\tposition.balance,\n\t\ttoken.decimals || 0,\n\t);\n\tconst initialPrice = Number.parseFloat(position.initialPrice);\n\tconst currentPrice = token.price || 0;\n\n\tconst trades = calculateTradeMetrics(transactions, token);\n\n\tconst currentValue = normalizedBalance * currentPrice;\n\tconst initialValue = normalizedBalance * initialPrice;\n\n\t// Calculate unrealized P&L based on average entry price\n\tconst costBasis = normalizedBalance * trades.averageEntryPrice;\n\tconst unrealizedPnL = currentValue - costBasis;\n\tconst unrealizedPnLPercent =\n\t\ttrades.averageEntryPrice > 0\n\t\t\t? ((currentPrice - trades.averageEntryPrice) / trades.averageEntryPrice) *\n\t\t\t\t100\n\t\t\t: 0;\n\n\t// Total P&L combines realized and unrealized\n\tconst totalPnL = trades.realizedPnL + unrealizedPnL;\n\tconst totalCost = trades.totalBought * trades.averageEntryPrice;\n\tconst totalPnLPercent = totalCost > 0 ? (totalPnL / totalCost) * 100 : 0;\n\n\tconst profitLoss = currentValue - initialValue;\n\tconst profitLossPercentage = (profitLoss / initialValue) * 100;\n\tconst priceChange = currentPrice - initialPrice;\n\tconst priceChangePercentage = (priceChange / initialPrice) * 100;\n\n\treturn {\n\t\t...position,\n\t\ttoken,\n\t\tcurrentValue,\n\t\tinitialValue,\n\t\tprofitLoss,\n\t\tprofitLossPercentage,\n\t\tpriceChange,\n\t\tpriceChangePercentage,\n\t\tnormalizedBalance,\n\t\ttrades,\n\t\tunrealizedPnL,\n\t\tunrealizedPnLPercent,\n\t\ttotalPnL,\n\t\ttotalPnLPercent,\n\t};\n}\n\n/**\n * Formats the token performance information into a readable string.\n * @param {TokenPerformance} token - The token performance object to format.\n * @returns {string} The formatted token performance information.\n */\nfunction formatTokenPerformance(token: TokenPerformance): string {\n\treturn `\n Token: ${token.name || \"Unknown\"} (${token.symbol || \"Unknown\"})\n Address: ${token.address || \"N/A\"}\n Chain: ${token.chain || \"Unknown\"}\n Last Updated: ${token.updatedAt ? formatDate(token.updatedAt) : \"N/A\"}\n Price: ${token.price !== undefined ? formatPrice(token.price) : \"N/A\"} (24h: ${token.price24hChange !== undefined ? formatPercent(token.price24hChange) : \"N/A\"})\n Volume: ${token.volume !== undefined ? formatPrice(token.volume) : \"N/A\"} (24h: ${token.volume24hChange !== undefined ? formatPercent(token.volume24hChange) : \"N/A\"})\n Liquidity: ${token.liquidity !== undefined ? formatPrice(token.liquidity) : \"N/A\"}\n Holders: ${token.holders !== undefined ? formatNumber(token.holders) : \"N/A\"} (24h: ${token.holders24hChange !== undefined ? formatPercent(token.holders24hChange) : \"N/A\"})\n Trades: ${token.trades !== undefined ? formatNumber(token.trades) : \"N/A\"}\n Security Info:\n - Creator: ${(token.metadata?.security as Record<string, MetadataJsonValue> | undefined)?.creatorAddress || \"N/A\"}\n - Creation Time: ${(token.metadata?.security as Record<string, MetadataJsonValue> | undefined)?.creationTime ? new Date(((token.metadata?.security as Record<string, MetadataJsonValue>).creationTime as number) * 1000).toLocaleString() : \"N/A\"}\n - Total Supply: ${(token.metadata?.security as Record<string, MetadataJsonValue> | undefined)?.totalSupply !== undefined ? formatNumber((token.metadata?.security as Record<string, MetadataJsonValue>).totalSupply as number) : \"N/A\"}\n - Top 10 Holders: ${(token.metadata?.security as Record<string, MetadataJsonValue> | undefined)?.top10HolderPercent !== undefined ? formatPercent((token.metadata?.security as Record<string, MetadataJsonValue>).top10HolderPercent as number) : \"N/A\"}\n - Token Standard: ${(token.metadata?.security as Record<string, MetadataJsonValue> | undefined)?.isToken2022 ? \"Token-2022\" : \"SPL Token\"}\n `.trim();\n}\n\n/**\n * Formats transaction history data into an array of strings for display.\n * @param {Transaction[]} transactions - The list of transactions to format.\n * @param {TokenPerformance} token - The token performance data used for formatting.\n * @returns {string[]} - An array of formatted strings representing each transaction.\n */\nfunction formatTransactionHistory(\n\ttransactions: Transaction[],\n\ttoken: TokenPerformance,\n): string[] {\n\treturn transactions\n\t\t.sort(\n\t\t\t(a, b) =>\n\t\t\t\tnew Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),\n\t\t)\n\t\t.map((tx) => {\n\t\t\tconst normalizedAmount = normalizeBalance(tx.amount, token.decimals || 0);\n\t\t\tconst price = tx.price ? formatPrice(Number.parseFloat(tx.price)) : \"N/A\";\n\t\t\tconst value = tx.valueUsd ? formatPrice(tx.valueUsd) : \"N/A\";\n\n\t\t\treturn `\n ${formatDate(tx.timestamp)} - ${tx.type}\n Amount: ${formatNumber(normalizedAmount)} ${token.symbol}\n Price: ${price}\n Value: ${value}\n TX: ${tx.transactionHash}\n `.trim();\n\t\t});\n}\n\n/**\n * Format the performance metrics and details of a position.\n *\n * @param {PositionWithBalance} position The position object containing balance information.\n * @param {TokenPerformance} token The token performance object.\n * @param {Transaction[]} transactions The list of transactions associated with the position.\n * @returns {string} The formatted performance details of the position.\n */\nfunction formatPositionPerformance(\n\tposition: PositionWithBalance,\n\ttoken: TokenPerformance,\n\ttransactions: Transaction[],\n): string {\n\tconst perfData = calculatePositionPerformance(position, token, transactions);\n\n\treturn `\n Position ID: ${position.id}\n Type: ${position.isSimulation ? \"Simulation\" : \"Real\"}\n Token: ${token.name} (${token.symbol})\n Wallet: ${position.walletAddress}\n\n Trading Summary:\n - Total Bought: ${formatNumber(perfData.trades.totalBought)} ${token.symbol}\n - Total Sold: ${formatNumber(perfData.trades.totalSold)} ${token.symbol}\n - Average Entry: ${formatPrice(perfData.trades.averageEntryPrice)}\n - Average Exit: ${formatPrice(perfData.trades.averageExitPrice)}\n - Trading Volume: ${formatPrice(perfData.trades.volumeUsd)}\n - First Trade: ${formatDate(perfData.trades.firstTradeTime)}\n - Last Trade: ${formatDate(perfData.trades.lastTradeTime)}\n\n Performance Metrics:\n - Current Price: ${token.price !== undefined ? formatPrice(token.price) : \"N/A\"}\n - Initial Price: ${formatPrice(Number.parseFloat(position.initialPrice))}\n - Price Change: ${formatPrice(perfData.priceChange)} (${formatPercent(perfData.priceChangePercentage)})\n\n Position Value:\n - Current Balance: ${formatNumber(perfData.normalizedBalance)} ${token.symbol}\n - Current Value: ${formatPrice(perfData.currentValue)}\n - Realized P&L: ${formatPrice(perfData.trades.realizedPnL)} (${formatPercent(perfData.trades.realizedPnLPercent)})\n - Unrealized P&L: ${formatPrice(perfData.unrealizedPnL)} (${formatPercent(perfData.unrealizedPnLPercent)})\n - Total P&L: ${formatPrice(perfData.totalPnL)} (${formatPercent(perfData.totalPnLPercent)})\n\n Market Info:\n - Current Liquidity: ${token.liquidity !== undefined ? formatPrice(token.liquidity) : \"N/A\"}\n - 24h Volume: ${token.volume !== undefined ? formatPrice(token.volume) : \"N/A\"}\n\n Transaction History:\n ${formatTransactionHistory(transactions, token)}\n `.trim();\n}\n\n/**\n * Formats a full report based on the provided data.\n *\n * @param {TokenPerformance[]} tokens - Array of token performance data.\n * @param {PositionWithBalance[]} positions - Array of positions with balance data.\n * @param {Transaction[]} transactions - Array of transactions data.\n * @returns {{\n * tokenReports: Object[],\n * positionReports: Object[],\n * totalCurrentValue: string,\n * totalRealizedPnL: string,\n * totalUnrealizedPnL: string,\n * totalPnL: string,\n * positionsWithBalance: Object[],\n * }} Formatted full report containing token reports, position reports, total values, and positions with balance.\n */\nexport function formatFullReport(\n\ttokens: TokenPerformance[],\n\tpositions: PositionWithBalance[],\n\ttransactions: Transaction[],\n) {\n\tconst tokenMap = new Map(tokens.map((token) => [token.address, token]));\n\tconst txMap = new Map<string, Transaction[]>();\n\n\t// Group transactions by position ID\n\ttransactions.forEach((tx) => {\n\t\tif (!txMap.has(tx.positionId)) {\n\t\t\ttxMap.set(tx.positionId, []);\n\t\t}\n\t\ttxMap.get(tx.positionId)?.push(tx);\n\t});\n\n\tconst tokenReports = tokens.map((token) => formatTokenPerformance(token));\n\n\tconst positionsWithData = positions.flatMap((position) => {\n\t\tconst token = tokenMap.get(position.tokenAddress);\n\t\treturn token\n\t\t\t? [{ position, token, transactions: txMap.get(position.id) || [] }]\n\t\t\t: [];\n\t});\n\n\tconst positionReports = positionsWithData.map(\n\t\t({ position, token, transactions }) =>\n\t\t\tformatPositionPerformance(position, token, transactions),\n\t);\n\n\tconst { totalCurrentValue, totalRealizedPnL, totalUnrealizedPnL } =\n\t\tpositions.reduce(\n\t\t\t(acc, position) => {\n\t\t\t\tconst token = tokenMap.get(position.tokenAddress);\n\n\t\t\t\tif (token) {\n\t\t\t\t\tconst perfData = calculatePositionPerformance(\n\t\t\t\t\t\tposition,\n\t\t\t\t\t\ttoken,\n\t\t\t\t\t\ttxMap.get(position.id) || [],\n\t\t\t\t\t);\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttotalCurrentValue: acc.totalCurrentValue + perfData.currentValue,\n\t\t\t\t\t\ttotalRealizedPnL:\n\t\t\t\t\t\t\tacc.totalRealizedPnL + perfData.trades.realizedPnL,\n\t\t\t\t\t\ttotalUnrealizedPnL: acc.totalUnrealizedPnL + perfData.unrealizedPnL,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\treturn acc;\n\t\t\t},\n\t\t\t{\n\t\t\t\ttotalCurrentValue: 0,\n\t\t\t\ttotalRealizedPnL: 0,\n\t\t\t\ttotalUnrealizedPnL: 0,\n\t\t\t},\n\t\t);\n\n\tconst totalPnL = totalRealizedPnL + totalUnrealizedPnL;\n\n\treturn {\n\t\ttokenReports,\n\t\tpositionReports,\n\t\ttotalCurrentValue: formatPrice(totalCurrentValue),\n\t\ttotalRealizedPnL: formatPrice(totalRealizedPnL),\n\t\ttotalUnrealizedPnL: formatPrice(totalUnrealizedPnL),\n\t\ttotalPnL: formatPrice(totalPnL),\n\t\tpositionsWithBalance: positionsWithData,\n\t};\n}\n\n/**\n * Formats a numerical score to have exactly two decimal places.\n *\n * @param {number} score - The numerical score to be formatted.\n * @returns {string} The formatted score with two decimal places.\n */\n\nfunction formatScore(score: number): string {\n\treturn score.toFixed(2);\n}\n\n/**\n * Formats a numeric value into a percentage string with one decimal place.\n *\n * @param {number} value - The numeric value to be formatted as a percentage.\n * @returns {string} The formatted percentage string.\n */\nfunction formatPercentMetric(value: number): string {\n\treturn `${(value * 100).toFixed(1)}%`;\n}\n\n/**\n * TypeScript type to retrieve the keys of a given object `T` that have numeric values.\n */\ntype NumericKeys<T> = {\n\t[K in keyof T]: T[K] extends number ? K : never;\n}[keyof T];\n\n/**\n * Represents the numeric keys from the `RecommenderMetrics` type.\n */\ntype RecommenderNumericMetrics = NumericKeys<RecommenderMetrics>;\n\n/**\n * Calculate the trend of a specific metric based on historical data.\n * @template Metric - The type of metric to calculate trend for.\n * @param {RecommenderMetrics} current - The current metrics values.\n * @param {Metric} metric - The specific metric to calculate trend for.\n * @param {RecommenderMetricsHistory[]} history - Array of historical metrics data.\n * @returns {{ trend: number; description: string }} - Object containing trend value and description.\n */\nfunction calculateMetricTrend<Metric extends RecommenderNumericMetrics>(\n\tcurrent: RecommenderMetrics,\n\tmetric: Metric,\n\thistory: RecommenderMetricsHistory[],\n): { trend: number; description: string } {\n\tif (history.length === 0)\n\t\treturn { trend: 0, description: \"No historical data\" };\n\n\tconst sortedHistory = history\n\t\t.slice()\n\t\t.sort(\n\t\t\t(a, b) =>\n\t\t\t\tnew Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),\n\t\t);\n\n\tconst previousValue = sortedHistory[0].metrics[metric];\n\tconst trend = ((current[metric] - previousValue) / previousValue) * 100;\n\n\tlet description = \"stable\";\n\tif (trend > 5) description = \"improving\";\n\tif (trend < -5) description = \"declining\";\n\n\treturn { trend, description };\n}\n\n/**\n * Calculate the percentage trend between the current value and the first value in the historical values array.\n *\n * @param {number} current - The current value.\n * @param {number[]} historicalValues - An array of historical values.\n * @returns {number} The calculated trend percentage.\n */\nfunction calculateTrend(current: number, historicalValues: number[]): number {\n\tif (historicalValues.length === 0) return 0;\n\tconst previousValue = historicalValues[0];\n\treturn ((current - previousValue) / previousValue) * 100;\n}\n\n/**\n * Formats the trend arrow based on the trend value.\n * An arrow pointing upwards (\"↑\") is returned if the trend is greater than 5.\n * An arrow pointing downwards (\"↓\") is returned if the trend is less than -5.\n * A horizontal arrow (\"→\") is returned if the trend is between -5 and 5 (inclusive).\n *\n * @param trend The value representing the trend\n * @returns The formatted arrow representing the trend direction\n */\nfunction formatTrendArrow(trend: number): string {\n\tif (trend > 5) return \"↑\";\n\tif (trend < -5) return \"↓\";\n\treturn \"→\";\n}\n\n/**\n * Represents a time period with a label and number of days.\n * @typedef {Object} TimePeriod\n * @property {string} label - The label for the time period.\n * @property {number} days - The number of days in the time period.\n */\ntype TimePeriod = {\n\tlabel: string;\n\tdays: number;\n};\n\n/**\n * Calculates and returns trends for a given history of recommended metrics.\n * If a specific period is provided, trends are calculated for that period.\n * If no period is provided, monthly trends are calculated.\n *\n * @param {RecommenderMetricsHistory[]} history - The history of recommended metrics.\n * @param {TimePeriod} period - The time period for which trends should be calculated. If not provided, monthly trends are calculated.\n * @returns {Array<{\n * \tperiod: string;\n * \tavgPerformance: number;\n * \tsuccessRate: number;\n * \trecommendations: number;\n * }>} An array of objects containing period, average performance, success rate, and total recommendations.\n */\nfunction calculatePeriodTrends(\n\thistory: RecommenderMetricsHistory[],\n\tperiod: TimePeriod | null = null,\n): Array<{\n\tperiod: string;\n\tavgPerformance: number;\n\tsuccessRate: number;\n\trecommendations: number;\n}> {\n\t// For monthly grouping\n\tif (!period) {\n\t\tconst monthlyData = history.reduce(\n\t\t\t(acc, record) => {\n\t\t\t\tconst month = new Date(record.timestamp).toISOString().slice(0, 7);\n\n\t\t\t\tconst currentData = acc.get(month) ?? {\n\t\t\t\t\tperformances: [],\n\t\t\t\t\tsuccesses: 0,\n\t\t\t\t\ttotal: 0,\n\t\t\t\t};\n\n\t\t\t\tacc.set(month, {\n\t\t\t\t\tperformances: [\n\t\t\t\t\t\t...currentData.performances,\n\t\t\t\t\t\trecord.metrics.avgTokenPerformance,\n\t\t\t\t\t],\n\t\t\t\t\tsuccesses: currentData.successes + record.metrics.successfulRecs,\n\t\t\t\t\ttotal: currentData.total + record.metrics.totalRecommendations,\n\t\t\t\t});\n\n\t\t\t\treturn acc;\n\t\t\t},\n\t\t\tnew Map<\n\t\t\t\tstring,\n\t\t\t\t{\n\t\t\t\t\tperformances: number[];\n\t\t\t\t\tsuccesses: number;\n\t\t\t\t\ttotal: number;\n\t\t\t\t}\n\t\t\t>(),\n\t\t);\n\n\t\treturn Array.from(monthlyData.entries())\n\t\t\t.map(([month, data]) => ({\n\t\t\t\tperiod: month,\n\t\t\t\tavgPerformance:\n\t\t\t\t\tdata.performances.reduce((a, b) => a + b, 0) /\n\t\t\t\t\tdata.performances.length,\n\t\t\t\tsuccessRate: data.successes / data.total,\n\t\t\t\trecommendations: data.total,\n\t\t\t}))\n\t\t\t.sort((a, b) => b.period.localeCompare(a.period));\n\t}\n\n\t// For daily and weekly periods\n\tconst cutoffDate = new Date();\n\tcutoffDate.setDate(cutoffDate.getDate() - period.days);\n\n\tconst periodData = history.filter(\n\t\t(record) => new Date(record.timestamp) >= cutoffDate,\n\t);\n\n\tif (periodData.length === 0) {\n\t\treturn [\n\t\t\t{\n\t\t\t\tperiod: period.label,\n\t\t\t\tavgPerformance: 0,\n\t\t\t\tsuccessRate: 0,\n\t\t\t\trecommendations: 0,\n\t\t\t},\n\t\t];\n\t}\n\n\tconst performances = periodData.map(\n\t\t(record) => record.metrics.avgTokenPerformance,\n\t);\n\tconst totalRecommendations = periodData.reduce(\n\t\t(sum, record) => sum + record.metrics.totalRecommendations,\n\t\t0,\n\t);\n\tconst successfulRecs = periodData.reduce(\n\t\t(sum, record) => sum + record.metrics.successfulRecs,\n\t\t0,\n\t);\n\n\treturn [\n\t\t{\n\t\t\tperiod: period.label,\n\t\t\tavgPerformance:\n\t\t\t\tperformances.reduce((a, b) => a + b, 0) / performances.length,\n\t\t\tsuccessRate:\n\t\t\t\ttotalRecommendations > 0 ? successfulRecs / totalRecommendations : 0,\n\t\t\trecommendations: totalRecommendations,\n\t\t},\n\t];\n}\n\n/**\n * Formats an array of trends into a string representation.\n *\n * @param {Array<{ period: string; avgPerformance: number; successRate: number; recommendations: number; }>} trends The array of trends to format.\n * @returns {string} The formatted trends as a string with each trend separated by two new lines.\n */\nfunction formatTrends(\n\ttrends: Array<{\n\t\tperiod: string;\n\t\tavgPerformance: number;\n\t\tsuccessRate: number;\n\t\trecommendations: number;\n\t}>,\n): string {\n\treturn trends\n\t\t.map((trend) =>\n\t\t\t`\n${trend.period}:\n- Performance: ${formatPercent(trend.avgPerformance)}\n- Success Rate: ${formatPercentMetric(trend.successRate)}\n- Recommendations: ${trend.recommendations}`.trim(),\n\t\t)\n\t\t.join(\"\\n\\n\");\n}\n\n/**\n * Formats the recommender profile for a given entity based on the provided metrics and history.\n * @param {Entity} entity - The entity for which the profile is being formatted.\n * @param {RecommenderMetrics} metrics - The metrics related to the recommendations for the entity.\n * @param {RecommenderMetricsHistory[]} history - The history of metrics for the entity.\n * @returns {string} The formatted recommender profile string.\n */\nexport function formatRecommenderProfile(\n\tentity: Entity,\n\tmetrics: RecommenderMetrics,\n\thistory: RecommenderMetricsHistory[],\n): string {\n\tconst successRate = metrics.successfulRecs / metrics.totalRecommendations;\n\tconst trustTrend = calculateMetricTrend(metrics, \"trustScore\", history);\n\tconst performanceTrend = calculateMetricTrend(\n\t\tmetrics,\n\t\t\"avgTokenPerformance\",\n\t\thistory,\n\t);\n\n\treturn `\nEntity Profile: ${entity.metadata?.username || \"Unknown\"}\nPlatform: ${entity.metadata?.platform || \"Unknown\"}\nID: ${entity.id}\n\nPerformance Metrics:\n- Trust Score: ${formatScore(metrics.trustScore)} (${formatPercent(trustTrend.trend)} ${trustTrend.description})\n- Success Rate: ${formatPercentMetric(successRate)}\n- Recommendations: ${metrics.totalRecommendations} total, ${metrics.successfulRecs} successful\n- Avg Token Performance: ${formatPercent(metrics.avgTokenPerformance)} (${formatPercent(performanceTrend.trend)} ${performanceTrend.description})\n\nRisk Assessment:\n- Consistency Score: ${formatScore(metrics.consistencyScore)}\n\nActivity:\n- Last Active: ${formatDate(metrics.lastUpdated)}\n `.trim();\n}\n\n/**\n * Formats a recommender report for an entity with provided metrics and history.\n * @param {Entity} entity - The entity for which the report is being generated.\n * @param {RecommenderMetrics} metrics - The metrics for the entity's recommendations.\n * @param {RecommenderMetricsHistory[]} history - The historical metrics for the entity's recommendations.\n * @returns {string} The formatted recommender report.\n */\nexport function formatRecommenderReport(\n\tentity: Entity,\n\tmetrics: RecommenderMetrics,\n\thistory: RecommenderMetricsHistory[],\n): string {\n\tconst sortedHistory = [...history].sort(\n\t\t(a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),\n\t);\n\n\t// Calculate performance trends for different time periods\n\tconst dailyTrends = calculatePeriodTrends(sortedHistory, {\n\t\tlabel: \"24 Hours\",\n\t\tdays: 1,\n\t});\n\tconst weeklyTrends = calculatePeriodTrends(sortedHistory, {\n\t\tlabel: \"7 Days\",\n\t\tdays: 7,\n\t});\n\tconst monthlyTrends = calculatePeriodTrends(sortedHistory);\n\n\t// Calculate success trend\n\tconst successTrend = calculateTrend(\n\t\tmetrics.successfulRecs / metrics.totalRecommendations,\n\t\tsortedHistory.map(\n\t\t\t(h) => h.metrics.successfulRecs / h.metrics.totalRecommendations,\n\t\t),\n\t);\n\n\t// Calculate performance trend\n\tconst performanceTrend = calculateTrend(\n\t\tmetrics.avgTokenPerformance,\n\t\tsortedHistory.map((h) => h.metrics.avgTokenPerformance),\n\t);\n\n\treturn `\nUsername: ${entity.metadata?.username || \"Unknown\"}\nPlatform: ${entity.metadata?.platform || \"Unknown\"}\nID: ${entity.id}\n\n=== CURRENT METRICS ===\nTrust Score: ${formatScore(metrics.trustScore)}\nSuccess Rate: ${formatPercentMetric(metrics.successfulRecs / metrics.totalRecommendations)} (${formatTrendArrow(successTrend)})\nTotal Recommendations: ${metrics.totalRecommendations}\nAverage Token Performance: ${formatPercent(metrics.avgTokenPerformance)} (${formatTrendArrow(performanceTrend)})\n\nRisk Analysis:\n- Consistency: ${formatScore(metrics.consistencyScore)}\n\nActivity Status:\n- Last Active: ${formatDate(metrics.lastUpdated)}\n\n=== PERFORMANCE TRENDS ===\n${formatTrends(dailyTrends)}\n\n${formatTrends(weeklyTrends)}\n\nMonthly Average Performance:\n${formatTrends(monthlyTrends)}`.trim();\n}\n\n/**\n * Formats the top recommenders overview based on the provided data.\n *\n * @param {Entity[]} recommenders - The list of recommenders to be formatted\n * @param {Map<string, RecommenderMetrics>} metrics - The map of recommender metrics\n * @param {Map<string, RecommenderMetricsHistory[]>} history - The map of historical metrics data\n * @returns {string} The formatted top recommenders overview\n */\nexport function formatTopRecommendersOverview(\n\trecommenders: Entity[],\n\tmetrics: Map<string, RecommenderMetrics>,\n\thistory: Map<string, RecommenderMetricsHistory[]>,\n): string {\n\tconst sortedRecommenders = [...recommenders].sort((a, b) => {\n\t\tif (!a.id || !b.id) return 0;\n\t\tconst metricsA = metrics.get(a.id);\n\t\tconst metricsB = metrics.get(b.id);\n\t\tif (!metricsA || !metricsB) return 0;\n\t\treturn metricsB.trustScore - metricsA.trustScore;\n\t});\n\n\treturn `\n<top_recommenders>\n${sortedRecommenders\n\t.map((entity) => {\n\t\tif (!entity.id) return null;\n\t\tconst metric = metrics.get(entity.id);\n\t\tif (!metric) return null;\n\t\tconst historicalData = history.get(entity.id) || [];\n\t\tconst trustTrend = calculateMetricTrend(\n\t\t\tmetric,\n\t\t\t\"trustScore\",\n\t\t\thistoricalData,\n\t\t);\n\n\t\tconst performanceTrend = calculateMetricTrend(\n\t\t\tmetric,\n\t\t\t\"avgTokenPerformance\",\n\t\t\thistoricalData,\n\t\t);\n\n\t\treturn `\n${entity.metadata?.username || \"Unknown\"} (${entity.metadata?.platform || \"Unknown\"})\nTrust Score: ${formatScore(metric.trustScore)} (${formatPercent(trustTrend.trend)} ${trustTrend.description})\nPerformance Score: ${formatScore(metric.avgTokenPerformance)} (${formatPercent(performanceTrend.trend)} ${performanceTrend.description})\nSuccess Rate: ${formatPercentMetric(metric.successfulRecs / metric.totalRecommendations)}\nLast Active: ${formatDate(metric.lastUpdated)}\n `.trim();\n\t})\n\t.filter((report) => report !== null)\n\t.join(\"\\n\\n\")}\n</top_recommenders>`.trim();\n}\n"],"mappings":"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","names":["transactions"]}
@@ -0,0 +1,3 @@
1
+ import type { Route } from "@elizaos/core";
2
+ export declare const communityInvestorRoutes: Route[];
3
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEX,KAAK,EAGL,MAAM,eAAe,CAAC;AA2EvB,eAAO,MAAM,uBAAuB,EAAE,KAAK,EAM1C,CAAC"}
package/dist/routes.js ADDED
@@ -0,0 +1,59 @@
1
+ import { logger } from "@elizaos/core";
2
+ import { ServiceType } from "./types.js";
3
+ function errorMessage(error) {
4
+ return error instanceof Error ? error.message : String(error);
5
+ }
6
+ function nodeResponse(res) {
7
+ return res;
8
+ }
9
+ function sendSuccess(res, data, status = 200) {
10
+ const nodeRes = nodeResponse(res);
11
+ nodeRes.writeHead(status, { "Content-Type": "application/json" });
12
+ nodeRes.end(JSON.stringify({ success: true, data }));
13
+ }
14
+ function sendError(res, status, code, message, details) {
15
+ const nodeRes = nodeResponse(res);
16
+ nodeRes.writeHead(status, { "Content-Type": "application/json" });
17
+ nodeRes.end(
18
+ JSON.stringify({ success: false, error: { code, message, details } })
19
+ );
20
+ }
21
+ async function getLeaderboardDataHandler(_req, res, runtime) {
22
+ const service = runtime.getService(
23
+ ServiceType.COMMUNITY_INVESTOR
24
+ );
25
+ if (!service) {
26
+ return sendError(
27
+ res,
28
+ 500,
29
+ "SERVICE_NOT_FOUND",
30
+ "CommunityInvestorService not found"
31
+ );
32
+ }
33
+ try {
34
+ const leaderboardData = await service.getLeaderboardData(runtime);
35
+ sendSuccess(res, leaderboardData);
36
+ } catch (error) {
37
+ logger.error(
38
+ `[API /leaderboard] Error fetching leaderboard data: ${errorMessage(error)}`
39
+ );
40
+ sendError(
41
+ res,
42
+ 500,
43
+ "LEADERBOARD_ERROR",
44
+ "Failed to fetch leaderboard data",
45
+ errorMessage(error)
46
+ );
47
+ }
48
+ }
49
+ const communityInvestorRoutes = [
50
+ {
51
+ type: "GET",
52
+ path: "/api/social-alpha/leaderboard",
53
+ handler: getLeaderboardDataHandler
54
+ }
55
+ ];
56
+ export {
57
+ communityInvestorRoutes
58
+ };
59
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/routes.ts"],"sourcesContent":["import type {\n\tIAgentRuntime,\n\tRoute,\n\tRouteRequest,\n\tRouteResponse,\n} from \"@elizaos/core\";\nimport { logger } from \"@elizaos/core\";\nimport type { CommunityInvestorService } from \"./service.js\";\nimport { ServiceType } from \"./types.js\";\n\ntype JsonResponseBody = Record<string, unknown> | unknown[];\ntype NodeStyleRouteResponse = RouteResponse & {\n\twriteHead(status: number, headers: Record<string, string>): void;\n\tend(chunk?: string): RouteResponse;\n};\n\nfunction errorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction nodeResponse(res: RouteResponse): NodeStyleRouteResponse {\n\treturn res as NodeStyleRouteResponse;\n}\n\n// Helper to send success response\nfunction sendSuccess(res: RouteResponse, data: JsonResponseBody, status = 200) {\n\tconst nodeRes = nodeResponse(res);\n\tnodeRes.writeHead(status, { \"Content-Type\": \"application/json\" });\n\tnodeRes.end(JSON.stringify({ success: true, data }));\n}\n\n// Helper to send error response\nfunction sendError(\n\tres: RouteResponse,\n\tstatus: number,\n\tcode: string,\n\tmessage: string,\n\tdetails?: string,\n) {\n\tconst nodeRes = nodeResponse(res);\n\tnodeRes.writeHead(status, { \"Content-Type\": \"application/json\" });\n\tnodeRes.end(\n\t\tJSON.stringify({ success: false, error: { code, message, details } }),\n\t);\n}\n\nasync function getLeaderboardDataHandler(\n\t_req: RouteRequest,\n\tres: RouteResponse,\n\truntime: IAgentRuntime,\n) {\n\tconst service = runtime.getService<CommunityInvestorService>(\n\t\tServiceType.COMMUNITY_INVESTOR,\n\t);\n\tif (!service) {\n\t\treturn sendError(\n\t\t\tres,\n\t\t\t500,\n\t\t\t\"SERVICE_NOT_FOUND\",\n\t\t\t\"CommunityInvestorService not found\",\n\t\t);\n\t}\n\ttry {\n\t\tconst leaderboardData = await service.getLeaderboardData(runtime);\n\t\t// Return the leaderboard data directly as an array, not wrapped in an object\n\t\tsendSuccess(res, leaderboardData);\n\t} catch (error: unknown) {\n\t\tlogger.error(\n\t\t\t`[API /leaderboard] Error fetching leaderboard data: ${errorMessage(error)}`,\n\t\t);\n\t\tsendError(\n\t\t\tres,\n\t\t\t500,\n\t\t\t\"LEADERBOARD_ERROR\",\n\t\t\t\"Failed to fetch leaderboard data\",\n\t\t\terrorMessage(error),\n\t\t);\n\t}\n}\n\nexport const communityInvestorRoutes: Route[] = [\n\t{\n\t\ttype: \"GET\",\n\t\tpath: \"/api/social-alpha/leaderboard\",\n\t\thandler: getLeaderboardDataHandler,\n\t},\n];\n"],"mappings":"AAMA,SAAS,cAAc;AAEvB,SAAS,mBAAmB;AAQ5B,SAAS,aAAa,OAAwB;AAC7C,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC7D;AAEA,SAAS,aAAa,KAA4C;AACjE,SAAO;AACR;AAGA,SAAS,YAAY,KAAoB,MAAwB,SAAS,KAAK;AAC9E,QAAM,UAAU,aAAa,GAAG;AAChC,UAAQ,UAAU,QAAQ,EAAE,gBAAgB,mBAAmB,CAAC;AAChE,UAAQ,IAAI,KAAK,UAAU,EAAE,SAAS,MAAM,KAAK,CAAC,CAAC;AACpD;AAGA,SAAS,UACR,KACA,QACA,MACA,SACA,SACC;AACD,QAAM,UAAU,aAAa,GAAG;AAChC,UAAQ,UAAU,QAAQ,EAAE,gBAAgB,mBAAmB,CAAC;AAChE,UAAQ;AAAA,IACP,KAAK,UAAU,EAAE,SAAS,OAAO,OAAO,EAAE,MAAM,SAAS,QAAQ,EAAE,CAAC;AAAA,EACrE;AACD;AAEA,eAAe,0BACd,MACA,KACA,SACC;AACD,QAAM,UAAU,QAAQ;AAAA,IACvB,YAAY;AAAA,EACb;AACA,MAAI,CAAC,SAAS;AACb,WAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AACA,MAAI;AACH,UAAM,kBAAkB,MAAM,QAAQ,mBAAmB,OAAO;AAEhE,gBAAY,KAAK,eAAe;AAAA,EACjC,SAAS,OAAgB;AACxB,WAAO;AAAA,MACN,uDAAuD,aAAa,KAAK,CAAC;AAAA,IAC3E;AACA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,KAAK;AAAA,IACnB;AAAA,EACD;AACD;AAEO,MAAM,0BAAmC;AAAA,EAC/C;AAAA,IACC,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,EACV;AACD;","names":[]}