@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,252 @@
1
+ // @ts-nocheck — legacy code from absorbed plugins (lp-manager, lpinfo, dexscreener, defi-news, birdeye); strict types pending cleanup
2
+ import type { IAgentRuntime, Memory, Provider, State } from "@elizaos/core";
3
+ import { BIRDEYE_SERVICE_NAME } from "../constants";
4
+ import type { WalletPortfolioResponse } from "../types/api/wallet";
5
+ import { extractChain, formatJsonScalar, formatJsonTable } from "../utils";
6
+
7
+ type PortfolioService = {
8
+ fetchWalletTokenList?: (
9
+ chain: unknown,
10
+ walletAddr: string,
11
+ opts: { notOlderThan: number },
12
+ ) => Promise<unknown>;
13
+ fetchWalletTxList?: (
14
+ chain: unknown,
15
+ walletAddr: string,
16
+ opts: { notOlderThan: number },
17
+ ) => Promise<unknown[]>;
18
+ };
19
+
20
+ export interface BirdeyePortfolioProviderOptions {
21
+ name: string;
22
+ description: string;
23
+ descriptionCompressed: string;
24
+ includeTrades?: boolean;
25
+ }
26
+
27
+ function statusJson(name: string, status: string, reason: string): string {
28
+ return [
29
+ `${name}:`,
30
+ ` status: ${formatJsonScalar(status)}`,
31
+ ` reason: ${formatJsonScalar(reason)}`,
32
+ ].join("\n");
33
+ }
34
+
35
+ function normalizePortfolioResponse(response: unknown) {
36
+ if (response?.data?.items) {
37
+ return response.data;
38
+ }
39
+ return response ?? {};
40
+ }
41
+
42
+ export const formatPortfolio = (response: WalletPortfolioResponse) => {
43
+ const portfolio = normalizePortfolioResponse(response);
44
+ const items = portfolio.items ?? [];
45
+ if (!items.length) return "holdings[0]: []";
46
+
47
+ return formatJsonTable(
48
+ "holdings",
49
+ items.map((item) => ({
50
+ symbol: item.symbol || "unknown",
51
+ address: item.address || "unknown",
52
+ amount:
53
+ typeof item.uiAmount === "number"
54
+ ? Number(item.uiAmount.toFixed(4))
55
+ : "unknown",
56
+ priceUsd:
57
+ typeof item.priceUsd === "number"
58
+ ? Number(item.priceUsd.toFixed(6))
59
+ : "unknown",
60
+ valueUsd:
61
+ typeof item.valueUsd === "number"
62
+ ? Number(item.valueUsd.toFixed(2))
63
+ : "unknown",
64
+ chainId: item.chainId || "unknown",
65
+ })),
66
+ ["symbol", "address", "amount", "priceUsd", "valueUsd", "chainId"],
67
+ );
68
+ };
69
+
70
+ function formatPortfolioProviderText({
71
+ wallet,
72
+ chain,
73
+ portfolio,
74
+ trades,
75
+ }: {
76
+ wallet: string;
77
+ chain: string;
78
+ portfolio: unknown;
79
+ trades?: unknown[];
80
+ }): string {
81
+ const normalized = normalizePortfolioResponse(portfolio);
82
+ const holdings = normalized.items ?? [];
83
+ const lines = [
84
+ "birdeye_wallet_portfolio:",
85
+ " status: ok",
86
+ ` wallet: ${formatJsonScalar(normalized.wallet ?? wallet)}`,
87
+ ` chain: ${formatJsonScalar(chain)}`,
88
+ ` totalUsd: ${formatJsonScalar(normalized.totalUsd ?? 0)}`,
89
+ formatJsonTable(
90
+ " holdings",
91
+ holdings.slice(0, 20).map((item) => ({
92
+ symbol: item.symbol || "unknown",
93
+ address: item.address || "unknown",
94
+ amount:
95
+ typeof item.uiAmount === "number"
96
+ ? Number(item.uiAmount.toFixed(4))
97
+ : "unknown",
98
+ priceUsd:
99
+ typeof item.priceUsd === "number"
100
+ ? Number(item.priceUsd.toFixed(6))
101
+ : "unknown",
102
+ valueUsd:
103
+ typeof item.valueUsd === "number"
104
+ ? Number(item.valueUsd.toFixed(2))
105
+ : "unknown",
106
+ chainId: item.chainId || "unknown",
107
+ })),
108
+ ["symbol", "address", "amount", "priceUsd", "valueUsd", "chainId"],
109
+ ),
110
+ ];
111
+
112
+ if (trades) {
113
+ lines.push(` tradeCount: ${trades.length}`);
114
+ lines.push(
115
+ formatJsonTable(
116
+ " trades",
117
+ trades.slice(0, 10).map((trade) => ({
118
+ txHash: trade.txHash ?? "unknown",
119
+ action: trade.mainAction ?? "unknown",
120
+ status: trade.status ?? "unknown",
121
+ blockTime: trade.blockTime ?? "unknown",
122
+ from: trade.from ?? "unknown",
123
+ to: trade.to ?? "unknown",
124
+ })),
125
+ ["txHash", "action", "status", "blockTime", "from", "to"],
126
+ ),
127
+ );
128
+ }
129
+
130
+ return lines.join("\n");
131
+ }
132
+
133
+ function getPortfolioService(
134
+ runtime: IAgentRuntime,
135
+ includeTrades: boolean,
136
+ ): PortfolioService | undefined {
137
+ const beService = runtime.getService(BIRDEYE_SERVICE_NAME) as
138
+ | PortfolioService
139
+ | undefined;
140
+ if (!beService || typeof beService.fetchWalletTokenList !== "function") {
141
+ return undefined;
142
+ }
143
+ if (includeTrades && typeof beService.fetchWalletTxList !== "function") {
144
+ return undefined;
145
+ }
146
+ return beService;
147
+ }
148
+
149
+ export function createBirdeyePortfolioProvider(
150
+ options: BirdeyePortfolioProviderOptions,
151
+ ): Provider {
152
+ const includeTrades = options.includeTrades ?? false;
153
+ return {
154
+ name: options.name,
155
+ description: options.description,
156
+ descriptionCompressed: options.descriptionCompressed,
157
+ dynamic: true,
158
+ contexts: ["finance", "crypto", "wallet"],
159
+ contextGate: { anyOf: ["finance", "crypto", "wallet"] },
160
+ cacheStable: false,
161
+ cacheScope: "turn",
162
+ roleGate: { minRole: "OWNER" },
163
+ get: async (runtime: IAgentRuntime, _message: Memory, _state?: State) => {
164
+ try {
165
+ const walletAddr = runtime.getSetting("BIRDEYE_WALLET_ADDR");
166
+ if (!walletAddr) {
167
+ runtime.logger?.error(
168
+ "BIRDEYE_WALLET_ADDR setting is not configured",
169
+ );
170
+ return {
171
+ values: {},
172
+ text: statusJson(
173
+ "birdeye_wallet_portfolio",
174
+ "error",
175
+ "missing BIRDEYE_WALLET_ADDR",
176
+ ),
177
+ data: {},
178
+ };
179
+ }
180
+
181
+ const explicitChain = runtime.getSetting("BIRDEYE_CHAIN");
182
+ const chain = extractChain(walletAddr, explicitChain);
183
+ const beService = getPortfolioService(runtime, includeTrades);
184
+ if (!beService) {
185
+ runtime.logger?.error(
186
+ "Birdeye service is unavailable or missing required portfolio methods",
187
+ );
188
+ return {
189
+ values: {},
190
+ text: statusJson(
191
+ "birdeye_wallet_portfolio",
192
+ "unavailable",
193
+ includeTrades
194
+ ? "missing fetchWalletTokenList or fetchWalletTxList"
195
+ : "missing fetchWalletTokenList",
196
+ ),
197
+ data: {},
198
+ };
199
+ }
200
+
201
+ const portfolioPromise = beService.fetchWalletTokenList(
202
+ chain,
203
+ walletAddr,
204
+ { notOlderThan: 30 * 1000 },
205
+ );
206
+ const tradesPromise = includeTrades
207
+ ? beService.fetchWalletTxList(chain, walletAddr, {
208
+ notOlderThan: 30 * 1000,
209
+ })
210
+ : Promise.resolve(undefined);
211
+ const [portfolio, trades] = await Promise.all([
212
+ portfolioPromise,
213
+ tradesPromise,
214
+ ]);
215
+
216
+ return {
217
+ data: includeTrades ? { portfolio, trades } : portfolio,
218
+ values: {},
219
+ text: formatPortfolioProviderText({
220
+ wallet: walletAddr,
221
+ chain,
222
+ portfolio,
223
+ trades,
224
+ }),
225
+ };
226
+ } catch (error) {
227
+ const errorMessage =
228
+ error instanceof Error ? error.message : String(error);
229
+ runtime.logger?.error(
230
+ `Error fetching Birdeye portfolio: ${errorMessage}`,
231
+ );
232
+
233
+ const isConfigError =
234
+ errorMessage.includes("BIRDEYE_CHAIN") ||
235
+ errorMessage.includes("address") ||
236
+ errorMessage.includes("Invalid");
237
+
238
+ return {
239
+ values: {},
240
+ text: statusJson(
241
+ "birdeye_wallet_portfolio",
242
+ "error",
243
+ isConfigError
244
+ ? errorMessage
245
+ : "unable to fetch wallet portfolio data",
246
+ ),
247
+ data: {},
248
+ };
249
+ }
250
+ },
251
+ };
252
+ }
@@ -0,0 +1,365 @@
1
+ // @ts-nocheck — legacy code from absorbed plugins (lp-manager, lpinfo, dexscreener, defi-news, birdeye); strict types pending cleanup
2
+ import type { IAgentRuntime, Memory, Provider, State } from "@elizaos/core";
3
+ import { formatJsonScalar, formatJsonTable } from "../utils";
4
+
5
+ const TRENDING_ROW_LIMIT = 18;
6
+
7
+ interface TrendingToken {
8
+ address: string;
9
+ symbol: string;
10
+ price: number;
11
+ volume24hUSD: number;
12
+ price24hChangePercent: number;
13
+ liquidity: number;
14
+ }
15
+
16
+ export async function getCacheTimed<T>(
17
+ runtime: IAgentRuntime,
18
+ key: string,
19
+ options: { notOlderThan?: number } = {},
20
+ ): Promise<T | false> {
21
+ const wrapper = await runtime.getCache<{ data: T; setAt: number }>(key);
22
+ if (!wrapper) return false;
23
+ if (options.notOlderThan) {
24
+ const diff = Date.now() - wrapper.setAt;
25
+ //console.log('checking notOlderThan', diff + 'ms', 'setAt', wrapper.setAt, 'asking', options.notOlderThan)
26
+ if (diff > options.notOlderThan) {
27
+ // no data
28
+ return false;
29
+ }
30
+ }
31
+ // return data
32
+ return wrapper.data;
33
+ }
34
+
35
+ /**
36
+ * Provider for Birdeye trending coins
37
+ *
38
+ * @typedef {import('./Provider').Provider} Provider
39
+ * @typedef {import('./Runtime').IAgentRuntime} IAgentRuntime
40
+ * @typedef {import('./Memory').Memory} Memory
41
+ * @typedef {import('./State').State} State
42
+ * @typedef {import('./Action').Action} Action
43
+ *
44
+ * @type {Provider}
45
+ * @property {string} name - The name of the provider
46
+ * @property {string} description - Description of the provider
47
+ * @property {number} position - The position of the provider
48
+ * @property {Function} get - Asynchronous function to get actions that validate for a given message
49
+ *
50
+ * @param {IAgentRuntime} runtime - The agent runtime
51
+ * @param {Memory} message - The message memory
52
+ * @param {State} state - The state of the agent
53
+ * @returns {Object} Object containing data, values, and text related to actions
54
+ */
55
+ export const trendingProvider: Provider = {
56
+ name: "BIRDEYE_TRENDING_CRYPTOCURRENCY",
57
+ description: "Birdeye's trending cryptocurrencies",
58
+ descriptionCompressed: "Read Birdeye trending cryptocurrency tokens.",
59
+ dynamic: true,
60
+ contexts: ["finance", "crypto", "wallet"],
61
+ contextGate: { anyOf: ["finance", "crypto", "wallet"] },
62
+ cacheStable: false,
63
+ cacheScope: "turn",
64
+ roleGate: { minRole: "USER" },
65
+ //position: -1,
66
+ get: async (runtime: IAgentRuntime, _message: Memory, _state: State) => {
67
+ try {
68
+ runtime.logger?.log("birdeye:provider:trending - get birdeye");
69
+ // Get all sentiments
70
+
71
+ /*
72
+ const chains = ['solana', 'eth', 'base'];
73
+ const tokenData = []
74
+ for(const chain of chains) {
75
+ tokenData = [...tokenData, ...(await runtime.getCache<IToken[]>('tokens_' + chain)) || []];
76
+ }
77
+ console.log('tokenData', tokenData)
78
+ */
79
+ const solanaCache = await runtime.getCache<{
80
+ data: TrendingToken[];
81
+ setAt: number;
82
+ }>("tokens_v2_solana");
83
+ if (!solanaCache?.data) {
84
+ runtime.logger?.warn(
85
+ "birdeye:provider:trending - no birdeye token data found",
86
+ );
87
+ return {
88
+ values: {},
89
+ text: [
90
+ "birdeye_trending_tokens:",
91
+ " status: empty",
92
+ " reason: no cached Solana trending token data",
93
+ ].join("\n"),
94
+ data: {},
95
+ };
96
+ }
97
+ const solanaTokens = solanaCache.data;
98
+ //console.log('intel:provider - birdeye data', tokens)
99
+ if (!solanaTokens.length) {
100
+ runtime.logger?.warn(
101
+ "birdeye:provider:trending - no birdeye token data found",
102
+ );
103
+ return {
104
+ values: {},
105
+ text: [
106
+ "birdeye_trending_tokens:",
107
+ " status: empty",
108
+ " reason: no Solana trending tokens",
109
+ ].join("\n"),
110
+ data: {},
111
+ };
112
+ }
113
+
114
+ //console.log('birdeye:provider:trending - birdeye token data', tokens)
115
+ /*
116
+ name: "Bitcoin",
117
+ rank: 1,
118
+ chain: "L1",
119
+ price: 93768.60351119141,
120
+ symbol: "BTC",
121
+ address: "bitcoin",
122
+ logoURI: "https://s2.coinmarketcap.com/static/img/coins/128x128/1.png",
123
+ decimals: null,
124
+ provider: "coinmarketcap",
125
+ liquidity: null,
126
+ marketcap: 0,
127
+ last_updated: "2025-04-23T22:50:00.000Z",
128
+ volume24hUSD: 43588891208.92652,
129
+ price24hChangePercent: 1.17760374,
130
+ */
131
+
132
+ const rows = [];
133
+
134
+ const solanaService = runtime.getService("chain_solana") as
135
+ | {
136
+ getSupply?: (addresses: string[]) => Promise<
137
+ Record<
138
+ string,
139
+ {
140
+ human?: {
141
+ multipliedBy: (n: number) => {
142
+ toFixed: (p: number) => string;
143
+ };
144
+ };
145
+ }
146
+ >
147
+ >;
148
+ }
149
+ | undefined;
150
+ if (!solanaService) {
151
+ runtime.logger?.warn(
152
+ "no chain_solana service found - market cap calculation will be skipped for Solana tokens",
153
+ );
154
+ }
155
+
156
+ const topSolanaTokens = solanaTokens.slice(0, 33);
157
+ let tokens = [...topSolanaTokens];
158
+
159
+ // Try to get supply data if solanaService is available
160
+ let supplies: Record<
161
+ string,
162
+ {
163
+ human?: {
164
+ multipliedBy: (n: number) => { toFixed: (p: number) => string };
165
+ };
166
+ }
167
+ > = {};
168
+ if (solanaService) {
169
+ try {
170
+ const CAs = topSolanaTokens.map((t) => t.address);
171
+ supplies = await solanaService.getSupply(CAs);
172
+ } catch (error) {
173
+ runtime.logger?.warn(
174
+ `Failed to get supply data from Solana service: ${error instanceof Error ? error.message : String(error)}`,
175
+ );
176
+ }
177
+ }
178
+
179
+ for (const token of topSolanaTokens) {
180
+ // has a marketcap but seems to always be 0
181
+ //console.log('token', token)
182
+ const rugKey = `rugcheck_solana_${token.address}`;
183
+ const rugCache = await getCacheTimed(runtime, rugKey, {
184
+ notOlderThan: 6 * 60 * 60 * 1000,
185
+ });
186
+ //console.log('rugKey', rugKey, 'rugCache', rugCache)
187
+
188
+ // Damnatio memoriae
189
+ if (rugCache && rugCache === "rug") {
190
+ runtime.logger?.log("omitting", token.address, "because in rugCache");
191
+ continue;
192
+ }
193
+
194
+ // Calculate market cap if supply data is available
195
+ let mcapValue = "?";
196
+ if (supplies[token.address]?.human) {
197
+ const supply = supplies[token.address].human;
198
+ const mcap = supply.multipliedBy(token.price);
199
+ mcapValue = mcap.toFixed(0);
200
+ //console.log('Hum supply', supply.toFormat(), 'price', token.price, 'mcap', mcap.toFormat(2))
201
+ //console.log('Mac supply', supply, 'price', token.price, 'mcap', mcap.toFixed(0))
202
+ }
203
+
204
+ rows.push({
205
+ chain: "solana",
206
+ address: token.address,
207
+ symbol: token.symbol,
208
+ priceUsd: token.price.toFixed(4),
209
+ marketCapUsd: mcapValue,
210
+ volume24hUsd: token.volume24hUSD.toFixed(0),
211
+ change24hPct: token.price24hChangePercent.toFixed(2),
212
+ liquidityUsd: token.liquidity.toFixed(2),
213
+ });
214
+ }
215
+ // if in cache, then it's a lot of data, maybe too much
216
+ const ethCache = await runtime.getCache<{
217
+ data: TrendingToken[];
218
+ setAt: number;
219
+ }>("tokens_v2_ethereum");
220
+ if (ethCache?.data) {
221
+ const ethTokens = ethCache.data.slice(0, 33);
222
+ tokens = [...tokens, ...ethTokens];
223
+ for (const token of ethTokens) {
224
+ // has a marketcap but seems to always be 0
225
+ //console.log('token', token)
226
+ /*
227
+ const rugKey = 'rugcheck_eth_' + token.address
228
+ const rugCache = await getCacheTimed(runtime, rugKey, { notOlderThan: 6 * 60 * 60 * 1000 })
229
+ //console.log('rugKey', rugKey, 'rugCache', rugCache)
230
+
231
+ // Damnatio memoriae
232
+ if (rugCache && rugCache === 'rug') {
233
+ console.log('omitting', token.address, 'because in rugCache')
234
+ continue
235
+ }
236
+ */
237
+ rows.push({
238
+ chain: "ethereum",
239
+ address: token.address,
240
+ symbol: token.symbol,
241
+ priceUsd: token.price?.toFixed(4) || "0",
242
+ marketCapUsd: "unknown",
243
+ volume24hUsd: token.volume24hUSD?.toFixed(0) || "0",
244
+ change24hPct: token.price24hChangePercent?.toFixed(2) || "0",
245
+ liquidityUsd: token.liquidity?.toFixed(2) || "0",
246
+ });
247
+ }
248
+ }
249
+ const baseCache = await runtime.getCache<{
250
+ data: TrendingToken[];
251
+ setAt: number;
252
+ }>("tokens_v2_base");
253
+ if (baseCache?.data) {
254
+ const baseTokens = baseCache.data.slice(0, 33);
255
+ tokens = [...tokens, ...baseTokens];
256
+ for (const token of baseTokens) {
257
+ // has a marketcap but seems to always be 0
258
+ //console.log('token', token)
259
+ /*
260
+ const rugKey = 'rugcheck_eth_' + token.address
261
+ const rugCache = await getCacheTimed(runtime, rugKey, { notOlderThan: 6 * 60 * 60 * 1000 })
262
+ //console.log('rugKey', rugKey, 'rugCache', rugCache)
263
+
264
+ // Damnatio memoriae
265
+ if (rugCache && rugCache === 'rug') {
266
+ console.log('omitting', token.address, 'because in rugCache')
267
+ continue
268
+ }
269
+ */
270
+ rows.push({
271
+ chain: "base",
272
+ address: token.address,
273
+ symbol: token.symbol,
274
+ priceUsd: token.price?.toFixed(4) || "0",
275
+ marketCapUsd: "unknown",
276
+ volume24hUsd: token.volume24hUSD?.toFixed(0) || "0",
277
+ change24hPct: token.price24hChangePercent?.toFixed(2) || "0",
278
+ liquidityUsd: token.liquidity?.toFixed(2) || "0",
279
+ });
280
+ }
281
+ }
282
+
283
+ /*
284
+ let idx = 1;
285
+ // maybe filter by active chains
286
+ const reduceTokens = tokens.map((t) => {
287
+ const obj = {
288
+ name: t.name,
289
+ rank: t.rank,
290
+ chain: t.chain,
291
+ priceUsd: t.price,
292
+ symbol: t.symbol,
293
+ address: t.address,
294
+ // skip logo, decimals
295
+ // liquidity/marketcap are optimal
296
+ // last_updated
297
+ volume24hUSD: t.volume24hUSD,
298
+ price24hChangePercent: t.price24hChangePercent,
299
+ };
300
+ // optional fields
301
+ if (t.liquidity !== null) obj.liquidity = t.liquidity;
302
+ if (t.marketcap !== 0) obj.marketcap = t.marketcap;
303
+ return obj;
304
+ });
305
+ */
306
+
307
+ /*
308
+ for (const t of tokens) {
309
+ if (!sentiment?.occuringTokens?.length) continue;
310
+ sentiments += `ENTRY ${idx}\nTIME: ${sentiment.timeslot}\nTOKEN ANALYSIS:\n`;
311
+ for (const token of sentiment.occuringTokens) {
312
+ sentiments += `${token.token} - Sentiment: ${token.sentiment}\n${token.reason}\n`;
313
+ }
314
+ latestTxt += '\n-------------------\n';
315
+ idx++;
316
+ }
317
+ */
318
+ //latestTxt += '\n' + JSON.stringify(reduceTokens) + '\n';
319
+
320
+ //console.log('intel:provider - cmc token text', rows)
321
+
322
+ const boundedRows = rows.slice(0, TRENDING_ROW_LIMIT);
323
+ const data = {
324
+ tokens: tokens.slice(0, TRENDING_ROW_LIMIT),
325
+ };
326
+
327
+ const values = {};
328
+
329
+ // Combine all text sections
330
+ const text = [
331
+ "birdeye_trending_tokens:",
332
+ " status: ok",
333
+ formatJsonTable(" tokens", boundedRows, [
334
+ "chain",
335
+ "address",
336
+ "symbol",
337
+ "priceUsd",
338
+ "marketCapUsd",
339
+ "volume24hUsd",
340
+ "change24hPct",
341
+ "liquidityUsd",
342
+ ]),
343
+ ].join("\n");
344
+
345
+ return {
346
+ data,
347
+ values,
348
+ text,
349
+ };
350
+ } catch (error) {
351
+ runtime.logger?.error(
352
+ `Error fetching trending data: ${error instanceof Error ? error.message : String(error)}`,
353
+ );
354
+ return {
355
+ values: {},
356
+ text: [
357
+ "birdeye_trending_tokens:",
358
+ " status: error",
359
+ ` reason: ${formatJsonScalar(error instanceof Error ? error.message : String(error))}`,
360
+ ].join("\n"),
361
+ data: {},
362
+ };
363
+ }
364
+ },
365
+ };
@@ -0,0 +1,14 @@
1
+ // @ts-nocheck — legacy code from absorbed plugins (lp-manager, lpinfo, dexscreener, defi-news, birdeye); strict types pending cleanup
2
+ import { createBirdeyePortfolioProvider } from "./portfolio-factory";
3
+
4
+ /**
5
+ * Optional wallet trade provider. It shares wallet, chain, service, error, and JSON
6
+ * formatting behavior with the agent portfolio provider through the portfolio factory.
7
+ */
8
+ export const tradePortfolioProvider = createBirdeyePortfolioProvider({
9
+ name: "BIRDEYE_TRADE_PORTFOLIO",
10
+ description: "Birdeye wallet portfolio and recent trade history",
11
+ descriptionCompressed:
12
+ "Read Birdeye wallet portfolio and recent trade history.",
13
+ includeTrades: true,
14
+ });