@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,89 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { existsSync } from "node:fs";
4
+ import { mkdir, writeFile } from "node:fs/promises";
5
+ import { join } from "node:path";
6
+
7
+ async function runBuild(): Promise<boolean> {
8
+ console.log("Building @elizaos/plugin-wallet evm chain...");
9
+
10
+ const distDir = join(process.cwd(), "dist");
11
+
12
+ if (existsSync(distDir)) {
13
+ await Bun.$`rm -rf ${distDir}`;
14
+ }
15
+
16
+ await mkdir(distDir, { recursive: true });
17
+
18
+ const result = await Bun.build({
19
+ entrypoints: ["./index.ts"],
20
+ outdir: distDir,
21
+ target: "node",
22
+ format: "esm",
23
+ sourcemap: "external",
24
+ minify: false,
25
+ external: [
26
+ "@elizaos/core",
27
+ "dotenv",
28
+ "fs",
29
+ "path",
30
+ "node:path",
31
+ "node:fs",
32
+ "node:os",
33
+ "viem",
34
+ "viem/accounts",
35
+ "viem/chains",
36
+ "@lifi/sdk",
37
+ "@lifi/types",
38
+ "@lifi/data-types",
39
+ "zod",
40
+ "https",
41
+ "http",
42
+ "agentkeepalive",
43
+ "@reflink/reflink",
44
+ ],
45
+ });
46
+
47
+ if (!result.success) {
48
+ console.error("Build failed:");
49
+ for (const log of result.logs) {
50
+ console.error(log);
51
+ }
52
+ return false;
53
+ }
54
+
55
+ console.log(`Build successful: ${result.outputs.length} files generated`);
56
+
57
+ console.log("Generating TypeScript declarations...");
58
+ const tscResult = await Bun.$`cd ${process.cwd()} && bun x tsc -p tsconfig.build.json`
59
+ .quiet()
60
+ .nothrow();
61
+
62
+ if (tscResult.exitCode !== 0) {
63
+ console.warn("Warning: TypeScript declaration generation had issues:");
64
+ console.warn(tscResult.stderr.toString());
65
+ }
66
+
67
+ const indexDtsPath = join(distDir, "index.d.ts");
68
+ if (!existsSync(indexDtsPath)) {
69
+ await writeFile(
70
+ indexDtsPath,
71
+ `export * from "./index";
72
+ export { default } from "./index";
73
+ `,
74
+ "utf8"
75
+ );
76
+ }
77
+
78
+ console.log("Build complete!");
79
+ return true;
80
+ }
81
+
82
+ runBuild()
83
+ .then((ok) => {
84
+ if (!ok) process.exit(1);
85
+ })
86
+ .catch((error) => {
87
+ console.error("Build script error:", error);
88
+ process.exit(1);
89
+ });
@@ -0,0 +1,416 @@
1
+ import type { ITokenDataService } from "@elizaos/core";
2
+ import {
3
+ type Address,
4
+ type Chain,
5
+ encodeFunctionData,
6
+ parseAbi,
7
+ parseEther,
8
+ parseUnits,
9
+ } from "viem";
10
+ import { buildSendTxParams } from "./actions/helpers";
11
+ import { SwapAction } from "./actions/swap";
12
+ import { TransferAction } from "./actions/transfer";
13
+ import { NATIVE_TOKEN_ADDRESS } from "./constants";
14
+ import { routeEvmGovernance } from "./gov-router";
15
+ import { initWalletProvider, type WalletProvider } from "./providers/wallet";
16
+ import type {
17
+ WalletChainHandler,
18
+ WalletRouterContext,
19
+ WalletRouterExecution,
20
+ WalletRouterParams,
21
+ } from "../../types/wallet-router.js";
22
+ import type { SupportedChain, Transaction } from "./types";
23
+
24
+ export type EvmWalletSubaction = "transfer" | "swap" | "gov";
25
+ export type EvmWalletMode = "prepare" | "execute";
26
+
27
+ export interface EvmWalletChainHandlerOptions {
28
+ readonly walletProvider?: WalletProvider;
29
+ }
30
+
31
+ export interface EvmPreparedResult extends WalletRouterExecution {
32
+ readonly status: "prepared";
33
+ }
34
+
35
+ export interface EvmExecutedTransaction extends WalletRouterExecution {
36
+ readonly status: "submitted";
37
+ }
38
+
39
+ export type EvmRouterResult = EvmPreparedResult | EvmExecutedTransaction;
40
+
41
+ function isEvmAddress(value: string): value is Address {
42
+ return /^0x[a-fA-F0-9]{40}$/.test(value);
43
+ }
44
+
45
+ function evmAliases(key: string, chain: Chain): string[] {
46
+ const aliases = new Set<string>([
47
+ key,
48
+ chain.name,
49
+ String(chain.id),
50
+ chain.nativeCurrency.symbol,
51
+ ]);
52
+ if (key === "mainnet") {
53
+ aliases.add("ethereum");
54
+ aliases.add("eth");
55
+ }
56
+ return [...aliases];
57
+ }
58
+
59
+ function isNativeEvmToken(value: string | undefined, chain: Chain): boolean {
60
+ if (!value) return true;
61
+ const normalized = value.toLowerCase();
62
+ return (
63
+ normalized === "native" ||
64
+ normalized === "eth" ||
65
+ normalized === chain.nativeCurrency.symbol.toLowerCase() ||
66
+ normalized === NATIVE_TOKEN_ADDRESS.toLowerCase()
67
+ );
68
+ }
69
+
70
+ async function resolveTokenViaService(
71
+ service: ITokenDataService | null,
72
+ token: string,
73
+ chain: string
74
+ ): Promise<string | null> {
75
+ if (!service) return null;
76
+ const results = await service.searchTokens(token, chain, 5);
77
+ const match = results.find((candidate) => {
78
+ const maybe = candidate as { address?: unknown; symbol?: unknown };
79
+ return (
80
+ typeof maybe.address === "string" &&
81
+ (String(maybe.symbol ?? "").toLowerCase() === token.toLowerCase() ||
82
+ maybe.address.toLowerCase() === token.toLowerCase())
83
+ );
84
+ });
85
+ const address = (match as { address?: unknown } | undefined)?.address;
86
+ return typeof address === "string" ? address : null;
87
+ }
88
+
89
+ async function resolveEvmTokenAddress(
90
+ token: string | undefined,
91
+ chainKey: string,
92
+ chain: Chain,
93
+ context: WalletRouterContext
94
+ ): Promise<Address> {
95
+ if (isNativeEvmToken(token, chain)) {
96
+ return NATIVE_TOKEN_ADDRESS;
97
+ }
98
+ if (token && isEvmAddress(token)) {
99
+ return token;
100
+ }
101
+ if (token) {
102
+ const resolved = await resolveTokenViaService(context.tokenDataService, token, chainKey);
103
+ if (resolved && isEvmAddress(resolved)) {
104
+ return resolved;
105
+ }
106
+ }
107
+ throw new Error(
108
+ `Token "${token ?? "native"}" must be an EVM address or a resolvable ${chain.name} token symbol.`
109
+ );
110
+ }
111
+
112
+ function transactionToExecution(
113
+ tx: Transaction,
114
+ params: WalletRouterParams,
115
+ chainKey: string,
116
+ chain: Chain
117
+ ): EvmExecutedTransaction {
118
+ return {
119
+ status: "submitted",
120
+ chain: chainKey,
121
+ chainId: String(chain.id),
122
+ subaction: params.subaction,
123
+ dryRun: false,
124
+ mode: params.mode,
125
+ transactionHash: tx.hash,
126
+ from: tx.from,
127
+ to: tx.to,
128
+ amount: params.amount,
129
+ fromToken: params.fromToken,
130
+ toToken: params.toToken,
131
+ metadata: {
132
+ value: tx.value.toString(),
133
+ data: tx.data,
134
+ chainId: tx.chainId ?? chain.id,
135
+ },
136
+ };
137
+ }
138
+
139
+ function requireAmount(params: WalletRouterParams): string {
140
+ if (!params.amount) {
141
+ throw new Error("amount is required.");
142
+ }
143
+ return params.amount;
144
+ }
145
+
146
+ function requireRecipient(params: WalletRouterParams): Address {
147
+ if (!params.recipient || !isEvmAddress(params.recipient)) {
148
+ throw new Error("recipient must be a valid EVM address.");
149
+ }
150
+ return params.recipient;
151
+ }
152
+
153
+ export class EvmWalletChainHandler implements WalletChainHandler {
154
+ readonly chainId: string;
155
+ readonly chain: string;
156
+ readonly name: string;
157
+ readonly aliases: readonly string[];
158
+ readonly supportedActions = ["transfer", "swap", "gov"] as const;
159
+ readonly tokens: WalletChainHandler["tokens"];
160
+ readonly signer: WalletChainHandler["signer"];
161
+ readonly dryRun: WalletChainHandler["dryRun"];
162
+
163
+ constructor(
164
+ private readonly chainKey: SupportedChain,
165
+ private readonly chainConfig: Chain,
166
+ private readonly options: EvmWalletChainHandlerOptions = {}
167
+ ) {
168
+ this.chainId = String(chainConfig.id);
169
+ this.chain = chainKey;
170
+ this.name = chainConfig.name;
171
+ this.aliases = evmAliases(chainKey, chainConfig);
172
+ this.tokens = [
173
+ {
174
+ symbol: chainConfig.nativeCurrency.symbol,
175
+ address: NATIVE_TOKEN_ADDRESS,
176
+ decimals: chainConfig.nativeCurrency.decimals,
177
+ native: true,
178
+ },
179
+ ];
180
+ this.signer = {
181
+ required: true,
182
+ kind: "evm",
183
+ source: "WalletBackend EVM signer or EVM_PRIVATE_KEY",
184
+ description: "Required only for execute mode.",
185
+ };
186
+ this.dryRun = {
187
+ supported: true,
188
+ supportedActions: ["transfer", "swap", "gov"],
189
+ description: "Prepare mode and dry-run return route metadata without signing.",
190
+ };
191
+ }
192
+
193
+ async execute(
194
+ params: WalletRouterParams,
195
+ context: WalletRouterContext
196
+ ): Promise<EvmRouterResult> {
197
+ if (params.mode === "prepare" || params.dryRun) {
198
+ if (params.subaction === "transfer") {
199
+ return this.prepareTransfer(params);
200
+ }
201
+ if (params.subaction === "swap") {
202
+ return this.prepareSwap(params);
203
+ }
204
+ return routeEvmGovernance(
205
+ params,
206
+ context,
207
+ this.chain,
208
+ this.chainConfig
209
+ ) as Promise<EvmRouterResult>;
210
+ }
211
+ if (params.subaction === "transfer") {
212
+ return this.executeTransfer(params, context);
213
+ }
214
+ if (params.subaction === "swap") {
215
+ return this.executeSwap(params, context);
216
+ }
217
+ return routeEvmGovernance(
218
+ params,
219
+ context,
220
+ this.chain,
221
+ this.chainConfig,
222
+ await this.getWalletProvider(context)
223
+ ) as Promise<EvmRouterResult>;
224
+ }
225
+
226
+ prepareTransfer(params: WalletRouterParams): EvmPreparedResult {
227
+ const recipient = requireRecipient(params);
228
+ const amount = requireAmount(params);
229
+ const token = params.fromToken ?? this.chainConfig.nativeCurrency.symbol;
230
+
231
+ return {
232
+ status: "prepared",
233
+ chain: this.chain,
234
+ chainId: this.chainId,
235
+ subaction: "transfer",
236
+ dryRun: params.dryRun,
237
+ mode: params.mode,
238
+ to: recipient,
239
+ amount,
240
+ fromToken: token,
241
+ metadata: {
242
+ requiresConfirmation: true,
243
+ transactionRequest:
244
+ isNativeEvmToken(params.fromToken, this.chainConfig)
245
+ ? {
246
+ to: recipient,
247
+ value: parseEther(amount).toString(),
248
+ data: "0x",
249
+ chainId: this.chainConfig.id,
250
+ }
251
+ : undefined,
252
+ signer: this.signer,
253
+ },
254
+ };
255
+ }
256
+
257
+ prepareSwap(params: WalletRouterParams): EvmPreparedResult {
258
+ const amount = requireAmount(params);
259
+ if (!params.fromToken) {
260
+ throw new Error("fromToken is required for swap.");
261
+ }
262
+ if (!params.toToken) {
263
+ throw new Error("toToken is required for swap.");
264
+ }
265
+
266
+ return {
267
+ status: "prepared",
268
+ chain: this.chain,
269
+ chainId: this.chainId,
270
+ subaction: "swap",
271
+ dryRun: params.dryRun,
272
+ mode: params.mode,
273
+ amount,
274
+ fromToken: params.fromToken,
275
+ toToken: params.toToken,
276
+ metadata: {
277
+ requiresConfirmation: true,
278
+ slippageBps: params.slippageBps,
279
+ signer: this.signer,
280
+ },
281
+ };
282
+ }
283
+
284
+ async executeTransfer(
285
+ params: WalletRouterParams,
286
+ context: WalletRouterContext
287
+ ): Promise<EvmExecutedTransaction> {
288
+ const recipient = requireRecipient(params);
289
+ const amount = requireAmount(params);
290
+ const walletProvider = await this.getWalletProvider(context);
291
+ const token = await resolveEvmTokenAddress(
292
+ params.fromToken,
293
+ this.chain,
294
+ this.chainConfig,
295
+ context
296
+ );
297
+
298
+ if (token === NATIVE_TOKEN_ADDRESS) {
299
+ const tx = await new TransferAction(walletProvider).transfer({
300
+ fromChain: this.chainKey,
301
+ toAddress: recipient,
302
+ amount,
303
+ token: params.fromToken,
304
+ });
305
+ return transactionToExecution(tx, params, this.chain, this.chainConfig);
306
+ }
307
+
308
+ const walletClient = walletProvider.getWalletClient(this.chainKey);
309
+ const account = walletClient.account;
310
+ if (!account) {
311
+ throw new Error("Wallet account is not available.");
312
+ }
313
+
314
+ const publicClient = walletProvider.getPublicClient(this.chainKey);
315
+ const decimalsAbi = parseAbi(["function decimals() view returns (uint8)"]);
316
+ const decimals = Number(
317
+ await publicClient.readContract({
318
+ address: token,
319
+ abi: decimalsAbi,
320
+ functionName: "decimals",
321
+ authorizationList: undefined,
322
+ })
323
+ );
324
+ const transferAbi = parseAbi(["function transfer(address,uint256) returns (bool)"]);
325
+ const data = encodeFunctionData({
326
+ abi: transferAbi,
327
+ functionName: "transfer",
328
+ args: [recipient, parseUnits(amount, decimals)],
329
+ });
330
+
331
+ const hash = await walletClient.sendTransaction(
332
+ buildSendTxParams({
333
+ account,
334
+ to: token,
335
+ value: 0n,
336
+ data,
337
+ chain: this.chainConfig,
338
+ })
339
+ );
340
+
341
+ return {
342
+ status: "submitted",
343
+ chain: this.chain,
344
+ chainId: this.chainId,
345
+ subaction: "transfer",
346
+ dryRun: false,
347
+ mode: params.mode,
348
+ transactionHash: hash,
349
+ from: account.address,
350
+ to: recipient,
351
+ amount,
352
+ fromToken: token,
353
+ metadata: {
354
+ token,
355
+ decimals,
356
+ value: "0",
357
+ data,
358
+ },
359
+ };
360
+ }
361
+
362
+ async executeSwap(
363
+ params: WalletRouterParams,
364
+ context: WalletRouterContext
365
+ ): Promise<EvmExecutedTransaction> {
366
+ const amount = requireAmount(params);
367
+ const walletProvider = await this.getWalletProvider(context);
368
+ const fromToken = await resolveEvmTokenAddress(
369
+ params.fromToken,
370
+ this.chain,
371
+ this.chainConfig,
372
+ context
373
+ );
374
+ const toToken = await resolveEvmTokenAddress(
375
+ params.toToken,
376
+ this.chain,
377
+ this.chainConfig,
378
+ context
379
+ );
380
+
381
+ const tx = await new SwapAction(walletProvider).swap({
382
+ chain: this.chainKey,
383
+ fromToken,
384
+ toToken,
385
+ amount,
386
+ });
387
+ return transactionToExecution(
388
+ {
389
+ ...tx,
390
+ chainId: tx.chainId ?? this.chainConfig.id,
391
+ },
392
+ {
393
+ ...params,
394
+ fromToken,
395
+ toToken,
396
+ },
397
+ this.chain,
398
+ this.chainConfig
399
+ );
400
+ }
401
+
402
+ private async getWalletProvider(context: WalletRouterContext): Promise<WalletProvider> {
403
+ if (this.options.walletProvider) {
404
+ return this.options.walletProvider;
405
+ }
406
+ return initWalletProvider(context.runtime);
407
+ }
408
+ }
409
+
410
+ export function createEvmWalletChainHandler(
411
+ chainKey: string,
412
+ chain: Chain,
413
+ options?: EvmWalletChainHandlerOptions
414
+ ): EvmWalletChainHandler {
415
+ return new EvmWalletChainHandler(chainKey as SupportedChain, chain, options);
416
+ }
@@ -0,0 +1,23 @@
1
+ export const EVM_SERVICE_NAME = "evmService" as const;
2
+ export const EVM_WALLET_DATA_CACHE_KEY = "evm_wallet_data" as const;
3
+ export const CACHE_REFRESH_INTERVAL_MS = 60000;
4
+ export const GAS_BUFFER_MULTIPLIER = 1.2 as const;
5
+ export const GAS_PRICE_MULTIPLIER = 1.1 as const;
6
+ export const MAX_SLIPPAGE_PERCENT = 0.05 as const;
7
+ export const DEFAULT_SLIPPAGE_PERCENT = 0.01 as const;
8
+ export const MAX_PRICE_IMPACT = 0.4 as const;
9
+ export const TX_CONFIRMATION_TIMEOUT_MS = 60000;
10
+ export const BRIDGE_POLL_INTERVAL_MS = 5000;
11
+ export const MAX_BRIDGE_POLL_ATTEMPTS = 60 as const;
12
+ export const NATIVE_TOKEN_ADDRESS = "0x0000000000000000000000000000000000000000" as const;
13
+
14
+ export const BEBOP_CHAIN_MAP: Readonly<Record<string, string>> = {
15
+ mainnet: "ethereum",
16
+ optimism: "optimism",
17
+ polygon: "polygon",
18
+ arbitrum: "arbitrum",
19
+ base: "base",
20
+ linea: "linea",
21
+ } as const;
22
+
23
+ export const DEFAULT_CHAINS = ["mainnet", "base", "bsc"] as const;