@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,74 @@
1
+ // @ts-nocheck — legacy code from absorbed plugins (lp-manager, lpinfo, dexscreener, defi-news, birdeye); strict types pending cleanup
2
+ export const DEFAULT_MAX_RETRIES = 3;
3
+
4
+ export const BIRDEYE_SERVICE_NAME = "birdeye";
5
+
6
+ export const DEFAULT_SUPPORTED_SYMBOLS = {
7
+ SOL: "So11111111111111111111111111111111111111112",
8
+ BTC: "qfnqNqs3nCAHjnyCgLRDbBtq4p2MtHZxw8YjSyYhPoL",
9
+ ETH: "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs",
10
+ Example: "2weMjPLLybRMMva1fM3U31goWWrCpF59CHWNhnCJ9Vyh",
11
+ };
12
+
13
+ export const API_BASE_URL = "https://public-api.birdeye.so";
14
+
15
+ export const RETRY_DELAY_MS = 2_000;
16
+
17
+ export const BIRDEYE_ENDPOINTS = {
18
+ defi: {
19
+ networks: "/defi/networks", // https://docs.birdeye.so/reference/get_defi-networks
20
+ price: "/defi/price", // https://docs.birdeye.so/reference/get_defi-price
21
+ price_multi: "/defi/multi_price", // https://docs.birdeye.so/reference/get_defi-multi-price
22
+ price_multi_POST: "/defi/multi_price", // https://docs.birdeye.so/reference/post_defi-multi-price
23
+ history_price: "/defi/history_price", // https://docs.birdeye.so/reference/get_defi-history-price
24
+ historical_price_unix: "/defi/historical_price_unix", // https://docs.birdeye.so/reference/get_defi-historical-price-unix
25
+ trades_token: "/defi/txs/token", // https://docs.birdeye.so/reference/get_defi-txs-token
26
+ trades_pair: "/defi/txs/pair", // https://docs.birdeye.so/reference/get_defi-txs-pair
27
+ trades_token_seek: "/defi/txs/token/seek_by_time", // https://docs.birdeye.so/reference/get_defi-txs-token-seek-by-time
28
+ trades_pair_seek: "/defi/txs/pair/seek_by_time", // https://docs.birdeye.so/reference/get_defi-txs-pair-seek-by-time
29
+ ohlcv: "/defi/ohlcv", // https://docs.birdeye.so/reference/get_defi-ohlcv
30
+ ohlcv_pair: "/defi/ohlcv/pair", // https://docs.birdeye.so/reference/get_defi-ohlcv-pair
31
+ ohlcv_base_quote: "/defi/ohlcv/base_quote", // https://docs.birdeye.so/reference/get_defi-ohlcv-base-quote
32
+ price_volume: "/defi/price_volume/single", // https://docs.birdeye.so/reference/get_defi-price-volume-single
33
+ price_volume_multi: "/defi/price_volume/multi", // https://docs.birdeye.so/reference/get_defi-price-volume-multi
34
+ price_volume_multi_POST: "/defi/price_volume/multi", // https://docs.birdeye.so/reference/post_defi-price-volume-multi
35
+ },
36
+ token: {
37
+ list_all: "/defi/tokenlist", // https://docs.birdeye.so/reference/get_defi-tokenlist
38
+ security: "/defi/token_security", // https://docs.birdeye.so/reference/get_defi-token-security
39
+ overview: "/defi/token_overview", // https://docs.birdeye.so/reference/get_defi-token-overview
40
+ creation_info: "/defi/token_creation_info", // https://docs.birdeye.so/reference/get_defi-token-creation-info
41
+ trending: "/defi/token_trending", // https://docs.birdeye.so/reference/get_defi-token-trending
42
+ list_all_v2_POST: "/defi/v2/tokens/all", // https://docs.birdeye.so/reference/post_defi-v2-tokens-all
43
+ new_listing: "/defi/v2/tokens/new_listing", // https://docs.birdeye.so/reference/get_defi-v2-tokens-new-listing
44
+ top_traders: "/defi/v2/tokens/top_traders", // https://docs.birdeye.so/reference/get_defi-v2-tokens-top-traders
45
+ all_markets: "/defi/v2/markets", // https://docs.birdeye.so/reference/get_defi-v2-markets
46
+ metadata_single: "/defi/v3/token/meta-data/single", // https://docs.birdeye.so/reference/get_defi-v3-token-meta-data-single
47
+ metadata_multi: "/defi/v3/token/meta-data/multiple", // https://docs.birdeye.so/reference/get_defi-v3-token-meta-data-multiple
48
+ market_data: "/defi/v3/token/market-data", // https://docs.birdeye.so/reference/get_defi-v3-token-market-data
49
+ trade_data_single: "/defi/v3/token/trade-data/single", // https://docs.birdeye.so/reference/get_defi-v3-token-trade-data-single
50
+ trade_data_multi: "/defi/v3/token/trade-data/multiple", // https://docs.birdeye.so/reference/get_defi-v3-token-trade-data-multiple
51
+ holders: "/defi/v3/token/holder", // https://docs.birdeye.so/reference/get_defi-v3-token-holder
52
+ mint_burn: "/defi/v3/token/mint-burn-txs", // https://docs.birdeye.so/reference/get_defi-v3-token-mint-burn-txs
53
+ },
54
+ wallet: {
55
+ networks: "/v1/wallet/list_supported_chain", // https://docs.birdeye.so/reference/get_v1-wallet-list-supported-chain
56
+ portfolio: "/v1/wallet/token_list", // https://docs.birdeye.so/reference/get_v1-wallet-token-list
57
+ portfolio_multichain: "/v1/wallet/multichain_token_list", // https://docs.birdeye.so/reference/get_v1-wallet-multichain-token-list
58
+ token_balance: "/v1/wallet/token_balance", // https://docs.birdeye.so/reference/get_v1-wallet-token-balance
59
+ transaction_history: "/v1/wallet/tx_list", // https://docs.birdeye.so/reference/get_v1-wallet-tx-list
60
+ transaction_history_multichain: "/v1/wallet/multichain_tx_list", // https://docs.birdeye.so/reference/get_v1-wallet-multichain-tx-list
61
+ transaction_simulation_POST: "/v1/wallet/simulate", // https://docs.birdeye.so/reference/post_v1-wallet-simulate
62
+ },
63
+ trader: {
64
+ gainers_losers: "/trader/gainers-losers", // https://docs.birdeye.so/reference/get_trader-gainers-losers
65
+ trades_seek: "/trader/txs/seek_by_time", // https://docs.birdeye.so/reference/get_trader-txs-seek-by-time
66
+ },
67
+ pair: {
68
+ overview_multi: "/defi/v3/pair/overview/multiple", // https://docs.birdeye.so/reference/get_defi-v3-pair-overview-multiple
69
+ overview_single: "/defi/v3/pair/overview/single", // https://docs.birdeye.so/reference/get_defi-v3-pair-overview-single
70
+ },
71
+ search: {
72
+ token_market: "/defi/v3/search", // https://docs.birdeye.so/reference/get_defi-v3-search
73
+ },
74
+ };
@@ -0,0 +1,18 @@
1
+ // @ts-nocheck — legacy code from absorbed plugins (lp-manager, lpinfo, dexscreener, defi-news, birdeye); strict types pending cleanup
2
+ import {
3
+ createBirdeyePortfolioProvider,
4
+ formatPortfolio,
5
+ } from "./portfolio-factory";
6
+
7
+ /**
8
+ * Agent portfolio data provider that queries Birdeye API for the agent's wallet address.
9
+ * When a wallet address is set, this provider fetches current token balances and makes
10
+ * compact JSON portfolio context available to the planner.
11
+ */
12
+ export const agentPortfolioProvider = createBirdeyePortfolioProvider({
13
+ name: "BIRDEYE_WALLET_PORTFOLIO",
14
+ description: "Birdeye token balances for the agent wallet",
15
+ descriptionCompressed: "Read Birdeye token balances for wallet.",
16
+ });
17
+
18
+ export { formatPortfolio };
@@ -0,0 +1,227 @@
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 { addHeader, composeActionExamples, formatActionNames, formatActions } from '@elizaos/core';
4
+ //import type { IToken } from '../types';
5
+ import { BIRDEYE_SERVICE_NAME } from "../constants";
6
+ import type { CacheWrapper, GetCacheTimedOptions } from "../types/shared";
7
+ import { formatJsonScalar, formatJsonTable } from "../utils";
8
+
9
+ const MARKET_ROW_LIMIT = 12;
10
+
11
+ export async function getCacheTimed<T>(
12
+ runtime: IAgentRuntime,
13
+ key: string,
14
+ options: GetCacheTimedOptions = {},
15
+ ): Promise<T | undefined> {
16
+ const wrapper = await runtime.getCache<CacheWrapper<T>>(key);
17
+ if (!wrapper) return;
18
+ if (options.notOlderThan) {
19
+ const diff = Date.now() - wrapper.setAt;
20
+ //console.log('checking notOlderThan', diff + 'ms', 'setAt', wrapper.setAt, 'asking', options.notOlderThan)
21
+ if (diff > options.notOlderThan) {
22
+ // no data
23
+ return;
24
+ }
25
+ }
26
+ // return data
27
+ return wrapper.data;
28
+ }
29
+
30
+ /**
31
+ * Provider for Birdeye market data
32
+ *
33
+ * @typedef {import('./Provider').Provider} Provider
34
+ * @typedef {import('./Runtime').IAgentRuntime} IAgentRuntime
35
+ * @typedef {import('./Memory').Memory} Memory
36
+ * @typedef {import('./State').State} State
37
+ * @typedef {import('./Action').Action} Action
38
+ *
39
+ * @type {Provider}
40
+ * @property {string} name - The name of the provider
41
+ * @property {string} description - Description of the provider
42
+ * @property {number} position - The position of the provider
43
+ * @property {Function} get - Asynchronous function to get actions that validate for a given message
44
+ *
45
+ * @param {IAgentRuntime} runtime - The agent runtime
46
+ * @param {Memory} message - The message memory
47
+ * @param {State} state - The state of the agent
48
+ * @returns {Object} Object containing data, values, and text related to actions
49
+ */
50
+ export const marketProvider: Provider = {
51
+ name: "BIRDEYE_CRYPTOCURRENCY_MARKET_DATA",
52
+ description: "Birdeye get latest cryptocurrencies overview",
53
+ descriptionCompressed: "Read latest Birdeye cryptocurrency market overview.",
54
+ dynamic: true,
55
+ contexts: ["finance", "crypto", "wallet"],
56
+ contextGate: { anyOf: ["finance", "crypto", "wallet"] },
57
+ cacheStable: false,
58
+ cacheScope: "turn",
59
+ roleGate: { minRole: "USER" },
60
+ //position: -1,
61
+ get: async (runtime: IAgentRuntime, _message: Memory, _state: State) => {
62
+ try {
63
+ //console.log('BIRDEYE_CRYPTOCURRENCY_MARKET_DATA getting');
64
+
65
+ // define the market
66
+ // FIXME: get out of runtime.getSettings
67
+ const TOKEN_ADDRESSES = {
68
+ SOL: "So11111111111111111111111111111111111111112",
69
+ BTC: "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh", // wBTC
70
+ ETH: "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs", // wETH
71
+ };
72
+
73
+ const hardcodedSolanaCA2SymbolMap = {
74
+ So11111111111111111111111111111111111111112: "SOL",
75
+ "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh": "BTC", // wBTC
76
+ "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs": "ETH", // wETH
77
+ };
78
+
79
+ // get the market
80
+ const CAs = Object.values(TOKEN_ADDRESSES);
81
+
82
+ // get services
83
+ const birdeyeService = runtime.getService(BIRDEYE_SERVICE_NAME) as
84
+ | {
85
+ getTokensMarketData?: (
86
+ chain: string,
87
+ addresses: string[],
88
+ ) => Promise<
89
+ Record<
90
+ string,
91
+ {
92
+ symbol: string;
93
+ priceUsd: number;
94
+ priceChange24h: number;
95
+ liquidity: number;
96
+ }
97
+ >
98
+ >;
99
+ }
100
+ | undefined;
101
+ // want this for custom symbols
102
+ const solanaService = runtime.getService("chain_solana") as
103
+ | {
104
+ getTokensSymbols?: (
105
+ addresses: string[],
106
+ ) => Promise<Record<string, string>>;
107
+ }
108
+ | undefined;
109
+
110
+ // Guard Birdeye service before invoking methods
111
+ if (
112
+ !birdeyeService ||
113
+ typeof birdeyeService.getTokensMarketData !== "function"
114
+ ) {
115
+ runtime.logger?.error(
116
+ "Birdeye service is unavailable or does not have getTokensMarketData method",
117
+ );
118
+ return {
119
+ values: {},
120
+ text: [
121
+ "birdeye_market_data:",
122
+ " status: unavailable",
123
+ " reason: missing getTokensMarketData",
124
+ ].join("\n"),
125
+ data: {},
126
+ };
127
+ }
128
+
129
+ // FIXME: cache (how fresh does this have to be? 5 mins? 1 min?)
130
+ // get data
131
+ const ps = [birdeyeService.getTokensMarketData("solana", CAs)];
132
+ if (
133
+ solanaService &&
134
+ typeof solanaService.getTokensSymbols === "function"
135
+ ) {
136
+ ps.push(solanaService.getTokensSymbols(CAs));
137
+ }
138
+
139
+ const results = await Promise.all(ps);
140
+
141
+ const result = results[0]; // birdeye Results
142
+ const rows = [];
143
+
144
+ // FIXME: Market cap column is currently not populated from Birdeye API response
145
+ // Need to calculate or fetch market cap data separately
146
+ for (const ca of CAs) {
147
+ // Check if result[ca] exists before accessing it
148
+ if (!result[ca]) {
149
+ rows.push({
150
+ chain: "solana",
151
+ address: ca,
152
+ symbol: "unknown",
153
+ priceUsd: "unknown",
154
+ marketCapUsd: "unknown",
155
+ change24hPct: "unknown",
156
+ liquidityUsd: "unknown",
157
+ });
158
+ continue;
159
+ }
160
+
161
+ const t = result[ca];
162
+ t.symbol =
163
+ solanaService && results[1]
164
+ ? results[1][ca]
165
+ : (hardcodedSolanaCA2SymbolMap[ca] ?? "(Not available)");
166
+ // unwrap symbols
167
+ if (t.symbol === "WBTC") t.symbol = "BTC";
168
+ if (t.symbol === "WETH") t.symbol = "ETH";
169
+ //console.log('t', t)
170
+ rows.push({
171
+ chain: "solana",
172
+ address: ca,
173
+ symbol: t.symbol,
174
+ priceUsd: t.priceUsd.toFixed(4),
175
+ marketCapUsd: "unknown",
176
+ change24hPct: t.priceChange24h.toFixed(2),
177
+ liquidityUsd: t.liquidity.toFixed(2),
178
+ });
179
+ }
180
+
181
+ //console.log('BIRDEYE_CRYPTOCURRENCY_MARKET_DATA - birdye market data text', latestTxt)
182
+
183
+ const boundedRows = rows.slice(0, MARKET_ROW_LIMIT);
184
+ const data = {
185
+ tokens: Object.fromEntries(
186
+ Object.entries(results[0] ?? {}).slice(0, MARKET_ROW_LIMIT),
187
+ ),
188
+ };
189
+
190
+ const values = {};
191
+
192
+ // Combine all text sections
193
+ const text = [
194
+ "birdeye_market_data:",
195
+ " status: ok",
196
+ formatJsonTable(" tokens", boundedRows, [
197
+ "chain",
198
+ "address",
199
+ "symbol",
200
+ "priceUsd",
201
+ "marketCapUsd",
202
+ "change24hPct",
203
+ "liquidityUsd",
204
+ ]),
205
+ ].join("\n");
206
+
207
+ return {
208
+ data,
209
+ values,
210
+ text,
211
+ };
212
+ } catch (err) {
213
+ runtime.logger?.error(
214
+ `Error fetching Birdeye market data: ${err instanceof Error ? err.message : String(err)}`,
215
+ );
216
+ return {
217
+ values: {},
218
+ text: [
219
+ "birdeye_market_data:",
220
+ " status: error",
221
+ ` reason: ${formatJsonScalar(err instanceof Error ? err.message : String(err))}`,
222
+ ].join("\n"),
223
+ data: {},
224
+ };
225
+ }
226
+ },
227
+ };
@@ -0,0 +1,138 @@
1
+ import type { IAgentRuntime, Memory, State } from "@elizaos/core";
2
+ import { describe, expect, it, vi } from "vitest";
3
+ import type { WalletPortfolioResponse } from "../types/api/wallet";
4
+ import {
5
+ createBirdeyePortfolioProvider,
6
+ formatPortfolio,
7
+ } from "./portfolio-factory";
8
+
9
+ const WALLET = "So11111111111111111111111111111111111111112";
10
+
11
+ function createRuntime(service: unknown): IAgentRuntime {
12
+ const runtime = {
13
+ getSetting: vi.fn((key: string) => {
14
+ if (key === "BIRDEYE_WALLET_ADDR") return WALLET;
15
+ if (key === "BIRDEYE_CHAIN") return "solana";
16
+ return undefined;
17
+ }),
18
+ getService: vi.fn(() => service),
19
+ logger: {
20
+ error: vi.fn(),
21
+ warn: vi.fn(),
22
+ log: vi.fn(),
23
+ debug: vi.fn(),
24
+ },
25
+ };
26
+
27
+ return runtime as IAgentRuntime;
28
+ }
29
+
30
+ describe("Birdeye portfolio provider factory", () => {
31
+ it("creates a portfolio provider that fetches holdings and renders JSON", async () => {
32
+ const service = {
33
+ fetchWalletTokenList: vi.fn(async () => ({
34
+ wallet: WALLET,
35
+ totalUsd: 250.5,
36
+ items: [
37
+ {
38
+ symbol: "SOL",
39
+ address: WALLET,
40
+ uiAmount: 1.23456,
41
+ priceUsd: 200.123456,
42
+ valueUsd: 247.11,
43
+ chainId: "solana",
44
+ },
45
+ ],
46
+ })),
47
+ };
48
+ const provider = createBirdeyePortfolioProvider({
49
+ name: "TEST_PORTFOLIO",
50
+ description: "Test portfolio",
51
+ descriptionCompressed: "test birdeye portfolio",
52
+ });
53
+
54
+ const result = await provider.get(
55
+ createRuntime(service),
56
+ {} as Memory,
57
+ {} as State,
58
+ );
59
+
60
+ expect(service.fetchWalletTokenList).toHaveBeenCalledWith(
61
+ "solana",
62
+ WALLET,
63
+ { notOlderThan: 30000 },
64
+ );
65
+ expect(result.text).toContain("birdeye_wallet_portfolio:");
66
+ expect(result.text).toContain(
67
+ "holdings[1]{symbol,address,amount,priceUsd,valueUsd,chainId}:",
68
+ );
69
+ expect(result.text).toContain("SOL");
70
+ expect(result.text).not.toContain("This is your portfolio");
71
+ });
72
+
73
+ it("creates a trade provider variant from the same factory", async () => {
74
+ const service = {
75
+ fetchWalletTokenList: vi.fn(async () => ({
76
+ wallet: WALLET,
77
+ totalUsd: 50,
78
+ items: [],
79
+ })),
80
+ fetchWalletTxList: vi.fn(async () => [
81
+ {
82
+ txHash: "tx-1",
83
+ mainAction: "swap",
84
+ status: true,
85
+ blockTime: "2026-05-05T12:00:00Z",
86
+ from: WALLET,
87
+ to: "market",
88
+ },
89
+ ]),
90
+ };
91
+ const provider = createBirdeyePortfolioProvider({
92
+ name: "TEST_TRADES",
93
+ description: "Test trades",
94
+ descriptionCompressed: "test birdeye trades",
95
+ includeTrades: true,
96
+ });
97
+
98
+ const result = await provider.get(
99
+ createRuntime(service),
100
+ {} as Memory,
101
+ {} as State,
102
+ );
103
+
104
+ expect(service.fetchWalletTokenList).toHaveBeenCalledTimes(1);
105
+ expect(service.fetchWalletTxList).toHaveBeenCalledWith("solana", WALLET, {
106
+ notOlderThan: 30000,
107
+ });
108
+ expect(result.data).toMatchObject({
109
+ portfolio: { totalUsd: 50 },
110
+ trades: [{ txHash: "tx-1" }],
111
+ });
112
+ expect(result.text).toContain("tradeCount: 1");
113
+ expect(result.text).toContain(
114
+ "trades[1]{txHash,action,status,blockTime,from,to}:",
115
+ );
116
+ });
117
+
118
+ it("formats legacy portfolio wrappers as JSON holdings", () => {
119
+ const legacy: WalletPortfolioResponse = {
120
+ success: true,
121
+ data: {
122
+ items: [
123
+ {
124
+ symbol: "ETH",
125
+ address: "0x0000000000000000000000000000000000000000",
126
+ uiAmount: 2,
127
+ priceUsd: 100,
128
+ valueUsd: 200,
129
+ chainId: "ethereum",
130
+ },
131
+ ],
132
+ },
133
+ };
134
+ expect(formatPortfolio(legacy)).toContain(
135
+ "holdings[1]{symbol,address,amount,priceUsd,valueUsd,chainId}:",
136
+ );
137
+ });
138
+ });