@elizaos/plugin-wallet 2.0.0-beta.1

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 (200) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +64 -0
  3. package/auto-enable.ts +76 -0
  4. package/dist/LpManagementService-BWrQ5-cO.mjs +353 -0
  5. package/dist/MockLpService-D_Apn4Fd.mjs +99 -0
  6. package/dist/aerodrome-CfnESC32.mjs +890 -0
  7. package/dist/chunk-hT5z_Zn9.mjs +35 -0
  8. package/dist/index.d.mts +34727 -0
  9. package/dist/index.mjs +21590 -0
  10. package/dist/lib/server-wallet-trade.d.mts +34 -0
  11. package/dist/lib/server-wallet-trade.mjs +306 -0
  12. package/dist/meteora-BPX39hZo.mjs +22640 -0
  13. package/dist/orca-Bybp1HXO.mjs +249 -0
  14. package/dist/pancakeswp-CkEXlXti.mjs +604 -0
  15. package/dist/plugin-ZO_MTyd0.mjs +529 -0
  16. package/dist/raydium-rfaM9yEf.mjs +539 -0
  17. package/dist/sdk/index.d.mts +32492 -0
  18. package/dist/sdk/index.mjs +6415 -0
  19. package/dist/types-D5252NZk.mjs +487 -0
  20. package/dist/uniswap-CReXgXVN.mjs +573 -0
  21. package/dist/wallet-action.d.mts +6 -0
  22. package/dist/wallet-action.mjs +820 -0
  23. package/package.json +152 -0
  24. package/src/actions/failure-codes.ts +79 -0
  25. package/src/actions/index.ts +1 -0
  26. package/src/analytics/birdeye/actions/wallet-search-address.ts +9 -0
  27. package/src/analytics/birdeye/birdeye-task.ts +175 -0
  28. package/src/analytics/birdeye/birdeye.ts +813 -0
  29. package/src/analytics/birdeye/constants.ts +74 -0
  30. package/src/analytics/birdeye/providers/agent-portfolio-provider.ts +18 -0
  31. package/src/analytics/birdeye/providers/market.ts +227 -0
  32. package/src/analytics/birdeye/providers/portfolio-factory.test.ts +138 -0
  33. package/src/analytics/birdeye/providers/portfolio-factory.ts +252 -0
  34. package/src/analytics/birdeye/providers/trending.ts +365 -0
  35. package/src/analytics/birdeye/providers/wallet.ts +14 -0
  36. package/src/analytics/birdeye/search-category.test.ts +207 -0
  37. package/src/analytics/birdeye/search-category.ts +506 -0
  38. package/src/analytics/birdeye/service.ts +992 -0
  39. package/src/analytics/birdeye/tasks/birdeye.ts +232 -0
  40. package/src/analytics/birdeye/types/api/common.ts +305 -0
  41. package/src/analytics/birdeye/types/api/defi.ts +220 -0
  42. package/src/analytics/birdeye/types/api/pair.ts +200 -0
  43. package/src/analytics/birdeye/types/api/search.ts +86 -0
  44. package/src/analytics/birdeye/types/api/token.ts +635 -0
  45. package/src/analytics/birdeye/types/api/trader.ts +76 -0
  46. package/src/analytics/birdeye/types/api/wallet.ts +181 -0
  47. package/src/analytics/birdeye/types/shared.ts +106 -0
  48. package/src/analytics/birdeye/utils.ts +700 -0
  49. package/src/analytics/dexscreener/errors.ts +28 -0
  50. package/src/analytics/dexscreener/index.ts +3 -0
  51. package/src/analytics/dexscreener/search-category.test.ts +49 -0
  52. package/src/analytics/dexscreener/search-category.ts +42 -0
  53. package/src/analytics/dexscreener/service.ts +595 -0
  54. package/src/analytics/dexscreener/types.ts +128 -0
  55. package/src/analytics/lpinfo/index.d.ts +7 -0
  56. package/src/analytics/lpinfo/index.ts +52 -0
  57. package/src/analytics/lpinfo/kamino/README.md +102 -0
  58. package/src/analytics/lpinfo/kamino/index.ts +24 -0
  59. package/src/analytics/lpinfo/kamino/providers/kaminoLiquidityProvider.ts +422 -0
  60. package/src/analytics/lpinfo/kamino/providers/kaminoPoolProvider.ts +365 -0
  61. package/src/analytics/lpinfo/kamino/providers/kaminoProvider.ts +496 -0
  62. package/src/analytics/lpinfo/kamino/services/kaminoLiquidityService.ts +1123 -0
  63. package/src/analytics/lpinfo/kamino/services/kaminoService.ts +758 -0
  64. package/src/analytics/lpinfo/steer/README.md +169 -0
  65. package/src/analytics/lpinfo/steer/index.ts +23 -0
  66. package/src/analytics/lpinfo/steer/providers/steerLiquidityProvider.ts +544 -0
  67. package/src/analytics/lpinfo/steer/services/steerLiquidityService.ts +1690 -0
  68. package/src/analytics/lpinfo/steer/steer-display-types.ts +99 -0
  69. package/src/analytics/news/index.ts +52 -0
  70. package/src/analytics/news/interfaces/types.ts +222 -0
  71. package/src/analytics/news/providers/defiNewsProvider.ts +734 -0
  72. package/src/analytics/news/services/newsDataService.ts +332 -0
  73. package/src/analytics/news/utils/formatters.ts +151 -0
  74. package/src/analytics/token-info/action.ts +240 -0
  75. package/src/analytics/token-info/index.ts +3 -0
  76. package/src/analytics/token-info/params.ts +215 -0
  77. package/src/analytics/token-info/providers.ts +681 -0
  78. package/src/analytics/token-info/service.ts +168 -0
  79. package/src/analytics/token-info/types.ts +74 -0
  80. package/src/audit/audit-log.ts +45 -0
  81. package/src/browser-shim/build-shim.ts +123 -0
  82. package/src/browser-shim/index.ts +5 -0
  83. package/src/browser-shim/shim.template.js +563 -0
  84. package/src/chains/evm/.github/workflows/npm-deploy.yml +112 -0
  85. package/src/chains/evm/LICENSE +21 -0
  86. package/src/chains/evm/README.md +106 -0
  87. package/src/chains/evm/actions/helpers.ts +147 -0
  88. package/src/chains/evm/actions/swap.ts +839 -0
  89. package/src/chains/evm/actions/transfer.ts +254 -0
  90. package/src/chains/evm/biome.json +61 -0
  91. package/src/chains/evm/bridge-router.ts +660 -0
  92. package/src/chains/evm/build.ts +89 -0
  93. package/src/chains/evm/chain-handler.ts +416 -0
  94. package/src/chains/evm/constants.ts +23 -0
  95. package/src/chains/evm/contracts/artifacts/OZGovernor.json +1707 -0
  96. package/src/chains/evm/contracts/artifacts/TimelockController.json +1007 -0
  97. package/src/chains/evm/contracts/artifacts/VoteToken.json +895 -0
  98. package/src/chains/evm/dex/aerodrome/index.ts +34 -0
  99. package/src/chains/evm/dex/aerodrome/services/AerodromeLpService.ts +558 -0
  100. package/src/chains/evm/dex/aerodrome/types.ts +318 -0
  101. package/src/chains/evm/dex/pancakeswp/index.ts +35 -0
  102. package/src/chains/evm/dex/pancakeswp/services/PancakeSwapV3LpService.ts +743 -0
  103. package/src/chains/evm/dex/pancakeswp/types.ts +65 -0
  104. package/src/chains/evm/dex/uniswap/index.ts +35 -0
  105. package/src/chains/evm/dex/uniswap/services/UniswapV3LpService.ts +759 -0
  106. package/src/chains/evm/dex/uniswap/types.ts +390 -0
  107. package/src/chains/evm/generated/specs/spec-helpers.ts +73 -0
  108. package/src/chains/evm/generated/specs/specs.ts +151 -0
  109. package/src/chains/evm/gov-router.ts +250 -0
  110. package/src/chains/evm/index.browser.ts +16 -0
  111. package/src/chains/evm/index.ts +31 -0
  112. package/src/chains/evm/prompts.ts +193 -0
  113. package/src/chains/evm/providers/get-balance.ts +123 -0
  114. package/src/chains/evm/providers/wallet.ts +715 -0
  115. package/src/chains/evm/routes/sign.ts +333 -0
  116. package/src/chains/evm/rpc-providers.ts +410 -0
  117. package/src/chains/evm/service.ts +140 -0
  118. package/src/chains/evm/templates/index.ts +10 -0
  119. package/src/chains/evm/types/index.ts +432 -0
  120. package/src/chains/evm/vitest.config.ts +18 -0
  121. package/src/chains/registry.ts +668 -0
  122. package/src/chains/solana/README.md +367 -0
  123. package/src/chains/wallet-action.ts +533 -0
  124. package/src/chains/wallet-router.test.ts +296 -0
  125. package/src/contracts.ts +65 -0
  126. package/src/core-augmentation.ts +10 -0
  127. package/src/index.ts +71 -0
  128. package/src/lib/server-wallet-trade.ts +192 -0
  129. package/src/lib/wallet-export-guard.ts +330 -0
  130. package/src/lp/actions/liquidity.ts +827 -0
  131. package/src/lp/e2e/real-token-tests.ts +428 -0
  132. package/src/lp/e2e/scenarios.ts +470 -0
  133. package/src/lp/e2e/test-utils.ts +145 -0
  134. package/src/lp/lp-manager-entry.ts +303 -0
  135. package/src/lp/services/ConcentratedLiquidityService.ts +120 -0
  136. package/src/lp/services/DexInteractionService.ts +226 -0
  137. package/src/lp/services/LpManagementService.test.ts +148 -0
  138. package/src/lp/services/LpManagementService.ts +632 -0
  139. package/src/lp/services/UserLpProfileService.ts +163 -0
  140. package/src/lp/services/VaultService.ts +153 -0
  141. package/src/lp/services/YieldOptimizationService.ts +344 -0
  142. package/src/lp/services/__tests__/MockLpService.ts +146 -0
  143. package/src/lp/tasks/LpAutoRebalanceTask.ts +117 -0
  144. package/src/lp/tasks/__tests__/LpAutoRebalanceTask.test.ts +370 -0
  145. package/src/lp/types.ts +582 -0
  146. package/src/lp/utils/solanaClient.ts +143 -0
  147. package/src/plugin.ts +125 -0
  148. package/src/policy/policy.ts +19 -0
  149. package/src/providers/canonical-provider.ts +27 -0
  150. package/src/providers/unified-wallet-provider.ts +79 -0
  151. package/src/register-routes.ts +11 -0
  152. package/src/routes/plugin.ts +47 -0
  153. package/src/routes/wallet-market-overview-route.ts +869 -0
  154. package/src/sdk/abi.ts +258 -0
  155. package/src/sdk/bridge/abis.ts +126 -0
  156. package/src/sdk/bridge/client.ts +518 -0
  157. package/src/sdk/bridge/index.ts +56 -0
  158. package/src/sdk/bridge/solana.ts +604 -0
  159. package/src/sdk/bridge/types.ts +202 -0
  160. package/src/sdk/convenience.ts +347 -0
  161. package/src/sdk/escrow/MutualStakeEscrow.ts +480 -0
  162. package/src/sdk/escrow/types.ts +64 -0
  163. package/src/sdk/escrow/verifiers.ts +73 -0
  164. package/src/sdk/identity/erc8004.ts +692 -0
  165. package/src/sdk/identity/reputation.ts +449 -0
  166. package/src/sdk/identity/uaid.ts +497 -0
  167. package/src/sdk/identity/validation.ts +372 -0
  168. package/src/sdk/index.ts +763 -0
  169. package/src/sdk/policy/SpendingPolicy.ts +260 -0
  170. package/src/sdk/policy/UptoBillingPolicy.ts +320 -0
  171. package/src/sdk/router/PaymentRouter.ts +215 -0
  172. package/src/sdk/router/index.ts +8 -0
  173. package/src/sdk/swap/SwapModule.ts +310 -0
  174. package/src/sdk/swap/abi.ts +117 -0
  175. package/src/sdk/swap/index.ts +34 -0
  176. package/src/sdk/swap/types.ts +135 -0
  177. package/src/sdk/tokens/decimals.ts +140 -0
  178. package/src/sdk/tokens/registry.ts +911 -0
  179. package/src/sdk/tokens/solana.ts +419 -0
  180. package/src/sdk/tokens/transfers.ts +327 -0
  181. package/src/sdk/types.ts +158 -0
  182. package/src/sdk/wallet-core.ts +115 -0
  183. package/src/sdk/x402/budget.ts +168 -0
  184. package/src/sdk/x402/chains/abstract/index.ts +280 -0
  185. package/src/sdk/x402/client.ts +320 -0
  186. package/src/sdk/x402/index.ts +46 -0
  187. package/src/sdk/x402/middleware.ts +92 -0
  188. package/src/sdk/x402/multi-asset.ts +144 -0
  189. package/src/sdk/x402/types.ts +156 -0
  190. package/src/services/wallet-backend-service.ts +328 -0
  191. package/src/types/wallet-router.ts +227 -0
  192. package/src/utils/intent-trajectory.ts +106 -0
  193. package/src/wallet/backend.ts +62 -0
  194. package/src/wallet/errors.ts +49 -0
  195. package/src/wallet/index.ts +27 -0
  196. package/src/wallet/local-eoa-backend.ts +201 -0
  197. package/src/wallet/pending.ts +60 -0
  198. package/src/wallet/select-backend.ts +47 -0
  199. package/src/wallet/steward-backend.ts +161 -0
  200. package/src/wallet-action.ts +1 -0
