@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,34 @@
1
+ import http from "node:http";
2
+
3
+ //#region src/contracts.d.ts
4
+ interface WalletExportRequestBody {
5
+ confirm?: boolean;
6
+ exportToken?: string;
7
+ }
8
+ interface WalletExportRejection {
9
+ status: 400 | 401 | 402 | 403 | 429;
10
+ reason: string;
11
+ }
12
+ //#endregion
13
+ //#region src/lib/server-wallet-trade.d.ts
14
+ declare function normalizeCompatRejection<T extends {
15
+ status: number;
16
+ reason: string;
17
+ } | null>(rejection: T): T;
18
+ declare function runWithCompatAuthContext<T>(req: Pick<http.IncomingMessage, "headers">, operation: () => T): T;
19
+ type TradePermissionMode = "user-sign-only" | "manual-local-key" | "agent-auto";
20
+ declare function resolveTradePermissionMode(config: {
21
+ features?: {
22
+ tradePermissionMode?: unknown;
23
+ } | null;
24
+ }): TradePermissionMode;
25
+ declare function canUseLocalTradeExecution(mode: TradePermissionMode, isAgent: boolean): boolean;
26
+ /**
27
+ * Hardened wallet export rejection function.
28
+ *
29
+ * Wraps the upstream token validation with per-IP rate limiting (1 per 10 min),
30
+ * audit logging (IP + UA), and a 10s confirmation delay via single-use nonces.
31
+ */
32
+ declare function resolveWalletExportRejection(req: http.IncomingMessage, body: WalletExportRequestBody): WalletExportRejection | null;
33
+ //#endregion
34
+ export { TradePermissionMode, canUseLocalTradeExecution, normalizeCompatRejection, resolveTradePermissionMode, resolveWalletExportRejection, runWithCompatAuthContext };
@@ -0,0 +1,306 @@
1
+ import crypto from "node:crypto";
2
+ import { syncAppEnvToEliza, syncElizaEnvAliases } from "@elizaos/core";
3
+ //#region src/lib/wallet-export-guard.ts
4
+ /**
5
+ * Hardened wallet private key export guard.
6
+ *
7
+ * Wraps the upstream resolveWalletExportRejection with:
8
+ * 1. Per-IP rate limiting (1 successful export per 10 minutes)
9
+ * 2. Audit logging with IP, User-Agent, and timestamp
10
+ * 3. Forced confirmation delay (10s countdown)
11
+ *
12
+ * The upstream function validates the export token. This module adds
13
+ * defence-in-depth so a compromised session cannot instantly extract
14
+ * keys without leaving an audit trail and hitting rate limits.
15
+ *
16
+ * Exported from the `@elizaos/plugin-wallet` barrel for package consumers.
17
+ */
18
+ const RATE_LIMIT_WINDOW_MS = 600 * 1e3;
19
+ const RATE_LIMIT_SWEEP_INTERVAL_MS = 900 * 1e3;
20
+ const rateLimitMap = /* @__PURE__ */ new Map();
21
+ const sweepTimer = setInterval(() => {
22
+ const now = Date.now();
23
+ for (const [key, entry] of rateLimitMap) if (now - entry.lastExportAt > RATE_LIMIT_WINDOW_MS * 2) rateLimitMap.delete(key);
24
+ }, RATE_LIMIT_SWEEP_INTERVAL_MS);
25
+ if (typeof sweepTimer === "object" && "unref" in sweepTimer) sweepTimer.unref();
26
+ /**
27
+ * Get client IP from the socket directly. X-Forwarded-For is not trusted
28
+ * because this is a local server — trusting XFF would let attackers spoof
29
+ * IPs to bypass rate limits and nonce IP binding.
30
+ */
31
+ function getClientIp(req) {
32
+ return req.socket?.remoteAddress ?? null;
33
+ }
34
+ function getUserAgent(req) {
35
+ return req.headers["user-agent"] ?? "unknown";
36
+ }
37
+ const auditLog = [];
38
+ const MAX_AUDIT_ENTRIES = 100;
39
+ function recordAudit(entry) {
40
+ auditLog.push(entry);
41
+ if (auditLog.length > MAX_AUDIT_ENTRIES) auditLog.shift();
42
+ const logLine = `[wallet-export-audit] ${entry.outcome} ip=${entry.ip} ua="${entry.userAgent}"${entry.reason ? ` reason="${entry.reason}"` : ""}`;
43
+ console.warn(logLine);
44
+ }
45
+ const EXPORT_DELAY_MS = 1e4;
46
+ const MAX_PENDING_NONCES_PER_IP = 3;
47
+ /**
48
+ * Issue a time-limited export nonce. The client must wait at least
49
+ * EXPORT_DELAY_MS before submitting the actual export request with this nonce.
50
+ */
51
+ const pendingExportNonces = /* @__PURE__ */ new Map();
52
+ const NONCE_TTL_MS = 300 * 1e3;
53
+ function issueExportNonce(ip) {
54
+ const now = Date.now();
55
+ for (const [key, value] of pendingExportNonces) if (now - value.issuedAt > NONCE_TTL_MS) pendingExportNonces.delete(key);
56
+ let countForIp = 0;
57
+ for (const entry of pendingExportNonces.values()) if (entry.ip === ip) countForIp++;
58
+ if (countForIp >= MAX_PENDING_NONCES_PER_IP) return null;
59
+ const nonce = `wxn_${crypto.randomBytes(16).toString("hex")}`;
60
+ pendingExportNonces.set(nonce, {
61
+ issuedAt: Date.now(),
62
+ ip
63
+ });
64
+ return nonce;
65
+ }
66
+ function validateExportNonce(nonce, ip) {
67
+ const entry = pendingExportNonces.get(nonce);
68
+ if (!entry) return {
69
+ valid: false,
70
+ reason: "Invalid or expired export nonce."
71
+ };
72
+ if (entry.ip !== ip) return {
73
+ valid: false,
74
+ reason: "Export nonce was issued to a different client."
75
+ };
76
+ const elapsed = Date.now() - entry.issuedAt;
77
+ if (elapsed < EXPORT_DELAY_MS) return {
78
+ valid: false,
79
+ reason: `Export confirmation delay not met. Wait ${Math.ceil((EXPORT_DELAY_MS - elapsed) / 1e3)} more seconds.`
80
+ };
81
+ pendingExportNonces.delete(nonce);
82
+ return { valid: true };
83
+ }
84
+ /**
85
+ * Create a hardened wallet export rejection function that wraps the upstream
86
+ * token validation with rate limiting, audit logging, and a forced delay.
87
+ *
88
+ * Two-phase export flow:
89
+ * 1. POST /api/wallet/export { confirm: true, exportToken: "...", requestNonce: true }
90
+ * → 403 with { nonce, delaySeconds } — client must wait
91
+ * 2. POST /api/wallet/export { confirm: true, exportToken: "...", exportNonce: "wxn_..." }
92
+ * → 200 with keys (if delay elapsed and rate limit not hit)
93
+ */
94
+ function createHardenedExportGuard(upstream) {
95
+ return (req, body) => {
96
+ const ip = getClientIp(req);
97
+ const ua = getUserAgent(req);
98
+ if (!ip) {
99
+ recordAudit({
100
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
101
+ ip: "unknown",
102
+ userAgent: ua,
103
+ outcome: "rejected",
104
+ reason: "No client IP available on socket"
105
+ });
106
+ return {
107
+ status: 400,
108
+ reason: "Unable to determine client IP; request rejected."
109
+ };
110
+ }
111
+ const upstreamRejection = upstream(req, body);
112
+ if (upstreamRejection) {
113
+ recordAudit({
114
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
115
+ ip,
116
+ userAgent: ua,
117
+ outcome: "rejected",
118
+ reason: upstreamRejection.reason
119
+ });
120
+ return upstreamRejection;
121
+ }
122
+ if (body.requestNonce) {
123
+ const nonce = issueExportNonce(ip);
124
+ if (!nonce) {
125
+ recordAudit({
126
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
127
+ ip,
128
+ userAgent: ua,
129
+ outcome: "rejected",
130
+ reason: "Too many pending nonces for this IP"
131
+ });
132
+ return {
133
+ status: 429,
134
+ reason: `Too many pending export requests. Complete or wait for existing nonces to expire.`
135
+ };
136
+ }
137
+ recordAudit({
138
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
139
+ ip,
140
+ userAgent: ua,
141
+ outcome: "rejected",
142
+ reason: "Nonce issued, waiting for confirmation delay"
143
+ });
144
+ return {
145
+ status: 403,
146
+ reason: JSON.stringify({
147
+ countdown: true,
148
+ nonce,
149
+ delaySeconds: EXPORT_DELAY_MS / 1e3,
150
+ message: `Export nonce issued. Wait ${EXPORT_DELAY_MS / 1e3} seconds, then re-submit with exportNonce: "${nonce}".`
151
+ })
152
+ };
153
+ }
154
+ if (!body.exportNonce) {
155
+ recordAudit({
156
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
157
+ ip,
158
+ userAgent: ua,
159
+ outcome: "rejected",
160
+ reason: "Missing export nonce"
161
+ });
162
+ return {
163
+ status: 403,
164
+ reason: "Export requires a confirmation delay. First send { \"confirm\": true, \"exportToken\": \"...\", \"requestNonce\": true } to start the countdown."
165
+ };
166
+ }
167
+ const nonceResult = validateExportNonce(body.exportNonce, ip);
168
+ if (!nonceResult.valid) {
169
+ recordAudit({
170
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
171
+ ip,
172
+ userAgent: ua,
173
+ outcome: "rejected",
174
+ reason: nonceResult.reason
175
+ });
176
+ return {
177
+ status: 403,
178
+ reason: nonceResult.reason
179
+ };
180
+ }
181
+ const rateLimitEntry = rateLimitMap.get(ip);
182
+ if (rateLimitEntry) {
183
+ const elapsed = Date.now() - rateLimitEntry.lastExportAt;
184
+ if (elapsed < RATE_LIMIT_WINDOW_MS) {
185
+ const retryAfter = Math.ceil((RATE_LIMIT_WINDOW_MS - elapsed) / 1e3);
186
+ recordAudit({
187
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
188
+ ip,
189
+ userAgent: ua,
190
+ outcome: "rate-limited",
191
+ reason: `Rate limited, retry after ${retryAfter}s`
192
+ });
193
+ return {
194
+ status: 429,
195
+ reason: `Rate limit exceeded. One export per ${RATE_LIMIT_WINDOW_MS / 6e4} minutes. Retry after ${retryAfter} seconds.`
196
+ };
197
+ }
198
+ }
199
+ rateLimitMap.set(ip, { lastExportAt: Date.now() });
200
+ recordAudit({
201
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
202
+ ip,
203
+ userAgent: ua,
204
+ outcome: "allowed"
205
+ });
206
+ return null;
207
+ };
208
+ }
209
+ //#endregion
210
+ //#region src/lib/server-wallet-trade.ts
211
+ /**
212
+ * Wallet / trade compat helpers — trade permission modes, local execution
213
+ * guards, and wallet export rejection wrappers.
214
+ *
215
+ * Exported from the `@elizaos/plugin-wallet` barrel for package consumers.
216
+ */
217
+ function normalizeCompatReason(reason) {
218
+ return reason;
219
+ }
220
+ function mirrorCompatHeaders(req) {
221
+ for (const [appHeader, elizaHeader] of [
222
+ ["x-elizaos-token", "x-eliza-token"],
223
+ ["x-elizaos-export-token", "x-eliza-export-token"],
224
+ ["x-elizaos-client-id", "x-eliza-client-id"],
225
+ ["x-elizaos-terminal-token", "x-eliza-terminal-token"],
226
+ ["x-elizaos-ui-language", "x-eliza-ui-language"],
227
+ ["x-elizaos-agent-action", "x-eliza-agent-action"]
228
+ ]) {
229
+ const appValue = req.headers[appHeader];
230
+ const elizaValue = req.headers[elizaHeader];
231
+ if (appValue != null && elizaValue == null) req.headers[elizaHeader] = appValue;
232
+ if (elizaValue != null && appValue == null) req.headers[appHeader] = elizaValue;
233
+ }
234
+ }
235
+ function normalizeCompatRejection(rejection) {
236
+ if (!rejection) return rejection;
237
+ return {
238
+ ...rejection,
239
+ reason: normalizeCompatReason(rejection.reason)
240
+ };
241
+ }
242
+ function runWithCompatAuthContext(req, operation) {
243
+ syncElizaEnvAliases();
244
+ syncAppEnvToEliza();
245
+ mirrorCompatHeaders(req);
246
+ try {
247
+ return operation();
248
+ } finally {
249
+ syncAppEnvToEliza();
250
+ syncElizaEnvAliases();
251
+ }
252
+ }
253
+ function tokenMatches(expected, provided) {
254
+ const a = Buffer.from(expected, "utf8");
255
+ const b = Buffer.from(provided, "utf8");
256
+ if (a.length !== b.length) return false;
257
+ return crypto.timingSafeEqual(a, b);
258
+ }
259
+ function resolveBaseWalletExportRejection(req, body) {
260
+ if (!body.confirm) return {
261
+ status: 403,
262
+ reason: "Export requires explicit confirmation. Send { \"confirm\": true } in the request body."
263
+ };
264
+ const expected = process.env.ELIZA_WALLET_EXPORT_TOKEN?.trim();
265
+ if (!expected) return {
266
+ status: 403,
267
+ reason: "Wallet export is disabled. Set ELIZA_WALLET_EXPORT_TOKEN to enable secure exports."
268
+ };
269
+ const headerToken = typeof req.headers["x-eliza-export-token"] === "string" ? req.headers["x-eliza-export-token"].trim() : "";
270
+ const bodyToken = typeof body.exportToken === "string" ? body.exportToken.trim() : "";
271
+ const provided = headerToken || bodyToken;
272
+ if (!provided) return {
273
+ status: 401,
274
+ reason: "Missing export token. Provide X-Eliza-Export-Token header or exportToken in request body."
275
+ };
276
+ if (!tokenMatches(expected, provided)) return {
277
+ status: 401,
278
+ reason: "Invalid export token."
279
+ };
280
+ return null;
281
+ }
282
+ function resolveCompatWalletExportRejection(req, body) {
283
+ return runWithCompatAuthContext(req, () => normalizeCompatRejection(resolveBaseWalletExportRejection(req, body)));
284
+ }
285
+ const hardenedGuard = createHardenedExportGuard(resolveCompatWalletExportRejection);
286
+ function resolveTradePermissionMode(config) {
287
+ const raw = config.features?.tradePermissionMode;
288
+ if (raw === "user-sign-only" || raw === "manual-local-key" || raw === "agent-auto") return raw;
289
+ return "user-sign-only";
290
+ }
291
+ function canUseLocalTradeExecution(mode, isAgent) {
292
+ if (mode === "agent-auto") return true;
293
+ if (mode === "manual-local-key") return !isAgent;
294
+ return false;
295
+ }
296
+ /**
297
+ * Hardened wallet export rejection function.
298
+ *
299
+ * Wraps the upstream token validation with per-IP rate limiting (1 per 10 min),
300
+ * audit logging (IP + UA), and a 10s confirmation delay via single-use nonces.
301
+ */
302
+ function resolveWalletExportRejection(req, body) {
303
+ return runWithCompatAuthContext(req, () => normalizeCompatRejection(hardenedGuard(req, body)));
304
+ }
305
+ //#endregion
306
+ export { canUseLocalTradeExecution, normalizeCompatRejection, resolveTradePermissionMode, resolveWalletExportRejection, runWithCompatAuthContext };