@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,544 @@
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 type { SteerLiquidityService } from "../services/steerLiquidityService";
4
+ import type {
5
+ SteerStakingPoolDetailInput,
6
+ SteerVaultDetailInput,
7
+ } from "../steer-display-types.js";
8
+
9
+ const STEER_LIQUIDITY_TEXT_LIMIT = 4000;
10
+
11
+ /**
12
+ * Steer Finance Liquidity Protocol Provider
13
+ * Provides information about Steer Finance vaults and staking pools
14
+ */
15
+ export const steerLiquidityProvider: Provider = {
16
+ name: "STEER_LIQUIDITY",
17
+ description:
18
+ "Provides information about Steer Finance vaults, staking pools, and token-specific liquidity data across multiple chains",
19
+ descriptionCompressed:
20
+ "provide information Steer Finance vault, stak pool, token-specific liquidity data across multiple chain",
21
+ dynamic: true,
22
+ contexts: ["finance", "crypto", "wallet"],
23
+ contextGate: { anyOf: ["finance", "crypto", "wallet"] },
24
+ cacheStable: false,
25
+ cacheScope: "turn",
26
+ roleGate: { minRole: "USER" },
27
+ get: async (runtime: IAgentRuntime, message: Memory, _state: State) => {
28
+ console.log("šŸš€ STEER_LIQUIDITY provider called");
29
+ console.log("šŸ“ Message content:", message.content.text);
30
+ console.log("šŸ“ŗ Channel type:", message.content.channelType);
31
+ console.log("šŸ”§ Runtime methods available:", {
32
+ getService: !!runtime.getService,
33
+ getCache: !!runtime.getCache,
34
+ getSetting: !!runtime.getSetting,
35
+ });
36
+
37
+ let liquidityInfo = "";
38
+
39
+ try {
40
+ // Get Steer liquidity service with proper type casting
41
+ const steerLiquidityService = runtime.getService(
42
+ "STEER_LIQUIDITY_SERVICE",
43
+ ) as SteerLiquidityService;
44
+ if (!steerLiquidityService) {
45
+ console.log("Steer liquidity service not available");
46
+ return {
47
+ data: {},
48
+ values: {},
49
+ text: "Steer liquidity service not available.",
50
+ };
51
+ }
52
+
53
+ console.log("Steer liquidity service found, generating report...");
54
+
55
+ liquidityInfo += `=== STEER FINANCE LIQUIDITY POOLS REPORT ===\n\n`;
56
+
57
+ // Extract token address and chain from message content
58
+ const content = message.content.text || "";
59
+ console.log("Searching for token address and chain in content:", content);
60
+
61
+ // More flexible regex to catch various formats
62
+ const tokenMatch = content.match(/(0x[a-fA-F0-9]{40})/);
63
+ console.log("Token match result:", tokenMatch);
64
+
65
+ // Also try to find any 0x pattern that might be a token address
66
+ const anyHexMatch = content.match(/(0x[a-fA-F0-9]+)/);
67
+ console.log("Any hex match result:", anyHexMatch);
68
+
69
+ // Extract chain name from content
70
+ const chainMatch = content.match(
71
+ /\b(base|ethereum|mainnet|polygon|arbitrum|optimism)\b/i,
72
+ );
73
+ console.log("Chain match result:", chainMatch);
74
+
75
+ // Map chain names to chain IDs
76
+ const chainNameToId: { [key: string]: number } = {
77
+ ethereum: 1,
78
+ mainnet: 1,
79
+ polygon: 137,
80
+ arbitrum: 42161,
81
+ optimism: 10,
82
+ base: 8453,
83
+ };
84
+
85
+ const targetChainId = chainMatch
86
+ ? chainNameToId[chainMatch[1].toLowerCase()]
87
+ : null;
88
+ console.log("Target chain ID:", targetChainId);
89
+
90
+ // Validate chain if specified
91
+ if (
92
+ targetChainId &&
93
+ chainMatch &&
94
+ !chainNameToId[chainMatch[1].toLowerCase()]
95
+ ) {
96
+ liquidityInfo += `āŒ Unsupported chain: ${chainMatch[1]}\n`;
97
+ liquidityInfo += `Supported chains: ${Object.keys(chainNameToId).join(", ")}\n\n`;
98
+ return {
99
+ data: { steerLiquidity: liquidityInfo },
100
+ values: {},
101
+ text: liquidityInfo,
102
+ };
103
+ }
104
+
105
+ if (tokenMatch) {
106
+ const tokenIdentifier = tokenMatch[1];
107
+ console.log(`Token identifier found: ${tokenIdentifier}`);
108
+
109
+ // Validate token address format
110
+ if (!isValidEthereumAddress(tokenIdentifier)) {
111
+ liquidityInfo += `āŒ Invalid Ethereum address format: ${tokenIdentifier}\n`;
112
+ liquidityInfo += `Ethereum addresses must be exactly 40 hex characters (42 total with 0x prefix).\n\n`;
113
+ liquidityInfo += `Please provide a valid address like:\n`;
114
+ liquidityInfo += `• 0xA0b86a33E6441b8c4C8C1C1B8c4C8C1C1B8c4C8C1B8 (USDC)\n`;
115
+ liquidityInfo += `• 0x6B175474E89094C44Da98b954EedeAC495271d0F (DAI)\n`;
116
+ liquidityInfo += `• 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 (WETH)\n\n`;
117
+ } else {
118
+ // Get token-specific liquidity stats with optional chain filtering
119
+ const tokenStats = await getSteerLiquidityStats(
120
+ steerLiquidityService,
121
+ tokenIdentifier,
122
+ targetChainId,
123
+ );
124
+ liquidityInfo += tokenStats;
125
+
126
+ // Add single-asset deposit information if available
127
+ const depositInfo = await getSingleAssetDepositInfo(
128
+ steerLiquidityService,
129
+ tokenIdentifier,
130
+ targetChainId,
131
+ );
132
+ liquidityInfo += depositInfo;
133
+ }
134
+ } else if (anyHexMatch) {
135
+ // Found a hex pattern but it's not exactly 40 characters
136
+ const foundHex = anyHexMatch[1];
137
+ liquidityInfo += `āš ļø Found potential token address: ${foundHex}\n`;
138
+ liquidityInfo += `āŒ Invalid Ethereum address format: ${foundHex}\n`;
139
+ liquidityInfo += `Ethereum addresses must be exactly 40 hex characters (42 total with 0x prefix).\n\n`;
140
+ liquidityInfo += `Please provide a valid address like:\n`;
141
+ liquidityInfo += `• 0x1234567890123456789012345678901234567890\n`;
142
+ liquidityInfo += `• 0xabcdefabcdefabcdefabcdefabcdefabcdefabcd\n`;
143
+ liquidityInfo += `• 0x9876543210987654321098765432109876543210\n\n`;
144
+ liquidityInfo += `šŸ” Your input "${foundHex}" has ${foundHex.length - 2} hex characters, but needs exactly 40.\n\n`;
145
+ } else {
146
+ // No specific token provided, show protocol overview
147
+ liquidityInfo += `=== STEER FINANCE PROTOCOL OVERVIEW ===\n\n`;
148
+ liquidityInfo += `šŸ” Steer Finance Liquidity Protocol Information\n\n`;
149
+
150
+ // Use testConnection to get basic info without making expensive RPC calls
151
+ const testResults = await steerLiquidityService.testConnection();
152
+
153
+ liquidityInfo += `šŸ“Š Protocol Status:\n`;
154
+ liquidityInfo += ` āœ… Connection: ${testResults.connectionTest ? "Connected" : "Failed"}\n`;
155
+ liquidityInfo += ` 🌐 Supported Chains: ${testResults.supportedChains.map(getChainName).join(", ")}\n`;
156
+ liquidityInfo += ` šŸ“ˆ Available Vaults: ${testResults.vaultCount}\n`;
157
+ liquidityInfo += ` šŸ”’ Available Staking Pools: ${testResults.stakingPoolCount}\n\n`;
158
+
159
+ // Add general Steer Finance protocol info
160
+ liquidityInfo += await getSteerProtocolInfo(steerLiquidityService);
161
+
162
+ // Add usage instructions
163
+ liquidityInfo += `šŸ’” How to use:\n`;
164
+ liquidityInfo += ` • Provide a token address to search for specific liquidity pools\n`;
165
+ liquidityInfo += ` • Optionally specify a chain to filter results (faster)\n`;
166
+ liquidityInfo += ` • Example: "Check Steer Finance pools for 0xA0b86a33E6441b8c4C8C1C1B8c4C8C1C1B8c4C8C1B8 on base"\n`;
167
+ liquidityInfo += ` • Supported chains: ${Object.keys(chainNameToId).join(", ")}\n`;
168
+ liquidityInfo += ` • Visit https://app.steer.finance to view all pools\n\n`;
169
+ }
170
+ } catch (error) {
171
+ console.error("Error in Steer liquidity provider:", error);
172
+ liquidityInfo = `Error generating Steer liquidity report: ${error instanceof Error ? error.message : "Unknown error"}`;
173
+ }
174
+
175
+ const data = {
176
+ steerLiquidity: liquidityInfo,
177
+ };
178
+
179
+ const text = `${liquidityInfo}\n`.slice(0, STEER_LIQUIDITY_TEXT_LIMIT);
180
+
181
+ return {
182
+ data,
183
+ values: {} as Record<string, unknown>,
184
+ text,
185
+ };
186
+ },
187
+ };
188
+
189
+ /**
190
+ * Get Steer Finance liquidity pool statistics for a specific token
191
+ */
192
+ async function getSteerLiquidityStats(
193
+ steerLiquidityService: SteerLiquidityService,
194
+ tokenIdentifier: string,
195
+ targetChainId?: number | null,
196
+ ): Promise<string> {
197
+ let statsInfo = "";
198
+
199
+ try {
200
+ // Add chain filtering info if specified
201
+ if (targetChainId) {
202
+ const chainName = getChainName(targetChainId);
203
+ statsInfo += `šŸ” SEARCHING FOR STEER FINANCE LIQUIDITY POOLS ON ${chainName.toUpperCase()}...\n\n`;
204
+ } else {
205
+ statsInfo += `šŸ” SEARCHING FOR STEER FINANCE LIQUIDITY POOLS...\n\n`;
206
+ }
207
+
208
+ // Get detailed liquidity stats for the token with optional chain filtering
209
+ const tokenStats = await steerLiquidityService.getTokenLiquidityStats(
210
+ tokenIdentifier,
211
+ targetChainId,
212
+ );
213
+
214
+ if (tokenStats.vaults.length > 0 || tokenStats.stakingPools.length > 0) {
215
+ statsInfo += `šŸ“Š FOUND ${tokenStats.vaultCount} VAULTS AND ${tokenStats.stakingPoolCount} STAKING POOLS:\n\n`;
216
+ statsInfo += `Token: ${tokenStats.tokenName}\n`;
217
+ statsInfo += `Total TVL: $${tokenStats.totalTvl.toLocaleString()}\n`;
218
+ statsInfo += `24h Volume: $${tokenStats.totalVolume.toLocaleString()}\n`;
219
+ statsInfo += `APY Range: ${tokenStats.apyRange.min.toFixed(2)}% - ${tokenStats.apyRange.max.toFixed(2)}%\n\n`;
220
+
221
+ // Display vaults
222
+ if (tokenStats.vaults.length > 0) {
223
+ statsInfo += `šŸ¦ VAULTS (${tokenStats.vaults.length}):\n\n`;
224
+ for (const vault of tokenStats.vaults) {
225
+ statsInfo += await getVaultDetails(vault);
226
+ }
227
+ }
228
+
229
+ // Display staking pools
230
+ if (tokenStats.stakingPools.length > 0) {
231
+ statsInfo += `šŸ”’ STAKING POOLS (${tokenStats.stakingPools.length}):\n\n`;
232
+ for (const pool of tokenStats.stakingPools) {
233
+ statsInfo += await getStakingPoolDetails(pool);
234
+ }
235
+ }
236
+
237
+ // Add direct link to Steer app for found strategies
238
+ statsInfo += `šŸ”— **View on Steer Finance:** https://app.steer.finance\n\n`;
239
+ } else {
240
+ statsInfo += `āŒ No Steer Finance liquidity pools found for ${tokenIdentifier}\n\n`;
241
+ statsInfo += `This token may not be part of any active Steer Finance vaults or staking pools.\n`;
242
+ statsInfo += `You can check available pools at: https://app.steer.finance\n`;
243
+ }
244
+
245
+ // Add general Steer Finance protocol info
246
+ statsInfo += await getSteerProtocolInfo(steerLiquidityService);
247
+ } catch (error) {
248
+ console.error("Error getting Steer liquidity stats:", error);
249
+ statsInfo += `āŒ Error fetching liquidity data: ${error instanceof Error ? error.message : "Unknown error"}\n`;
250
+ }
251
+
252
+ return statsInfo;
253
+ }
254
+
255
+ /**
256
+ * Get detailed information about a specific vault
257
+ */
258
+ async function getVaultDetails(vault: SteerVaultDetailInput): Promise<string> {
259
+ let details = `šŸ¦ VAULT: ${vault.address}\n`;
260
+ details += ` šŸ“ˆ Name: ${vault.name}\n`;
261
+ details += ` 🌐 Chain: ${getChainName(vault.chainId)}\n`;
262
+ details += ` šŸ’° TVL: $${vault.tvl.toLocaleString()}\n`;
263
+ details += ` šŸ“Š 24h Volume: $${vault.volume24h.toLocaleString()}\n`;
264
+ details += ` šŸŽÆ APY: ${vault.apy.toFixed(2)}%\n`;
265
+ details += ` šŸ”„ Strategy Type: ${vault.strategyType}\n`;
266
+ details += ` šŸ’ø Fee: ${vault.fee}%\n`;
267
+ details += ` šŸ•’ Created: ${new Date(vault.createdAt).toLocaleDateString()}\n`;
268
+ details += ` āœ… Status: ${vault.isActive ? "Active" : "Inactive"}\n`;
269
+
270
+ // Show full token addresses if available
271
+ if (vault.token0 && vault.token0 !== "Unknown") {
272
+ const token0Address =
273
+ typeof vault.token0 === "string"
274
+ ? vault.token0
275
+ : vault.token0?.address || "Unknown";
276
+ const token0Symbol = getTokenSymbol(token0Address);
277
+ details += ` šŸŖ™ Token0: ${token0Address} (${token0Symbol})\n`;
278
+ } else {
279
+ details += ` šŸŖ™ Token0: Unknown\n`;
280
+ }
281
+
282
+ if (vault.token1 && vault.token1 !== "Unknown") {
283
+ const token1Address =
284
+ typeof vault.token1 === "string"
285
+ ? vault.token1
286
+ : vault.token1?.address || "Unknown";
287
+ const token1Symbol = getTokenSymbol(token1Address);
288
+ details += ` šŸŖ™ Token1: ${token1Address} (${token1Symbol})\n`;
289
+ } else {
290
+ details += ` šŸŖ™ Token1: Unknown\n`;
291
+ }
292
+
293
+ // Display GraphQL enriched data if available
294
+ if (vault.graphqlData) {
295
+ details += `\n šŸ“Š GRAPHQL ENRICHED DATA:\n`;
296
+ details += ` šŸŽÆ Weekly Fee APR: ${vault.graphqlData.weeklyFeeAPR.toFixed(2)}%\n`;
297
+ details += ` šŸŖ™ Token0 Symbol: ${vault.graphqlData.token0Symbol}\n`;
298
+ details += ` šŸŖ™ Token0 Decimals: ${vault.graphqlData.token0Decimals}\n`;
299
+ details += ` šŸŖ™ Token1 Symbol: ${vault.graphqlData.token1Symbol}\n`;
300
+ details += ` šŸŖ™ Token1 Decimals: ${vault.graphqlData.token1Decimals}\n`;
301
+ details += ` šŸ’° Token0 Balance: ${vault.graphqlData.token0Balance}\n`;
302
+ details += ` šŸ’° Token1 Balance: ${vault.graphqlData.token1Balance}\n`;
303
+ details += ` šŸŠ Total LP Tokens: ${vault.graphqlData.totalLPTokensIssued}\n`;
304
+ details += ` šŸ’ø Fee Tier: ${vault.graphqlData.feeTier} (${(vault.graphqlData.feeTier / 10000).toFixed(2)}%)\n`;
305
+ details += ` šŸ’° Fees0: ${vault.graphqlData.fees0}\n`;
306
+ details += ` šŸ’° Fees1: ${vault.graphqlData.fees1}\n`;
307
+
308
+ if (vault.graphqlData.strategyToken) {
309
+ details += ` šŸŽ­ Strategy Token: ${vault.graphqlData.strategyToken.name}\n`;
310
+ details += ` šŸ‘¤ Creator: ${vault.graphqlData.strategyToken.creator.id}\n`;
311
+ details += ` šŸ‘‘ Admin: ${vault.graphqlData.strategyToken.admin}\n`;
312
+ }
313
+
314
+ details += ` šŸ”§ Beacon Name: ${vault.graphqlData.beaconName}\n`;
315
+ details += ` šŸ“ Payload IPFS: ${vault.graphqlData.payloadIpfs}\n`;
316
+ details += ` šŸš€ Deployer: ${vault.graphqlData.deployer}\n`;
317
+
318
+ if (vault.calculatedTvl !== undefined) {
319
+ details += ` šŸ’° Calculated TVL: $${vault.calculatedTvl.toLocaleString()}\n`;
320
+ }
321
+ }
322
+
323
+ if (vault.positions && vault.positions.length > 0) {
324
+ details += ` šŸ“ Positions:\n`;
325
+ for (const position of vault.positions) {
326
+ details += ` • ${position.type}: ${position.range} ($${position.liquidity.toLocaleString()})\n`;
327
+ }
328
+ }
329
+
330
+ details += `\n`;
331
+
332
+ return details;
333
+ }
334
+
335
+ /**
336
+ * Get detailed information about a specific staking pool
337
+ */
338
+ async function getStakingPoolDetails(
339
+ pool: SteerStakingPoolDetailInput,
340
+ ): Promise<string> {
341
+ let details = `šŸ”’ STAKING POOL: ${pool.address}\n`;
342
+ details += ` šŸ“ˆ Name: ${pool.name}\n`;
343
+ details += ` 🌐 Chain: ${getChainName(pool.chainId)}\n`;
344
+ details += ` šŸ’° Total Staked: $${pool.totalStakedUSD.toLocaleString()}\n`;
345
+ details += ` šŸŽÆ APR: ${pool.apr.toFixed(2)}%\n`;
346
+ details += ` šŸŖ™ Staking Token: ${pool.stakingToken}\n`;
347
+ details += ` šŸŽ Reward Token: ${pool.rewardToken}\n`;
348
+ details += ` šŸ“Š Reward Rate: ${pool.rewardRate.toLocaleString()}\n`;
349
+ details += ` šŸ•’ Period Finish: ${new Date(pool.periodFinish).toLocaleDateString()}\n`;
350
+ details += ` āœ… Status: ${pool.isActive ? "Active" : "Inactive"}\n`;
351
+
352
+ details += `\n`;
353
+
354
+ return details;
355
+ }
356
+
357
+ /**
358
+ * Get chain name from chain ID
359
+ */
360
+ function getChainName(chainId: number): string {
361
+ const chainNames: { [key: number]: string } = {
362
+ 1: "Ethereum Mainnet",
363
+ 137: "Polygon",
364
+ 42161: "Arbitrum One",
365
+ 10: "Optimism",
366
+ };
367
+ return chainNames[chainId] || `Chain ${chainId}`;
368
+ }
369
+
370
+ /**
371
+ * Get general Steer Finance protocol information
372
+ */
373
+ async function getSteerProtocolInfo(
374
+ steerLiquidityService: SteerLiquidityService,
375
+ ): Promise<string> {
376
+ let info = `šŸŽÆ STEER FINANCE PROTOCOL INFO:\n\n`;
377
+
378
+ try {
379
+ const testResults = await steerLiquidityService.testConnection();
380
+
381
+ info += `🌐 Supported Chains: ${testResults.supportedChains.map(getChainName).join(", ")}\n`;
382
+ info += `āœ… Connection Status: ${testResults.connectionTest ? "Connected" : "Failed"}\n`;
383
+ info += `šŸ“Š Total Vaults: ${testResults.vaultCount}\n`;
384
+ info += `šŸ”’ Total Staking Pools: ${testResults.stakingPoolCount}\n\n`;
385
+
386
+ // Test GraphQL connection
387
+ const graphqlStatus = await steerLiquidityService.testGraphQLConnection();
388
+ info += `šŸ” GraphQL Subgraph: ${graphqlStatus.success ? "Connected" : "Failed"}\n`;
389
+ if (!graphqlStatus.success && graphqlStatus.error) {
390
+ info += ` āš ļø GraphQL Error: ${graphqlStatus.error}\n`;
391
+ }
392
+ info += `\n`;
393
+
394
+ if (testResults.error) {
395
+ info += `āš ļø Connection Errors: ${testResults.error}\n\n`;
396
+ }
397
+
398
+ info += `šŸ”— Useful Links:\n`;
399
+ info += ` • Steer Finance App: https://app.steer.finance\n`;
400
+ info += ` • Documentation: https://docs.steer.finance\n`;
401
+ info += ` • GitHub: https://github.com/steer-finance\n\n`;
402
+
403
+ info += `šŸ’” How to use:\n`;
404
+ info += ` • Visit the Steer Finance app to view all available vaults and staking pools\n`;
405
+ info += ` • Deposit tokens into vaults to earn yield from automated market making\n`;
406
+ info += ` • Stake tokens in staking pools to earn additional rewards\n`;
407
+ info += ` • Vaults automatically rebalance to maintain optimal positions\n`;
408
+ } catch (error) {
409
+ console.error("Error getting protocol info:", error);
410
+ info += `āŒ Error fetching protocol information\n`;
411
+ }
412
+
413
+ return info;
414
+ }
415
+
416
+ /**
417
+ * Get general Steer Finance overview
418
+ */
419
+ async function _getSteerGeneralOverview(
420
+ steerLiquidityService: SteerLiquidityService,
421
+ ): Promise<string> {
422
+ let overview = "šŸ“Š STEER FINANCE OVERVIEW:\n\n";
423
+
424
+ try {
425
+ const testResults = await steerLiquidityService.testConnection();
426
+
427
+ overview += `🌐 Supported Chains: ${testResults.supportedChains.map(getChainName).join(", ")}\n`;
428
+ overview += `āœ… Connection Status: ${testResults.connectionTest ? "Connected" : "Failed"}\n`;
429
+ overview += `šŸ“Š Total Vaults: ${testResults.vaultCount}\n`;
430
+ overview += `šŸ”’ Total Staking Pools: ${testResults.stakingPoolCount}\n\n`;
431
+
432
+ if (testResults.error) {
433
+ overview += `āš ļø Connection Errors: ${testResults.error}\n\n`;
434
+ }
435
+ } catch (error) {
436
+ console.error("Error getting general overview:", error);
437
+ overview += `āŒ Error fetching general overview\n`;
438
+ }
439
+
440
+ return overview;
441
+ }
442
+
443
+ /**
444
+ * Get single-asset deposit information for a token
445
+ */
446
+ async function getSingleAssetDepositInfo(
447
+ steerLiquidityService: SteerLiquidityService,
448
+ tokenIdentifier: string,
449
+ targetChainId?: number | null,
450
+ ): Promise<string> {
451
+ let depositInfo = "\nšŸ’Ž SINGLE-ASSET DEPOSIT INFORMATION:\n\n";
452
+
453
+ try {
454
+ // Get token stats to find vaults with optional chain filtering
455
+ const tokenStats = await steerLiquidityService.getTokenLiquidityStats(
456
+ tokenIdentifier,
457
+ targetChainId,
458
+ );
459
+
460
+ if (tokenStats.vaults.length === 0) {
461
+ depositInfo += "No vaults found for this token.\n";
462
+ return depositInfo;
463
+ }
464
+
465
+ depositInfo += `Found ${tokenStats.vaults.length} vault(s) supporting single-asset deposits:\n\n`;
466
+
467
+ for (const vault of tokenStats.vaults) {
468
+ if (vault.singleAssetDepositContract) {
469
+ depositInfo += `šŸ¦ Vault: ${vault.name}\n`;
470
+ depositInfo += ` šŸ“ Address: ${vault.address}\n`;
471
+ depositInfo += ` 🌐 Chain: ${getChainName(vault.chainId)}\n`;
472
+ depositInfo += ` šŸ’° TVL: $${vault.tvl.toLocaleString()}\n`;
473
+ depositInfo += ` šŸŽÆ APY: ${vault.apy.toFixed(2)}%\n`;
474
+ depositInfo += ` šŸ”„ Strategy: ${vault.strategyType}\n`;
475
+ depositInfo += ` šŸŠ Pool: ${vault.poolAddress || "N/A"}\n`;
476
+ depositInfo += ` šŸ“ Single-Asset Contract: ${vault.singleAssetDepositContract}\n`;
477
+ depositInfo += ` šŸŖ™ Token0: ${vault.token0} (${getTokenSymbol(typeof vault.token0 === "string" ? vault.token0 : vault.token0?.address || "Unknown")})\n`;
478
+ depositInfo += ` šŸŖ™ Token1: ${vault.token1} (${getTokenSymbol(typeof vault.token1 === "string" ? vault.token1 : vault.token1?.address || "Unknown")})\n`;
479
+
480
+ // Add additional APY breakdown if available
481
+ if (vault.apr1d || vault.apr7d || vault.apr14d) {
482
+ depositInfo += ` šŸ“Š APY Breakdown:\n`;
483
+ if (vault.apr1d)
484
+ depositInfo += ` • 1D: ${vault.apr1d.toFixed(2)}%\n`;
485
+ if (vault.apr7d)
486
+ depositInfo += ` • 7D: ${vault.apr7d.toFixed(2)}%\n`;
487
+ if (vault.apr14d)
488
+ depositInfo += ` • 14D: ${vault.apr14d.toFixed(2)}%\n`;
489
+ }
490
+
491
+ // Add fee breakdown if available
492
+ if (vault.feeApr || vault.stakingApr || vault.merklApr) {
493
+ depositInfo += ` šŸ’ø Fee Breakdown:\n`;
494
+ if (vault.feeApr)
495
+ depositInfo += ` • Fee APY: ${vault.feeApr.toFixed(2)}%\n`;
496
+ if (vault.stakingApr)
497
+ depositInfo += ` • Staking APY: ${vault.stakingApr.toFixed(2)}%\n`;
498
+ if (vault.merklApr)
499
+ depositInfo += ` • Merkl APY: ${vault.merklApr.toFixed(2)}%\n`;
500
+ }
501
+ depositInfo += `\n`;
502
+
503
+ depositInfo += ` šŸ’” Single-Asset Deposit Features:\n`;
504
+ depositInfo += ` • Deposit only one token (${tokenIdentifier === vault.token0.toLowerCase() ? "Token0" : "Token1"})\n`;
505
+ depositInfo += ` • Automatic internal swap to balance the pair\n`;
506
+ depositInfo += ` • Configurable slippage protection\n`;
507
+ depositInfo += ` • Preview functionality before execution\n`;
508
+ depositInfo += ` • UniswapV3 AMM support\n\n`;
509
+ }
510
+ }
511
+
512
+ depositInfo += `šŸ”— To use single-asset deposits:\n`;
513
+ depositInfo += ` • Visit https://app.steer.finance\n`;
514
+ depositInfo += ` • Select a vault that supports single-asset deposits\n`;
515
+ depositInfo += ` • Choose your token and amount\n`;
516
+ depositInfo += ` • Preview the transaction before executing\n\n`;
517
+ } catch (error) {
518
+ console.error("Error getting single-asset deposit info:", error);
519
+ depositInfo += `āŒ Error fetching single-asset deposit information\n`;
520
+ }
521
+
522
+ return depositInfo;
523
+ }
524
+
525
+ /**
526
+ * Validate Ethereum address format
527
+ */
528
+ function isValidEthereumAddress(address: string): boolean {
529
+ // Check if it starts with 0x and has exactly 40 hex characters
530
+ const ethereumAddressRegex = /^0x[a-fA-F0-9]{40}$/;
531
+ return ethereumAddressRegex.test(address);
532
+ }
533
+
534
+ /**
535
+ * Get token symbol from token address
536
+ */
537
+ function getTokenSymbol(address: string): string {
538
+ if (!address || address === "Unknown") {
539
+ return "Unknown";
540
+ }
541
+
542
+ // Return shortened address for all tokens
543
+ return `${address.slice(0, 6)}...${address.slice(-4)}`;
544
+ }