@@ -0,0 +1,332 @@
1
+ // @ts-nocheck — legacy code from absorbed plugins (lp-manager, lpinfo, dexscreener, defi-news, birdeye); strict types pending cleanup
2
+ import type { IAgentRuntime } from "@elizaos/core";
3
+ import { Service } from "@elizaos/core";
4
+ import type { RealWorldNewsArticle } from "../interfaces/types";
5
+
6
+ /**
7
+ * RSS Feed Item Interface
8
+ */
9
+ interface RSSItem {
10
+ title?: string;
11
+ link?: string;
12
+ description?: string;
13
+ pubDate?: string;
14
+ category?: string[];
15
+ guid?: string;
16
+ content?: string;
17
+ creator?: string;
18
+ }
19
+
20
+ /**
21
+ * Brave New Coin RSS Service for Real-World Crypto Events
22
+ *
23
+ * This service fetches real-world news and events related to cryptocurrency
24
+ * from Brave New Coin RSS feed.
25
+ */
26
+ export class NewsDataService extends Service {
27
+ static serviceType = "NEWS_DATA_SERVICE";
28
+ private rssUrl: string = "https://bravenewcoin.com/rss/insights";
29
+
30
+ get capabilityDescription(): string {
31
+ return "Provides real-world cryptocurrency news and events from Brave New Coin RSS feed";
32
+ }
33
+
34
+ constructor(runtime?: IAgentRuntime) {
35
+ super(runtime);
36
+ console.log(
37
+ "✅ [NewsDataService] Initialized with Brave New Coin RSS feed",
38
+ );
39
+ }
40
+
41
+ /**
42
+ * Start the NewsData service (static method for framework)
43
+ */
44
+ static async start(runtime: IAgentRuntime) {
45
+ const service = new NewsDataService(runtime);
46
+ return service;
47
+ }
48
+
49
+ /**
50
+ * Stop the NewsData service (static method for framework)
51
+ */
52
+ static async stop(runtime: IAgentRuntime) {
53
+ const service = runtime.getService(NewsDataService.serviceType);
54
+ if (!service) {
55
+ throw new Error(`${NewsDataService.serviceType} service not found`);
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Stop the service instance
61
+ */
62
+ async stop(): Promise<void> {
63
+ console.log("✅ [NewsDataService] Stopped");
64
+ }
65
+
66
+ /**
67
+ * Parse RSS XML to extract news items
68
+ */
69
+ private parseRSS(xmlText: string): RSSItem[] {
70
+ const items: RSSItem[] = [];
71
+
72
+ try {
73
+ // Extract all <item> blocks from the RSS feed
74
+ const itemRegex = /<item>([\s\S]*?)<\/item>/g;
75
+ const itemMatches = xmlText.matchAll(itemRegex);
76
+
77
+ for (const match of itemMatches) {
78
+ const itemXml = match[1];
79
+
80
+ // Extract individual fields
81
+ const title = this.decodeHtmlEntities(
82
+ this.extractTag(itemXml, "title") || "",
83
+ );
84
+ const link = this.extractTag(itemXml, "link");
85
+ const description = this.extractTag(itemXml, "description");
86
+ const pubDate = this.extractTag(itemXml, "pubDate");
87
+ const guid = this.extractTag(itemXml, "guid");
88
+ const creator =
89
+ this.extractTag(itemXml, "dc:creator") ||
90
+ this.extractTag(itemXml, "author");
91
+ const content = this.extractTag(itemXml, "content:encoded");
92
+
93
+ // Extract categories (handle CDATA)
94
+ const categoryRegex =
95
+ /<category>(?:<!\[CDATA\[)?(.*?)(?:\]\]>)?<\/category>/gs;
96
+ const categories: string[] = [];
97
+ for (;;) {
98
+ const categoryMatch = categoryRegex.exec(itemXml);
99
+ if (categoryMatch === null) break;
100
+ const cat = categoryMatch[1].trim();
101
+ if (cat) {
102
+ categories.push(cat);
103
+ }
104
+ }
105
+
106
+ items.push({
107
+ title,
108
+ link,
109
+ description,
110
+ pubDate,
111
+ category: categories.length > 0 ? categories : undefined,
112
+ guid,
113
+ creator,
114
+ content,
115
+ });
116
+ }
117
+ } catch (error) {
118
+ console.error("❌ [NewsDataService] Error parsing RSS:", error);
119
+ }
120
+
121
+ return items;
122
+ }
123
+
124
+ /**
125
+ * Extract content from XML tag
126
+ */
127
+ private extractTag(xml: string, tagName: string): string | undefined {
128
+ const regex = new RegExp(
129
+ `<${tagName}[^>]*><!\\[CDATA\\[(.*?)\\]\\]><\\/${tagName}>`,
130
+ "s",
131
+ );
132
+ const cdataMatch = xml.match(regex);
133
+ if (cdataMatch) {
134
+ return cdataMatch[1].trim();
135
+ }
136
+
137
+ const simpleRegex = new RegExp(
138
+ `<${tagName}[^>]*>(.*?)<\\/${tagName}>`,
139
+ "s",
140
+ );
141
+ const simpleMatch = xml.match(simpleRegex);
142
+ if (simpleMatch) {
143
+ return simpleMatch[1].trim();
144
+ }
145
+
146
+ return undefined;
147
+ }
148
+
149
+ /**
150
+ * Strip HTML tags from text
151
+ */
152
+ private stripHtml(html: string): string {
153
+ return html.replace(/<[^>]*>/g, "").trim();
154
+ }
155
+
156
+ /**
157
+ * Decode HTML entities (e.g., &#8217; to ')
158
+ */
159
+ private decodeHtmlEntities(text: string): string {
160
+ const entities: Record<string, string> = {
161
+ "&#8217;": "'",
162
+ "&#8216;": "'",
163
+ "&#8220;": '"',
164
+ "&#8221;": '"',
165
+ "&#8211;": "–",
166
+ "&#8212;": "—",
167
+ "&#038;": "&",
168
+ "&amp;": "&",
169
+ "&lt;": "<",
170
+ "&gt;": ">",
171
+ "&quot;": '"',
172
+ "&#39;": "'",
173
+ };
174
+
175
+ let decoded = text;
176
+ for (const [entity, char] of Object.entries(entities)) {
177
+ decoded = decoded.replace(new RegExp(entity, "g"), char);
178
+ }
179
+
180
+ // Handle numeric entities
181
+ decoded = decoded.replace(/&#(\d+);/g, (_match, dec) => {
182
+ return String.fromCharCode(dec);
183
+ });
184
+
185
+ return decoded;
186
+ }
187
+
188
+ /**
189
+ * Fetch latest crypto news from Brave New Coin RSS feed
190
+ */
191
+ async getLatestNews(options?: {
192
+ query?: string;
193
+ language?: string;
194
+ category?: string;
195
+ limit?: number;
196
+ }): Promise<RealWorldNewsArticle[]> {
197
+ try {
198
+ const limit = options?.limit || 10;
199
+ const query = options?.query?.toLowerCase();
200
+
201
+ console.log(
202
+ `🔍 [NewsDataService] Fetching news from Brave New Coin RSS feed`,
203
+ );
204
+
205
+ const response = await fetch(this.rssUrl, {
206
+ method: "GET",
207
+ headers: {
208
+ "User-Agent": "Mozilla/5.0 (compatible; SpartanBot/1.0)",
209
+ },
210
+ });
211
+
212
+ if (!response.ok) {
213
+ const errorText = await response.text();
214
+ console.error(
215
+ `❌ [NewsDataService] RSS fetch error (${response.status}): ${errorText}`,
216
+ );
217
+ throw new Error(
218
+ `RSS fetch error: ${response.status} ${response.statusText}`,
219
+ );
220
+ }
221
+
222
+ const xmlText = await response.text();
223
+ const rssItems = this.parseRSS(xmlText);
224
+
225
+ console.log(
226
+ `✅ [NewsDataService] Parsed ${rssItems.length} news articles from RSS`,
227
+ );
228
+
229
+ // Convert RSS items to RealWorldNewsArticle format
230
+ let articles: RealWorldNewsArticle[] = rssItems.map((item, index) => ({
231
+ article_id: item.guid || `bnc-${Date.now()}-${index}`,
232
+ title: item.title || "Untitled",
233
+ link: item.link || "",
234
+ description: item.description
235
+ ? this.decodeHtmlEntities(this.stripHtml(item.description))
236
+ : undefined,
237
+ pubDate: item.pubDate || new Date().toISOString(),
238
+ source_id: "bravenewcoin",
239
+ source_priority: 1,
240
+ source_url: "https://bravenewcoin.com",
241
+ language: "en",
242
+ category: item.category,
243
+ creator: item.creator ? [item.creator] : undefined,
244
+ keywords: undefined,
245
+ video_url: null,
246
+ content: item.content ? this.stripHtml(item.content) : undefined,
247
+ image_url: undefined,
248
+ source_icon: undefined,
249
+ country: undefined,
250
+ ai_tag: undefined,
251
+ sentiment: undefined,
252
+ sentiment_stats: undefined,
253
+ ai_region: undefined,
254
+ }));
255
+
256
+ // Filter by query if provided
257
+ if (query) {
258
+ articles = articles.filter((article) => {
259
+ const searchText =
260
+ `${article.title} ${article.description || ""} ${article.content || ""} ${article.category?.join(" ") || ""}`.toLowerCase();
261
+ return searchText.includes(query);
262
+ });
263
+ console.log(
264
+ `🔍 [NewsDataService] Filtered to ${articles.length} articles matching query: ${query}`,
265
+ );
266
+ }
267
+
268
+ // Limit results
269
+ articles = articles.slice(0, limit);
270
+
271
+ return articles;
272
+ } catch (error) {
273
+ if (error instanceof Error) {
274
+ console.error(
275
+ "❌ [NewsDataService] Error fetching news:",
276
+ error.message,
277
+ );
278
+ throw error;
279
+ } else {
280
+ console.error("❌ [NewsDataService] Unknown error:", error);
281
+ throw new Error("Failed to fetch news from Brave New Coin RSS");
282
+ }
283
+ }
284
+ }
285
+
286
+ /**
287
+ * Fetch news about a specific token
288
+ */
289
+ async getTokenNews(
290
+ tokenSymbol: string,
291
+ options?: {
292
+ language?: string;
293
+ limit?: number;
294
+ },
295
+ ): Promise<RealWorldNewsArticle[]> {
296
+ const query = tokenSymbol.toLowerCase();
297
+ return this.getLatestNews({
298
+ query,
299
+ language: options?.language,
300
+ limit: options?.limit,
301
+ });
302
+ }
303
+
304
+ /**
305
+ * Fetch DeFi-specific news
306
+ */
307
+ async getDefiNews(options?: {
308
+ language?: string;
309
+ limit?: number;
310
+ }): Promise<RealWorldNewsArticle[]> {
311
+ const query = "defi";
312
+ return this.getLatestNews({
313
+ query,
314
+ language: options?.language,
315
+ limit: options?.limit,
316
+ });
317
+ }
318
+
319
+ /**
320
+ * Fetch blockchain and crypto market news
321
+ */
322
+ async getCryptoMarketNews(options?: {
323
+ language?: string;
324
+ limit?: number;
325
+ }): Promise<RealWorldNewsArticle[]> {
326
+ // Return all crypto news from the feed
327
+ return this.getLatestNews({
328
+ language: options?.language,
329
+ limit: options?.limit,
330
+ });
331
+ }
332
+ }
@@ -0,0 +1,151 @@
1
+ // @ts-nocheck — legacy code from absorbed plugins (lp-manager, lpinfo, dexscreener, defi-news, birdeye); strict types pending cleanup
2
+ /**
3
+ * Utility functions for formatting DeFi news data
4
+ */
5
+
6
+ /**
7
+ * Format a number as currency (USD)
8
+ */
9
+ export function formatCurrency(value: number, decimals: number = 2): string {
10
+ if (value >= 1e12) {
11
+ return `$${(value / 1e12).toFixed(decimals)}T`;
12
+ } else if (value >= 1e9) {
13
+ return `$${(value / 1e9).toFixed(decimals)}B`;
14
+ } else if (value >= 1e6) {
15
+ return `$${(value / 1e6).toFixed(decimals)}M`;
16
+ } else if (value >= 1e3) {
17
+ return `$${(value / 1e3).toFixed(decimals)}K`;
18
+ } else {
19
+ return `$${value.toFixed(decimals)}`;
20
+ }
21
+ }
22
+
23
+ /**
24
+ * Format a percentage with appropriate emoji
25
+ */
26
+ export function formatPercentage(value: number, decimals: number = 2): string {
27
+ const emoji = value >= 0 ? "📈" : "📉";
28
+ const sign = value >= 0 ? "+" : "";
29
+ return `${emoji} ${sign}${value.toFixed(decimals)}%`;
30
+ }
31
+
32
+ /**
33
+ * Format a timestamp as a human-readable date
34
+ */
35
+ export function formatDate(timestamp: number | string): string {
36
+ const date = new Date(timestamp);
37
+ return date.toLocaleString();
38
+ }
39
+
40
+ /**
41
+ * Format a relative time (e.g., "2 hours ago")
42
+ */
43
+ export function formatRelativeTime(timestamp: number | string): string {
44
+ const now = Date.now();
45
+ const date = new Date(timestamp).getTime();
46
+ const diff = now - date;
47
+
48
+ const seconds = Math.floor(diff / 1000);
49
+ const minutes = Math.floor(seconds / 60);
50
+ const hours = Math.floor(minutes / 60);
51
+ const days = Math.floor(hours / 24);
52
+
53
+ if (days > 0) {
54
+ return `${days} day${days > 1 ? "s" : ""} ago`;
55
+ } else if (hours > 0) {
56
+ return `${hours} hour${hours > 1 ? "s" : ""} ago`;
57
+ } else if (minutes > 0) {
58
+ return `${minutes} minute${minutes > 1 ? "s" : ""} ago`;
59
+ } else {
60
+ return `${seconds} second${seconds > 1 ? "s" : ""} ago`;
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Truncate text to a maximum length
66
+ */
67
+ export function truncateText(text: string, maxLength: number = 200): string {
68
+ if (text.length <= maxLength) {
69
+ return text;
70
+ }
71
+ return `${text.substring(0, maxLength)}...`;
72
+ }
73
+
74
+ /**
75
+ * Get sentiment emoji
76
+ */
77
+ export function getSentimentEmoji(sentiment?: string): string {
78
+ if (!sentiment) return "😐";
79
+
80
+ switch (sentiment.toLowerCase()) {
81
+ case "positive":
82
+ return "😊";
83
+ case "negative":
84
+ return "😟";
85
+ case "neutral":
86
+ return "😐";
87
+ default:
88
+ return "😐";
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Format large numbers with commas
94
+ */
95
+ export function formatNumber(value: number, decimals: number = 0): string {
96
+ return value.toLocaleString("en-US", {
97
+ minimumFractionDigits: decimals,
98
+ maximumFractionDigits: decimals,
99
+ });
100
+ }
101
+
102
+ /**
103
+ * Extract token symbol from text
104
+ */
105
+ export function extractTokenSymbol(text: string): string | null {
106
+ // Match 3-5 uppercase letters that might be a token symbol
107
+ const match = text.match(/\b([A-Z]{3,5})\b/);
108
+ return match ? match[1] : null;
109
+ }
110
+
111
+ /**
112
+ * Format OHLCV data for display
113
+ */
114
+ export function formatOHLCV(candle: {
115
+ timestamp: number;
116
+ open: number;
117
+ high: number;
118
+ low: number;
119
+ close: number;
120
+ volume?: number;
121
+ }): string {
122
+ const date = formatDate(candle.timestamp);
123
+ let result = `📅 ${date}\n`;
124
+ result += ` Open: ${formatCurrency(candle.open)}\n`;
125
+ result += ` High: ${formatCurrency(candle.high)}\n`;
126
+ result += ` Low: ${formatCurrency(candle.low)}\n`;
127
+ result += ` Close: ${formatCurrency(candle.close)}`;
128
+ if (candle.volume !== undefined) {
129
+ result += `\n Volume: ${formatCurrency(candle.volume)}`;
130
+ }
131
+ return result;
132
+ }
133
+
134
+ /**
135
+ * Clean HTML tags from text
136
+ */
137
+ export function stripHtml(html: string): string {
138
+ return html.replace(/<[^>]*>/g, "");
139
+ }
140
+
141
+ /**
142
+ * Validate if a string is a valid token address
143
+ */
144
+ export function isValidTokenAddress(address: string): boolean {
145
+ // Ethereum address (0x followed by 40 hex characters)
146
+ const ethRegex = /^0x[a-fA-F0-9]{40}$/;
147
+ // Solana address (base58, 32-44 characters)
148
+ const solRegex = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
149
+
150
+ return ethRegex.test(address) || solRegex.test(address);
151
+ }