@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,250 @@
1
+ import type { Chain, Hex } from "viem";
2
+ import {
3
+ type Address,
4
+ encodeFunctionData,
5
+ keccak256,
6
+ stringToHex,
7
+ } from "viem";
8
+ import governorArtifacts from "./contracts/artifacts/OZGovernor.json";
9
+ import { buildSendTxParams } from "./actions/helpers";
10
+ import { initWalletProvider, type WalletProvider } from "./providers/wallet";
11
+ import type {
12
+ WalletRouterContext,
13
+ WalletRouterExecution,
14
+ WalletRouterParams,
15
+ } from "../../types/wallet-router.js";
16
+ import type { SupportedChain } from "./types";
17
+
18
+ function isEvmAddress(value: string | undefined): value is Address {
19
+ return typeof value === "string" && /^0x[a-fA-F0-9]{40}$/.test(value);
20
+ }
21
+
22
+ function requireGovernor(params: WalletRouterParams): Address {
23
+ if (!isEvmAddress(params.governor)) {
24
+ throw new Error("governor must be a valid EVM address.");
25
+ }
26
+ return params.governor;
27
+ }
28
+
29
+ function requireArray(
30
+ params: WalletRouterParams,
31
+ key: "targets" | "values" | "calldatas",
32
+ ): readonly string[] {
33
+ const value = params[key];
34
+ if (!value || value.length === 0) {
35
+ throw new Error(`${key} is required for governance ${params.op}.`);
36
+ }
37
+ return value;
38
+ }
39
+
40
+ function requireDescription(params: WalletRouterParams): string {
41
+ if (!params.description) {
42
+ throw new Error(`description is required for governance ${params.op}.`);
43
+ }
44
+ return params.description;
45
+ }
46
+
47
+ function requireProposalId(params: WalletRouterParams): string {
48
+ if (!params.proposalId) {
49
+ throw new Error(`proposalId is required for governance ${params.op}.`);
50
+ }
51
+ return params.proposalId;
52
+ }
53
+
54
+ function asAddressArray(values: readonly string[], key: string): Address[] {
55
+ return values.map((value) => {
56
+ if (!isEvmAddress(value)) {
57
+ throw new Error(`${key} must contain only valid EVM addresses.`);
58
+ }
59
+ return value;
60
+ });
61
+ }
62
+
63
+ function asHexArray(values: readonly string[], key: string): Hex[] {
64
+ return values.map((value) => {
65
+ if (!/^0x[0-9a-fA-F]*$/.test(value)) {
66
+ throw new Error(`${key} must contain only hex calldata values.`);
67
+ }
68
+ return value as Hex;
69
+ });
70
+ }
71
+
72
+ function asBigIntArray(values: readonly string[]): bigint[] {
73
+ return values.map((value) => BigInt(value));
74
+ }
75
+
76
+ function descriptionHash(description: string): Hex {
77
+ return keccak256(stringToHex(description));
78
+ }
79
+
80
+ export function validateWalletGovParams(
81
+ params: WalletRouterParams,
82
+ ): string | null {
83
+ try {
84
+ if (!params.op) {
85
+ return "op is required for governance actions.";
86
+ }
87
+ requireGovernor(params);
88
+ switch (params.op) {
89
+ case "propose":
90
+ requireArray(params, "targets");
91
+ requireArray(params, "values");
92
+ requireArray(params, "calldatas");
93
+ requireDescription(params);
94
+ break;
95
+ case "vote":
96
+ requireProposalId(params);
97
+ if (params.support === undefined) {
98
+ return "support is required for governance vote.";
99
+ }
100
+ break;
101
+ case "queue":
102
+ requireArray(params, "targets");
103
+ requireArray(params, "values");
104
+ requireArray(params, "calldatas");
105
+ requireDescription(params);
106
+ break;
107
+ case "execute":
108
+ requireProposalId(params);
109
+ requireArray(params, "targets");
110
+ requireArray(params, "values");
111
+ requireArray(params, "calldatas");
112
+ requireDescription(params);
113
+ break;
114
+ }
115
+ return null;
116
+ } catch (error) {
117
+ return error instanceof Error ? error.message : String(error);
118
+ }
119
+ }
120
+
121
+ export function encodeWalletGovData(params: WalletRouterParams): Hex {
122
+ const governor = requireGovernor(params);
123
+ void governor;
124
+
125
+ switch (params.op) {
126
+ case "propose":
127
+ return encodeFunctionData({
128
+ abi: governorArtifacts.abi,
129
+ functionName: "propose",
130
+ args: [
131
+ asAddressArray(requireArray(params, "targets"), "targets"),
132
+ asBigIntArray(requireArray(params, "values")),
133
+ asHexArray(requireArray(params, "calldatas"), "calldatas"),
134
+ requireDescription(params),
135
+ ],
136
+ }) as Hex;
137
+ case "vote":
138
+ return encodeFunctionData({
139
+ abi: governorArtifacts.abi,
140
+ functionName: "castVote",
141
+ args: [BigInt(requireProposalId(params)), BigInt(params.support ?? 0)],
142
+ }) as Hex;
143
+ case "queue": {
144
+ const description = requireDescription(params);
145
+ return encodeFunctionData({
146
+ abi: governorArtifacts.abi,
147
+ functionName: "queue",
148
+ args: [
149
+ asAddressArray(requireArray(params, "targets"), "targets"),
150
+ asBigIntArray(requireArray(params, "values")),
151
+ asHexArray(requireArray(params, "calldatas"), "calldatas"),
152
+ descriptionHash(description),
153
+ ],
154
+ }) as Hex;
155
+ }
156
+ case "execute": {
157
+ requireProposalId(params);
158
+ const description = requireDescription(params);
159
+ return encodeFunctionData({
160
+ abi: governorArtifacts.abi,
161
+ functionName: "execute",
162
+ args: [
163
+ asAddressArray(requireArray(params, "targets"), "targets"),
164
+ asBigIntArray(requireArray(params, "values")),
165
+ asHexArray(requireArray(params, "calldatas"), "calldatas"),
166
+ descriptionHash(description),
167
+ ],
168
+ }) as Hex;
169
+ }
170
+ default:
171
+ throw new Error(
172
+ "Missing or invalid op (expected propose | vote | queue | execute).",
173
+ );
174
+ }
175
+ }
176
+
177
+ export async function routeEvmGovernance(
178
+ params: WalletRouterParams,
179
+ context: WalletRouterContext,
180
+ chainKey: string,
181
+ chain: Chain,
182
+ walletProvider?: WalletProvider,
183
+ ): Promise<WalletRouterExecution> {
184
+ const governor = requireGovernor(params);
185
+ const data = encodeWalletGovData(params);
186
+
187
+ if (params.mode === "prepare" || params.dryRun) {
188
+ return {
189
+ status: "prepared",
190
+ chain: chainKey,
191
+ chainId: String(chain.id),
192
+ subaction: "gov",
193
+ dryRun: params.dryRun,
194
+ mode: params.mode,
195
+ to: governor,
196
+ metadata: {
197
+ op: params.op,
198
+ governor,
199
+ proposalId: params.proposalId,
200
+ support: params.support,
201
+ targets: params.targets,
202
+ values: params.values,
203
+ calldatas: params.calldatas,
204
+ description: params.description,
205
+ transactionRequest: {
206
+ to: governor,
207
+ value: "0",
208
+ data,
209
+ chainId: chain.id,
210
+ },
211
+ requiresConfirmation: true,
212
+ },
213
+ };
214
+ }
215
+
216
+ const provider = walletProvider ?? (await initWalletProvider(context.runtime));
217
+ const walletClient = provider.getWalletClient(chainKey as SupportedChain);
218
+ const account = walletClient.account;
219
+ if (!account) {
220
+ throw new Error("Wallet account is not available.");
221
+ }
222
+
223
+ const hash = await walletClient.sendTransaction(
224
+ buildSendTxParams({
225
+ account,
226
+ to: governor,
227
+ value: 0n,
228
+ data,
229
+ chain,
230
+ }),
231
+ );
232
+
233
+ return {
234
+ status: "submitted",
235
+ chain: chainKey,
236
+ chainId: String(chain.id),
237
+ subaction: "gov",
238
+ dryRun: false,
239
+ mode: params.mode,
240
+ transactionHash: hash,
241
+ from: account.address,
242
+ to: governor,
243
+ metadata: {
244
+ op: params.op,
245
+ proposalId: params.proposalId,
246
+ support: params.support,
247
+ data,
248
+ },
249
+ };
250
+ }
@@ -0,0 +1,16 @@
1
+ import type { IAgentRuntime, Plugin } from "@elizaos/core";
2
+ import { logger } from "@elizaos/core";
3
+
4
+ const pluginName = "evm";
5
+
6
+ export const evmPlugin: Plugin = {
7
+ name: pluginName,
8
+ description: "EVM plugin (browser stub; use a server proxy)",
9
+ async init(_config, _runtime: IAgentRuntime): Promise<void> {
10
+ logger.warn(
11
+ `[plugin-${pluginName}] This plugin is not supported directly in browsers. Use a server proxy.`
12
+ );
13
+ },
14
+ };
15
+
16
+ export default evmPlugin;
@@ -0,0 +1,31 @@
1
+ import type { Action, Plugin, ServiceClass } from "@elizaos/core";
2
+ import { promoteSubactionsToActions } from "@elizaos/core";
3
+ import { walletRouterAction } from "../wallet-action";
4
+ import { tokenBalanceProvider } from "./providers/get-balance";
5
+ import { evmWalletProvider } from "./providers/wallet";
6
+ import { evmSignRoutes } from "./routes/sign";
7
+ import { EVMService } from "./service";
8
+
9
+ export {
10
+ createEvmWalletChainHandler,
11
+ type EvmExecutedTransaction,
12
+ type EvmPreparedResult,
13
+ type EvmRouterResult,
14
+ EvmWalletChainHandler,
15
+ type EvmWalletChainHandlerOptions,
16
+ type EvmWalletMode,
17
+ type EvmWalletSubaction,
18
+ } from "./chain-handler";
19
+ export { initWalletProvider, WalletProvider } from "./providers/wallet";
20
+ export type { SupportedChain } from "./types";
21
+
22
+ export const evmPlugin: Plugin = {
23
+ name: "evm",
24
+ description: "EVM blockchain integration plugin",
25
+ providers: [evmWalletProvider, tokenBalanceProvider],
26
+ services: [EVMService] as ServiceClass[],
27
+ actions: promoteSubactionsToActions(walletRouterAction as Action) as Action[],
28
+ routes: evmSignRoutes,
29
+ };
30
+
31
+ export default evmPlugin;
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Prompt templates for plugin-wallet EVM actions and providers.
3
+ *
4
+ * These prompts use Handlebars-style template syntax:
5
+ * - {{variableName}} for simple substitution
6
+ * - {{#each items}}...{{/each}} for iteration
7
+ * - {{#if condition}}...{{/if}} for conditionals
8
+ */
9
+
10
+ export const bridgeTemplate = `Given the recent messages and wallet information below:
11
+
12
+ {{recentMessages}}
13
+
14
+ {{chainBalances}}
15
+
16
+ Extract the following information about the requested token bridge:
17
+ - Token symbol or address to bridge
18
+ - Source chain
19
+ - Destination chain
20
+ - Amount to bridge: Must be a string representing the amount in ether (only number without coin symbol, e.g., "0.1")
21
+ - Destination address (if specified)
22
+
23
+ Respond using plain key/value text like this:
24
+ token: token symbol or address, or empty if unknown
25
+ fromChain: source chain from {{supportedChains}}, or empty
26
+ toChain: destination chain from {{supportedChains}}, or empty
27
+ amount: amount as string (e.g. 0.1), or empty
28
+ toAddress: destination address, or empty
29
+
30
+ IMPORTANT: Your response must ONLY contain the key/value fields above. No preamble or explanation.`;
31
+
32
+ export const BRIDGE_TEMPLATE = bridgeTemplate;
33
+
34
+ export const executeProposalTemplate = `Given the recent messages and wallet information below:
35
+
36
+ {{recentMessages}}
37
+
38
+ {{walletInfo}}
39
+
40
+ Extract the following information about the requested proposal:
41
+ - Targets
42
+ - Values
43
+ - Calldatas
44
+ - Description
45
+ - Governor address
46
+ - Chain to execute on
47
+
48
+ Respond using plain key/value text like this. Use null for any scalar value that cannot be determined, and use empty arrays when no array values can be determined:
49
+ targets[2]: 0xTargetAddress1,0xTargetAddress2
50
+ values[2]: 0,1000000000000000000
51
+ calldatas[2]: 0xCalldata1,0xCalldata2
52
+ description: proposal description, or null
53
+ governor: governor contract address, or null
54
+ chain: chain to execute on, or null
55
+
56
+ IMPORTANT: Your response must ONLY contain the key/value fields above. No preamble or explanation.`;
57
+
58
+ export const EXECUTE_PROPOSAL_TEMPLATE = executeProposalTemplate;
59
+
60
+ export const proposeTemplate = `Given the recent messages and wallet information below:
61
+
62
+ {{recentMessages}}
63
+
64
+ {{walletInfo}}
65
+
66
+ Extract the following information about the requested proposal:
67
+ - Targets
68
+ - Values
69
+ - Calldatas
70
+ - Description
71
+ - Governor address
72
+ - Chain to execute on
73
+
74
+ Respond using plain key/value text like this. Use null for any scalar value that cannot be determined, and use empty arrays when no array values can be determined:
75
+ targets[2]: 0xTargetAddress1,0xTargetAddress2
76
+ values[2]: 0,1000000000000000000
77
+ calldatas[2]: 0xCalldata1,0xCalldata2
78
+ description: proposal description, or null
79
+ governor: governor contract address, or null
80
+ chain: chain to execute on, or null
81
+
82
+ IMPORTANT: Your response must ONLY contain the key/value fields above. No preamble or explanation.`;
83
+
84
+ export const PROPOSE_TEMPLATE = proposeTemplate;
85
+
86
+ export const queueProposalTemplate = `Given the recent messages and wallet information below:
87
+
88
+ {{recentMessages}}
89
+
90
+ {{walletInfo}}
91
+
92
+ Extract the following information about the requested proposal:
93
+ - Targets
94
+ - Values
95
+ - Calldatas
96
+ - Description
97
+ - Governor address
98
+ - Chain to execute on
99
+
100
+ Respond using plain key/value text like this. Use null for any scalar value that cannot be determined, and use empty arrays when no array values can be determined:
101
+ targets[2]: 0xTargetAddress1,0xTargetAddress2
102
+ values[2]: 0,1000000000000000000
103
+ calldatas[2]: 0xCalldata1,0xCalldata2
104
+ description: proposal description, or null
105
+ governor: governor contract address, or null
106
+ chain: chain to execute on, or null
107
+
108
+ IMPORTANT: Your response must ONLY contain the key/value fields above. No preamble or explanation.`;
109
+
110
+ export const QUEUE_PROPOSAL_TEMPLATE = queueProposalTemplate;
111
+
112
+ export const swapTemplate = `Given the recent messages and wallet information below:
113
+
114
+ {{recentMessages}}
115
+
116
+ {{chainBalances}}
117
+
118
+ Extract the following information about the requested token swap:
119
+ - Input token symbol or address (the token being sold)
120
+ - Output token symbol or address (the token being bought)
121
+ - Amount to swap: Must be a string representing the amount in ether (only number without coin symbol, e.g., "0.1")
122
+ - Chain to execute on
123
+
124
+ Respond using plain key/value text like this:
125
+ inputToken: token symbol or address being sold, or empty
126
+ outputToken: token symbol or address being bought, or empty
127
+ amount: amount as string (e.g. 0.1), or empty
128
+ chain: chain from {{supportedChains}}, or empty
129
+
130
+ IMPORTANT: Your response must ONLY contain the key/value fields above. No preamble or explanation.`;
131
+
132
+ export const SWAP_TEMPLATE = swapTemplate;
133
+
134
+ export const tokenBalanceTemplate = `Extract the token ticker and blockchain from the user's message.
135
+
136
+ User message: "{{userMessage}}"
137
+
138
+ Respond using plain key/value text like this:
139
+ token: TOKEN_SYMBOL
140
+ chain: CHAIN_NAME
141
+
142
+ If no token is mentioned or it's not a balance inquiry, return:
143
+ error: Not a token balance request
144
+
145
+ IMPORTANT: Your response must ONLY contain the key/value fields above. No preamble or explanation.`;
146
+
147
+ export const TOKEN_BALANCE_TEMPLATE = tokenBalanceTemplate;
148
+
149
+ export const transferTemplate = `Given the recent messages and wallet information below:
150
+
151
+ {{recentMessages}}
152
+
153
+ {{chainBalances}}
154
+
155
+ Extract the following information about the requested token transfer:
156
+ - Chain to execute on (must be one of the supported chains)
157
+ - Amount to transfer (only number without coin symbol, e.g., "0.1")
158
+ - Recipient address (must be a valid Ethereum address)
159
+ - Token symbol or address (if not a native token transfer)
160
+ - Additional data/calldata (if any is included)
161
+
162
+ Respond using plain key/value text like this:
163
+ fromChain: chain from {{supportedChains}}, or empty
164
+ amount: amount as string (e.g. 0.1), or empty
165
+ toAddress: recipient Ethereum address, or empty
166
+ token: token symbol or address (empty for native transfer)
167
+ data: additional calldata hex string, or empty
168
+
169
+ IMPORTANT: Your response must ONLY contain the key/value fields above. No preamble or explanation.`;
170
+
171
+ export const TRANSFER_TEMPLATE = transferTemplate;
172
+
173
+ export const voteTemplate = `Given the recent messages and wallet information below:
174
+
175
+ {{recentMessages}}
176
+
177
+ {{walletInfo}}
178
+
179
+ Extract the following information about the requested vote:
180
+ - Proposal ID
181
+ - Support (0 for against, 1 for yes, 2 for abstain)
182
+ - Governor address
183
+ - Chain to execute on
184
+
185
+ Respond using plain key/value text like this. Use null for any value that cannot be determined:
186
+ proposalId: proposal ID, or null
187
+ support: 0 for against, 1 for yes, 2 for abstain, or null
188
+ governor: governor contract address, or null
189
+ chain: chain to execute on, or null
190
+
191
+ IMPORTANT: Your response must ONLY contain the key/value fields above. No preamble or explanation.`;
192
+
193
+ export const VOTE_TEMPLATE = voteTemplate;
@@ -0,0 +1,123 @@
1
+ import {
2
+ type IAgentRuntime,
3
+ type Memory,
4
+ ModelType,
5
+ type Provider,
6
+ type ProviderResult,
7
+ parseJSONObjectFromText,
8
+ } from "@elizaos/core";
9
+ import { getToken } from "@lifi/sdk";
10
+ import { type Address, formatUnits, parseAbi } from "viem";
11
+ import { runIntentModel } from "../../../utils/intent-trajectory";
12
+ import { requireProviderSpec } from "../generated/specs/spec-helpers";
13
+ import { tokenBalanceTemplate } from "../prompts";
14
+ import { EVMError, EVMErrorCode, type SupportedChain } from "../types";
15
+ import { initWalletProvider } from "./wallet";
16
+
17
+ const spec = requireProviderSpec("get-balance");
18
+
19
+ export const tokenBalanceProvider: Provider = {
20
+ name: spec.name,
21
+ description: "Token balance for ERC20 tokens when onchain actions are requested",
22
+ descriptionCompressed: "ERC20 token balance for onchain actions.",
23
+ contexts: ["finance", "crypto", "wallet"],
24
+ contextGate: { anyOf: ["finance", "crypto", "wallet"] },
25
+ cacheStable: false,
26
+ cacheScope: "turn",
27
+ roleGate: { minRole: "OWNER" },
28
+ dynamic: true,
29
+ get: async (runtime: IAgentRuntime, message: Memory): Promise<ProviderResult> => {
30
+ const inputText =
31
+ typeof message.content === "string"
32
+ ? message.content
33
+ : typeof message.content?.text === "string"
34
+ ? message.content.text
35
+ : "";
36
+ const normalizedText = inputText.toLowerCase();
37
+ const keywordMatch =
38
+ normalizedText.includes("balance") ||
39
+ normalizedText.includes("token") ||
40
+ normalizedText.includes("erc20") ||
41
+ normalizedText.includes("wallet");
42
+ const regexMatch = /\b(?:balance|token|erc20|wallet|chain)\b/i.test(inputText);
43
+ if (!keywordMatch || !regexMatch) {
44
+ return { text: "", data: {}, values: {} };
45
+ }
46
+
47
+ try {
48
+ const prompt = tokenBalanceTemplate.replace("{{userMessage}}", inputText);
49
+
50
+ const response = await runIntentModel({
51
+ runtime,
52
+ taskName: "evm.token-balance.intent",
53
+ purpose: "provider",
54
+ template: prompt,
55
+ modelType: ModelType.TEXT_SMALL,
56
+ maxTokens: 100,
57
+ });
58
+
59
+ const parsed = parseJSONObjectFromText(response) as Record<string, unknown> | null;
60
+
61
+ if (!parsed || parsed.error || !parsed.token || !parsed.chain) {
62
+ return { text: "", data: {}, values: {} };
63
+ }
64
+
65
+ const token = String(parsed.token).toUpperCase();
66
+ const chain = String(parsed.chain).toLowerCase();
67
+
68
+ const walletProvider = await initWalletProvider(runtime);
69
+
70
+ if (!walletProvider.chains[chain]) {
71
+ throw new EVMError(EVMErrorCode.CHAIN_NOT_CONFIGURED, `Chain ${chain} is not configured`);
72
+ }
73
+
74
+ const chainConfig = walletProvider.getChainConfigs(chain as SupportedChain);
75
+ const address = walletProvider.getAddress();
76
+ const tokenData = await getToken(chainConfig.id, token);
77
+ const publicClient = walletProvider.getPublicClient(chain as SupportedChain);
78
+ const balanceAbi = parseAbi(["function balanceOf(address) view returns (uint256)"]);
79
+
80
+ const balance = BigInt(
81
+ await publicClient.readContract({
82
+ address: tokenData.address as Address,
83
+ abi: balanceAbi,
84
+ functionName: "balanceOf",
85
+ args: [address],
86
+ authorizationList: undefined,
87
+ })
88
+ );
89
+
90
+ const formattedBalance = formatUnits(balance, tokenData.decimals);
91
+ const hasBalance = parseFloat(formattedBalance) > 0;
92
+
93
+ return {
94
+ text: `${token} balance on ${chain} for ${address}: ${formattedBalance}`,
95
+ data: {
96
+ token: tokenData.symbol,
97
+ chain,
98
+ balance: formattedBalance,
99
+ decimals: tokenData.decimals,
100
+ address: tokenData.address,
101
+ hasBalance,
102
+ },
103
+ values: {
104
+ token: tokenData.symbol,
105
+ chain,
106
+ balance: formattedBalance,
107
+ hasBalance: String(hasBalance),
108
+ },
109
+ };
110
+ } catch (error) {
111
+ return {
112
+ text: `Token balance unavailable: ${
113
+ error instanceof Error ? error.message : String(error)
114
+ }`,
115
+ data: {},
116
+ values: {
117
+ tokenBalanceAvailable: false,
118
+ tokenBalanceError: error instanceof Error ? error.name : "TokenBalanceProviderError",
119
+ },
120
+ };
121
+ }
122
+ },
123
+ };