@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,533 @@
1
+ import type {
2
+ Action,
3
+ ActionResult,
4
+ HandlerCallback,
5
+ HandlerOptions,
6
+ IAgentRuntime,
7
+ Memory,
8
+ ProviderDataRecord,
9
+ ProviderValue,
10
+ State,
11
+ } from "@elizaos/core";
12
+ import {
13
+ WALLET_BACKEND_SERVICE_TYPE,
14
+ type WalletBackendService,
15
+ } from "../services/wallet-backend-service.js";
16
+ import type {
17
+ WalletRouterFailure,
18
+ WalletRouterParams,
19
+ WalletRouterResult,
20
+ WalletRouterSubaction,
21
+ } from "../types/wallet-router.js";
22
+ import {
23
+ isWalletRouterSubaction,
24
+ parseWalletRouterParams,
25
+ } from "../types/wallet-router.js";
26
+
27
+ const LEGACY_SWAP_ACTIONS = new Set([
28
+ "SWAP",
29
+ "SWAP_SOLANA",
30
+ "WALLET_SWAP",
31
+ "TOKEN_SWAP",
32
+ ]);
33
+
34
+ const LEGACY_TRANSFER_ACTIONS = new Set([
35
+ "TRANSFER",
36
+ "TRANSFER_TOKEN",
37
+ "WALLET_TRANSFER",
38
+ "SEND_TOKENS",
39
+ "PREPARE_TRANSFER",
40
+ ]);
41
+
42
+ const LEGACY_BRIDGE_ACTIONS = new Set(["CROSS_CHAIN_TRANSFER"]);
43
+ const LEGACY_GOV_ACTIONS = new Set(["WALLET_GOV", "WALLET_GOV"]);
44
+ const GOV_OPS = new Set(["propose", "vote", "queue", "execute"]);
45
+
46
+ function selectedContextMatches(
47
+ state: State | undefined,
48
+ contexts: readonly string[],
49
+ ): boolean {
50
+ const selected = new Set<string>();
51
+ const collect = (value: unknown) => {
52
+ if (!Array.isArray(value)) return;
53
+ for (const item of value) {
54
+ if (typeof item === "string") selected.add(item);
55
+ }
56
+ };
57
+ collect(
58
+ (state?.values as Record<string, unknown> | undefined)?.selectedContexts,
59
+ );
60
+ collect(
61
+ (state?.data as Record<string, unknown> | undefined)?.selectedContexts,
62
+ );
63
+ const contextObject = (state?.data as Record<string, unknown> | undefined)
64
+ ?.contextObject as
65
+ | {
66
+ trajectoryPrefix?: { selectedContexts?: unknown };
67
+ metadata?: { selectedContexts?: unknown };
68
+ }
69
+ | undefined;
70
+ collect(contextObject?.trajectoryPrefix?.selectedContexts);
71
+ collect(contextObject?.metadata?.selectedContexts);
72
+ return contexts.some((context) => selected.has(context));
73
+ }
74
+
75
+ function objectRecord(value: unknown): Record<string, unknown> | null {
76
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
77
+ return null;
78
+ }
79
+ return value as Record<string, unknown>;
80
+ }
81
+
82
+ function legacySubaction(value: unknown): WalletRouterSubaction | undefined {
83
+ if (typeof value !== "string") return undefined;
84
+ const upper = value.toUpperCase();
85
+ if (LEGACY_SWAP_ACTIONS.has(upper)) return "swap";
86
+ if (LEGACY_TRANSFER_ACTIONS.has(upper)) {
87
+ return "transfer";
88
+ }
89
+ if (LEGACY_BRIDGE_ACTIONS.has(upper)) return "bridge";
90
+ if (LEGACY_GOV_ACTIONS.has(upper)) return "gov";
91
+ return undefined;
92
+ }
93
+
94
+ function normalizedGovOp(value: unknown): string | undefined {
95
+ if (typeof value !== "string") return undefined;
96
+ const normalized = value.trim().toLowerCase();
97
+ return GOV_OPS.has(normalized) ? normalized : undefined;
98
+ }
99
+
100
+ function normalizeRawParams(
101
+ raw: Record<string, unknown>,
102
+ ): Record<string, unknown> {
103
+ const action = raw.action ?? raw.name;
104
+ const op = normalizedGovOp(raw.op ?? raw.govOp);
105
+ return {
106
+ subaction:
107
+ raw.subaction ??
108
+ raw.operation ??
109
+ raw.actionType ??
110
+ (op ? "gov" : undefined) ??
111
+ legacySubaction(action),
112
+ chain: raw.chain ?? raw.fromChain ?? raw.network,
113
+ toChain:
114
+ raw.toChain ?? raw.toNetwork ?? raw.destinationChain ?? raw.targetChain,
115
+ fromToken:
116
+ raw.fromToken ??
117
+ raw.inputToken ??
118
+ raw.inputTokenCA ??
119
+ raw.inputTokenSymbol ??
120
+ raw.token ??
121
+ raw.tokenAddress,
122
+ toToken:
123
+ raw.toToken ??
124
+ raw.outputToken ??
125
+ raw.outputTokenCA ??
126
+ raw.outputTokenSymbol,
127
+ amount: raw.amount,
128
+ recipient: raw.recipient ?? raw.toAddress ?? raw.to,
129
+ slippageBps: raw.slippageBps ?? raw.slippage,
130
+ mode: raw.mode ?? (raw.confirmed === true ? "execute" : undefined),
131
+ dryRun: raw.dryRun ?? raw.dry_run,
132
+ op,
133
+ governor: raw.governor,
134
+ proposalId: raw.proposalId,
135
+ support: raw.support,
136
+ targets: raw.targets,
137
+ values: raw.values,
138
+ calldatas: raw.calldatas,
139
+ description: raw.description,
140
+ };
141
+ }
142
+
143
+ function extractRawParams(
144
+ message: Memory,
145
+ state?: State,
146
+ options?: HandlerOptions | Record<string, unknown>,
147
+ ): Record<string, unknown> | null {
148
+ const optionRecord = objectRecord(options);
149
+ const optionParams = objectRecord(optionRecord?.parameters);
150
+ if (optionParams) return optionParams;
151
+
152
+ if (
153
+ optionRecord &&
154
+ ("subaction" in optionRecord || "action" in optionRecord)
155
+ ) {
156
+ return optionRecord;
157
+ }
158
+
159
+ const stateRecord = objectRecord(state);
160
+ const stateParams =
161
+ objectRecord(stateRecord?.walletRouterParams) ??
162
+ objectRecord(stateRecord?.walletCanonicalParams);
163
+ if (stateParams) return stateParams;
164
+
165
+ return objectRecord(message.content);
166
+ }
167
+
168
+ function toProviderValue(value: unknown): ProviderValue {
169
+ if (typeof value === "bigint") {
170
+ return value.toString();
171
+ }
172
+ if (value === undefined) {
173
+ return undefined;
174
+ }
175
+ if (
176
+ value === null ||
177
+ typeof value === "string" ||
178
+ typeof value === "number" ||
179
+ typeof value === "boolean"
180
+ ) {
181
+ return value;
182
+ }
183
+ if (Array.isArray(value)) {
184
+ return value.map((item) => toProviderValue(item));
185
+ }
186
+ if (typeof value === "object") {
187
+ return Object.fromEntries(
188
+ Object.entries(value as Record<string, unknown>).map(([key, item]) => [
189
+ key,
190
+ toProviderValue(item),
191
+ ]),
192
+ );
193
+ }
194
+ return String(value);
195
+ }
196
+
197
+ function toProviderRecord(value: unknown): ProviderDataRecord {
198
+ const converted = toProviderValue(value);
199
+ return converted && typeof converted === "object" && !Array.isArray(converted)
200
+ ? (converted as ProviderDataRecord)
201
+ : { value: converted };
202
+ }
203
+
204
+ function formatFailure(failure: WalletRouterFailure): string {
205
+ if (failure.error === "AMBIGUOUS_CHAIN" && failure.candidates?.length) {
206
+ const chains = failure.candidates
207
+ .map((candidate) => `${candidate.chain} (${candidate.name})`)
208
+ .join(", ");
209
+ return `${failure.detail} Available chains: ${chains}.`;
210
+ }
211
+ if (failure.error === "UNSUPPORTED_CHAIN" && failure.candidates?.length) {
212
+ const chains = failure.candidates
213
+ .map((candidate) => candidate.chain)
214
+ .join(", ");
215
+ return `${failure.detail} Supported chains: ${chains}.`;
216
+ }
217
+ return failure.detail;
218
+ }
219
+
220
+ function resultText(result: WalletRouterResult): string {
221
+ if (!result.ok) {
222
+ return formatFailure(result);
223
+ }
224
+ const execution = result.result;
225
+ if (execution.status === "prepared") {
226
+ const dryRunText = execution.dryRun ? "Dry run prepared" : "Prepared";
227
+ return `${dryRunText} ${execution.subaction} on ${result.handler.chain}.`;
228
+ }
229
+ const id = execution.transactionHash ?? execution.signature;
230
+ return `Submitted ${execution.subaction} on ${result.handler.chain}${id ? `: ${id}` : "."}`;
231
+ }
232
+
233
+ function serviceFromRuntime(
234
+ runtime: IAgentRuntime,
235
+ ): WalletBackendService | null {
236
+ const service = runtime.getService(WALLET_BACKEND_SERVICE_TYPE);
237
+ if (
238
+ service &&
239
+ typeof (service as WalletBackendService).routeWalletAction === "function"
240
+ ) {
241
+ return service as WalletBackendService;
242
+ }
243
+ return null;
244
+ }
245
+
246
+ async function parseParams(
247
+ message: Memory,
248
+ state?: State,
249
+ options?: HandlerOptions | Record<string, unknown>,
250
+ ): Promise<WalletRouterParams> {
251
+ const raw = extractRawParams(message, state, options);
252
+ return parseWalletRouterParams(normalizeRawParams(raw ?? {}));
253
+ }
254
+
255
+ export const walletRouterAction: Action = {
256
+ name: "WALLET",
257
+ description:
258
+ "Route wallet token operations through the registered chain handlers. Use subaction transfer, swap, or bridge with uniform params: subaction, chain, toChain, fromToken, toToken, amount, recipient, slippageBps, mode, dryRun. Bridge uses chain as the source and toChain as the destination. Omit chain only when one registered handler supports the subaction.",
259
+ descriptionCompressed:
260
+ "Route wallet transfer/swap/bridge via chain registry; params: subaction, chain, toChain, fromToken, toToken, amount, recipient, slippageBps, mode, dryRun.",
261
+ contexts: ["finance", "crypto", "wallet"],
262
+ contextGate: { anyOf: ["finance", "crypto", "wallet"] },
263
+ roleGate: { minRole: "USER" },
264
+ similes: [
265
+ "SWAP",
266
+ "SWAP_SOLANA",
267
+ "TRANSFER",
268
+ "TRANSFER_TOKEN",
269
+ "WALLET_SWAP",
270
+ "WALLET_TRANSFER",
271
+ "CROSS_CHAIN_TRANSFER",
272
+ "PREPARE_TRANSFER",
273
+ "WALLET_ACTION",
274
+ "WALLET_GOV",
275
+ "WALLET_GOV",
276
+ ],
277
+ parameters: [
278
+ {
279
+ name: "subaction",
280
+ description: "Wallet operation to perform.",
281
+ required: true,
282
+ schema: { type: "string", enum: ["transfer", "swap", "bridge", "gov"] },
283
+ examples: ["transfer", "swap", "bridge", "gov"],
284
+ },
285
+ {
286
+ name: "target",
287
+ description:
288
+ "Chain id or name (source chain for bridge). Omit only when one chain supports subaction.",
289
+ required: false,
290
+ schema: { type: "string" },
291
+ examples: ["base", "solana", "8453"],
292
+ },
293
+ {
294
+ name: "toChain",
295
+ description: "Destination chain for bridge.",
296
+ required: false,
297
+ schema: { type: "string" },
298
+ examples: ["arbitrum", "optimism", "base"],
299
+ },
300
+ {
301
+ name: "fromToken",
302
+ description: "Source token symbol, native token alias, or token address.",
303
+ required: false,
304
+ schema: { type: "string" },
305
+ examples: ["ETH", "SOL", "USDC"],
306
+ },
307
+ {
308
+ name: "toToken",
309
+ description:
310
+ "Destination token symbol, native token alias, or token address.",
311
+ required: false,
312
+ schema: { type: "string" },
313
+ examples: ["USDC", "SOL"],
314
+ },
315
+ {
316
+ name: "amount",
317
+ description:
318
+ "Human-readable token amount. Required for transfer, swap, and bridge.",
319
+ required: true,
320
+ schema: { type: "string" },
321
+ examples: ["0.1", "25"],
322
+ },
323
+ {
324
+ name: "recipient",
325
+ description: "Recipient address for transfer.",
326
+ required: false,
327
+ schema: { type: "string" },
328
+ examples: ["0x742d35Cc6634C0532925a3b844Bc454e4438f44e"],
329
+ },
330
+ {
331
+ name: "slippageBps",
332
+ description: "Maximum swap slippage in basis points.",
333
+ required: false,
334
+ schema: { type: "number" },
335
+ examples: [100],
336
+ },
337
+ {
338
+ name: "mode",
339
+ description: "Prepare without submitting, or execute the operation.",
340
+ required: false,
341
+ schema: {
342
+ type: "string",
343
+ enum: ["prepare", "execute"],
344
+ default: "prepare",
345
+ },
346
+ examples: ["prepare", "execute"],
347
+ },
348
+ {
349
+ name: "dryRun",
350
+ description: "Return metadata without signing or sending.",
351
+ required: false,
352
+ schema: { type: "boolean", default: false },
353
+ examples: [true, false],
354
+ },
355
+ {
356
+ name: "op",
357
+ description: "Governance operation when subaction is gov.",
358
+ required: false,
359
+ schema: { type: "string", enum: ["propose", "vote", "queue", "execute"] },
360
+ examples: ["vote"],
361
+ },
362
+ {
363
+ name: "governor",
364
+ description: "Governor contract address for governance operations.",
365
+ required: false,
366
+ schema: { type: "string" },
367
+ examples: ["0x742d35Cc6634C0532925a3b844Bc454e4438f44e"],
368
+ },
369
+ {
370
+ name: "proposalId",
371
+ description: "Proposal id for governance vote, queue, or execute.",
372
+ required: false,
373
+ schema: { type: "string" },
374
+ },
375
+ {
376
+ name: "support",
377
+ description: "Vote support value for governance vote operations.",
378
+ required: false,
379
+ schema: { type: "number" },
380
+ examples: [1],
381
+ },
382
+ {
383
+ name: "targets",
384
+ description:
385
+ "Target contract addresses for governance propose, queue, or execute.",
386
+ required: false,
387
+ schema: { type: "array", items: { type: "string" } },
388
+ },
389
+ {
390
+ name: "values",
391
+ description:
392
+ "Native token values as strings for governance propose, queue, or execute.",
393
+ required: false,
394
+ schema: { type: "array", items: { type: "string" } },
395
+ },
396
+ {
397
+ name: "calldatas",
398
+ description:
399
+ "Hex calldata values for governance propose, queue, or execute.",
400
+ required: false,
401
+ schema: { type: "array", items: { type: "string" } },
402
+ },
403
+ {
404
+ name: "description",
405
+ description:
406
+ "Proposal description for governance propose, queue, or execute.",
407
+ required: false,
408
+ schema: { type: "string" },
409
+ },
410
+ ],
411
+ validate: async (_runtime, message, state, options) => {
412
+ if (!serviceFromRuntime(_runtime)) {
413
+ return false;
414
+ }
415
+ const raw = extractRawParams(message, state, options);
416
+ if (raw) {
417
+ const normalized = normalizeRawParams(raw);
418
+ if (isWalletRouterSubaction(normalized.subaction)) {
419
+ return true;
420
+ }
421
+ }
422
+ if (selectedContextMatches(state, ["finance", "crypto", "wallet"])) {
423
+ return true;
424
+ }
425
+ return false;
426
+ },
427
+ handler: async (
428
+ runtime: IAgentRuntime,
429
+ message: Memory,
430
+ state?: State,
431
+ options?: HandlerOptions | Record<string, unknown>,
432
+ callback?: HandlerCallback,
433
+ ): Promise<ActionResult> => {
434
+ let params: WalletRouterParams;
435
+ try {
436
+ params = await parseParams(message, state, options);
437
+ } catch (error) {
438
+ const text = `Invalid wallet parameters: ${
439
+ error instanceof Error ? error.message : String(error)
440
+ }`;
441
+ await callback?.({ text, content: { error: "INVALID_PARAMS" } });
442
+ return {
443
+ success: false,
444
+ text,
445
+ data: { error: "INVALID_PARAMS" },
446
+ };
447
+ }
448
+
449
+ const service = serviceFromRuntime(runtime);
450
+ if (!service) {
451
+ const text = "Wallet router service is not available.";
452
+ await callback?.({ text, content: { error: "SERVICE_UNAVAILABLE" } });
453
+ return {
454
+ success: false,
455
+ text,
456
+ data: { error: "SERVICE_UNAVAILABLE" },
457
+ };
458
+ }
459
+
460
+ const routed = await service.routeWalletAction(params);
461
+ const text = resultText(routed);
462
+ const data = toProviderRecord(
463
+ routed.ok
464
+ ? {
465
+ ...routed.result,
466
+ handler: routed.handler,
467
+ }
468
+ : {
469
+ error: routed.error,
470
+ detail: routed.detail,
471
+ candidates: routed.candidates,
472
+ },
473
+ );
474
+
475
+ await callback?.({
476
+ text,
477
+ content: {
478
+ success: routed.ok,
479
+ ...data,
480
+ },
481
+ });
482
+
483
+ return {
484
+ success: routed.ok,
485
+ text,
486
+ values: routed.ok
487
+ ? {
488
+ walletActionSucceeded: routed.result.status === "submitted",
489
+ walletActionPrepared: routed.result.status === "prepared",
490
+ walletChain: routed.handler.chain,
491
+ walletSubaction: routed.result.subaction,
492
+ }
493
+ : {
494
+ walletActionError: routed.error,
495
+ },
496
+ data,
497
+ };
498
+ },
499
+ examples: [
500
+ [
501
+ {
502
+ name: "{{user1}}",
503
+ content: {
504
+ text: "Send 0.2 ETH on Base to 0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
505
+ },
506
+ },
507
+ {
508
+ name: "{{agent}}",
509
+ content: {
510
+ text: "Preparing the Base transfer.",
511
+ action: "WALLET",
512
+ },
513
+ },
514
+ ],
515
+ [
516
+ {
517
+ name: "{{user1}}",
518
+ content: {
519
+ text: "Swap 1 SOL to USDC on Solana with a dry run first",
520
+ },
521
+ },
522
+ {
523
+ name: "{{agent}}",
524
+ content: {
525
+ text: "Preparing a Solana swap dry run.",
526
+ action: "WALLET",
527
+ },
528
+ },
529
+ ],
530
+ ],
531
+ };
532
+
533
+ export default walletRouterAction;