auramaxx 1.0.0-alpha.4

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 (363) hide show
  1. package/LICENSE +26 -0
  2. package/README.md +112 -0
  3. package/bin/aurawallet.js +121 -0
  4. package/docs/ADAPTERS.md +467 -0
  5. package/docs/API.md +2679 -0
  6. package/docs/APPS.md +198 -0
  7. package/docs/ARCHITECTURE.md +350 -0
  8. package/docs/AUTH.md +698 -0
  9. package/docs/BEST-PRACTICES.md +121 -0
  10. package/docs/CLI.md +61 -0
  11. package/docs/DEVELOPING-APPS.md +452 -0
  12. package/docs/EXTENSION.md +97 -0
  13. package/docs/JOBS.md +33 -0
  14. package/docs/MCP.md +76 -0
  15. package/docs/PROTOCOL.md +142 -0
  16. package/docs/SETUP.md +219 -0
  17. package/docs/WORKSPACE.md +672 -0
  18. package/docs/agent-auth.md +63 -0
  19. package/docs/aura-file.md +48 -0
  20. package/docs/credentials.md +53 -0
  21. package/docs/external/getting-started.md +65 -0
  22. package/docs/external/overview.md +45 -0
  23. package/docs/external/use-cases.md +48 -0
  24. package/docs/external/why-aura.md +35 -0
  25. package/docs/jobs/connect-agent.md +77 -0
  26. package/docs/jobs/migrate-from-dotenv.md +79 -0
  27. package/docs/jobs/recover-from-lockout.md +72 -0
  28. package/docs/jobs/secure-ci.md +63 -0
  29. package/docs/oauth2.md +42 -0
  30. package/docs/passkeys.md +60 -0
  31. package/docs/security.md +540 -0
  32. package/docs/specs/aura-open-protocol.md +61 -0
  33. package/docs/specs/aura-provider-plugin.md +24 -0
  34. package/docs/specs/aura-registry-model.md +31 -0
  35. package/docs/specs/fixtures/invalid-bad-key.aura +1 -0
  36. package/docs/specs/fixtures/invalid-bad-unicode-escape.aura +1 -0
  37. package/docs/specs/fixtures/invalid-duplicate-key.aura +2 -0
  38. package/docs/specs/fixtures/valid-basic.aura +4 -0
  39. package/docs/specs/fixtures/valid-provider-ref.aura +1 -0
  40. package/docs/specs/fixtures/valid-quoted-escapes.aura +2 -0
  41. package/docs/templates/RELEASE_NOTES_TEMPLATE.md +22 -0
  42. package/docs/totp.md +40 -0
  43. package/docs/wallet/AI.md +508 -0
  44. package/docs/wallet/DEVELOPING-STRATEGIES.md +713 -0
  45. package/docs/wallet/README.md +47 -0
  46. package/docs/wallet/STRATEGY.md +89 -0
  47. package/next.config.ts +21 -0
  48. package/package.json +151 -0
  49. package/postcss.config.mjs +8 -0
  50. package/prisma/migrations/20260214170000_baseline/migration.sql +511 -0
  51. package/prisma/migrations/20260216214537_add_passkey_model/migration.sql +18 -0
  52. package/prisma/migrations/20260217150500_add_credential_access_audit/migration.sql +31 -0
  53. package/prisma/migrations/migration_lock.toml +3 -0
  54. package/prisma/schema.prisma +447 -0
  55. package/public/logo-chevron.svg +31 -0
  56. package/public/logo-concentric.svg +31 -0
  57. package/public/logo-crosshatch.svg +39 -0
  58. package/public/logo-dashed.svg +39 -0
  59. package/public/logo-horizontal.svg +31 -0
  60. package/public/logo-m56.svg +64 -0
  61. package/public/logo.webp +0 -0
  62. package/scripts/add-app.js +245 -0
  63. package/scripts/init.sh +57 -0
  64. package/scripts/migrate-apikeys-to-credentials.ts +35 -0
  65. package/scripts/sandbox-agent-flow.sh +235 -0
  66. package/scripts/sandbox.sh +175 -0
  67. package/scripts/validate-job-docs.mjs +125 -0
  68. package/server/abi/SwapHelper.json +438 -0
  69. package/server/cli/approval.ts +447 -0
  70. package/server/cli/commands/app.ts +204 -0
  71. package/server/cli/commands/cron.ts +24 -0
  72. package/server/cli/commands/doctor.ts +1007 -0
  73. package/server/cli/commands/env.ts +456 -0
  74. package/server/cli/commands/init.ts +752 -0
  75. package/server/cli/commands/mcp.ts +125 -0
  76. package/server/cli/commands/restore.ts +314 -0
  77. package/server/cli/commands/shell-hook.ts +468 -0
  78. package/server/cli/commands/start.ts +62 -0
  79. package/server/cli/commands/status.ts +59 -0
  80. package/server/cli/commands/stop.ts +14 -0
  81. package/server/cli/commands/token.ts +180 -0
  82. package/server/cli/commands/unlock.ts +49 -0
  83. package/server/cli/commands/vault.ts +417 -0
  84. package/server/cli/index.ts +328 -0
  85. package/server/cli/lib/aura-parser.ts +64 -0
  86. package/server/cli/lib/credential-create.ts +74 -0
  87. package/server/cli/lib/credential-resolve.ts +254 -0
  88. package/server/cli/lib/dotenv-migrate.ts +116 -0
  89. package/server/cli/lib/dotenv-parser.ts +146 -0
  90. package/server/cli/lib/http.ts +91 -0
  91. package/server/cli/lib/init-steps.ts +76 -0
  92. package/server/cli/lib/local-agent-trust.ts +45 -0
  93. package/server/cli/lib/process.ts +136 -0
  94. package/server/cli/lib/prompt.ts +85 -0
  95. package/server/cli/lib/theme.ts +240 -0
  96. package/server/cli/socket.ts +570 -0
  97. package/server/cli/transport-client.ts +50 -0
  98. package/server/cron/index.ts +137 -0
  99. package/server/cron/job.ts +31 -0
  100. package/server/cron/jobs/balance-sync.ts +436 -0
  101. package/server/cron/jobs/incoming-scan.ts +506 -0
  102. package/server/cron/jobs/native-price.ts +70 -0
  103. package/server/cron/jobs/orphan-cleanup.ts +40 -0
  104. package/server/cron/jobs/strategy-runner.ts +175 -0
  105. package/server/cron/scheduler.ts +125 -0
  106. package/server/index.ts +406 -0
  107. package/server/lib/adapters/factory.ts +110 -0
  108. package/server/lib/adapters/index.ts +19 -0
  109. package/server/lib/adapters/router.ts +297 -0
  110. package/server/lib/adapters/telegram.ts +645 -0
  111. package/server/lib/adapters/types.ts +89 -0
  112. package/server/lib/adapters/webhook.ts +95 -0
  113. package/server/lib/address.ts +49 -0
  114. package/server/lib/agent-auth/contracts.ts +1194 -0
  115. package/server/lib/agent-profiles.ts +328 -0
  116. package/server/lib/ai.ts +285 -0
  117. package/server/lib/api-registry/contracts.ts +86 -0
  118. package/server/lib/api-registry/validation.ts +172 -0
  119. package/server/lib/apikey-migration.ts +189 -0
  120. package/server/lib/app-installer.ts +505 -0
  121. package/server/lib/app-tokens.ts +247 -0
  122. package/server/lib/auth.ts +314 -0
  123. package/server/lib/batch.ts +242 -0
  124. package/server/lib/cold.ts +874 -0
  125. package/server/lib/config.ts +381 -0
  126. package/server/lib/credential-access-audit.ts +85 -0
  127. package/server/lib/credential-access-policy.ts +110 -0
  128. package/server/lib/credential-health.ts +343 -0
  129. package/server/lib/credential-import.ts +487 -0
  130. package/server/lib/credential-scope.ts +87 -0
  131. package/server/lib/credential-shares.ts +190 -0
  132. package/server/lib/credential-transport.ts +342 -0
  133. package/server/lib/credential-vault.ts +77 -0
  134. package/server/lib/credentials.ts +333 -0
  135. package/server/lib/crypto.ts +8 -0
  136. package/server/lib/db.ts +15 -0
  137. package/server/lib/defaults.ts +366 -0
  138. package/server/lib/dex/index.ts +80 -0
  139. package/server/lib/dex/relay.ts +235 -0
  140. package/server/lib/dex/types.ts +59 -0
  141. package/server/lib/dex/uniswap.ts +370 -0
  142. package/server/lib/e2e-agent/artifacts.ts +36 -0
  143. package/server/lib/e2e-agent/contracts.ts +112 -0
  144. package/server/lib/e2e-agent/validation.ts +135 -0
  145. package/server/lib/encrypt.ts +128 -0
  146. package/server/lib/error.ts +20 -0
  147. package/server/lib/events.ts +205 -0
  148. package/server/lib/hot.ts +357 -0
  149. package/server/lib/key-fingerprint.ts +28 -0
  150. package/server/lib/logger.ts +331 -0
  151. package/server/lib/network.ts +137 -0
  152. package/server/lib/notifications.ts +219 -0
  153. package/server/lib/oauth2-refresh.ts +241 -0
  154. package/server/lib/oursecret.ts +54 -0
  155. package/server/lib/passkey-credential.ts +360 -0
  156. package/server/lib/passkey.ts +68 -0
  157. package/server/lib/permissions.ts +248 -0
  158. package/server/lib/pino.ts +24 -0
  159. package/server/lib/policy-preview.ts +138 -0
  160. package/server/lib/price.ts +338 -0
  161. package/server/lib/prices.ts +34 -0
  162. package/server/lib/project-scope.ts +239 -0
  163. package/server/lib/resolve-action.ts +427 -0
  164. package/server/lib/resolve.ts +36 -0
  165. package/server/lib/sessions.ts +632 -0
  166. package/server/lib/solana/connection.ts +26 -0
  167. package/server/lib/solana/jupiter.ts +128 -0
  168. package/server/lib/solana/transfer.ts +108 -0
  169. package/server/lib/solana/wallet.ts +136 -0
  170. package/server/lib/strategy/emits.ts +21 -0
  171. package/server/lib/strategy/engine.ts +1305 -0
  172. package/server/lib/strategy/executor.ts +115 -0
  173. package/server/lib/strategy/hook-context.ts +158 -0
  174. package/server/lib/strategy/hooks.ts +990 -0
  175. package/server/lib/strategy/index.ts +28 -0
  176. package/server/lib/strategy/installer.ts +305 -0
  177. package/server/lib/strategy/loader.ts +256 -0
  178. package/server/lib/strategy/message.ts +235 -0
  179. package/server/lib/strategy/repository.ts +218 -0
  180. package/server/lib/strategy/session-logger.ts +693 -0
  181. package/server/lib/strategy/sources.ts +288 -0
  182. package/server/lib/strategy/state.ts +189 -0
  183. package/server/lib/strategy/templates.ts +403 -0
  184. package/server/lib/strategy/tick.ts +404 -0
  185. package/server/lib/strategy/types.ts +230 -0
  186. package/server/lib/swap.ts +3 -0
  187. package/server/lib/temp.ts +86 -0
  188. package/server/lib/token-metadata.ts +86 -0
  189. package/server/lib/token-safety.ts +200 -0
  190. package/server/lib/token-search.ts +444 -0
  191. package/server/lib/totp.ts +194 -0
  192. package/server/lib/transactions.ts +123 -0
  193. package/server/lib/transport.ts +75 -0
  194. package/server/lib/txhistory/decoder.ts +262 -0
  195. package/server/lib/txhistory/enricher.ts +652 -0
  196. package/server/lib/txhistory/index.ts +391 -0
  197. package/server/lib/txhistory/signatures.ts +59 -0
  198. package/server/lib/verified-summary.ts +421 -0
  199. package/server/mcp/profile-policy.ts +30 -0
  200. package/server/mcp/server.ts +619 -0
  201. package/server/mcp/tools.ts +523 -0
  202. package/server/middleware/auth.ts +119 -0
  203. package/server/middleware/requestLogger.ts +84 -0
  204. package/server/routes/actions.ts +459 -0
  205. package/server/routes/adapters.ts +703 -0
  206. package/server/routes/addressbook.ts +113 -0
  207. package/server/routes/ai.ts +34 -0
  208. package/server/routes/apikeys.ts +295 -0
  209. package/server/routes/apps.ts +601 -0
  210. package/server/routes/auth.ts +457 -0
  211. package/server/routes/backup.ts +340 -0
  212. package/server/routes/batch.ts +270 -0
  213. package/server/routes/bookmarks.ts +162 -0
  214. package/server/routes/credential-shares.ts +198 -0
  215. package/server/routes/credential-vaults.ts +154 -0
  216. package/server/routes/credentials.ts +1290 -0
  217. package/server/routes/dashboard.ts +71 -0
  218. package/server/routes/defaults.ts +124 -0
  219. package/server/routes/fund.ts +229 -0
  220. package/server/routes/import.ts +352 -0
  221. package/server/routes/launch.ts +665 -0
  222. package/server/routes/lock.ts +54 -0
  223. package/server/routes/logs.ts +68 -0
  224. package/server/routes/nuke.ts +111 -0
  225. package/server/routes/passkey-credentials.ts +99 -0
  226. package/server/routes/passkey.ts +346 -0
  227. package/server/routes/portfolio.ts +217 -0
  228. package/server/routes/price.ts +63 -0
  229. package/server/routes/resolve.ts +31 -0
  230. package/server/routes/security.ts +45 -0
  231. package/server/routes/send-evm.ts +241 -0
  232. package/server/routes/send-solana.ts +281 -0
  233. package/server/routes/send.ts +178 -0
  234. package/server/routes/setup.ts +210 -0
  235. package/server/routes/strategy.ts +894 -0
  236. package/server/routes/swap-evm.ts +353 -0
  237. package/server/routes/swap-solana.ts +177 -0
  238. package/server/routes/swap.ts +356 -0
  239. package/server/routes/token.ts +247 -0
  240. package/server/routes/unlock.ts +403 -0
  241. package/server/routes/wallet-assets.ts +361 -0
  242. package/server/routes/wallet-transactions.ts +515 -0
  243. package/server/routes/wallet.ts +710 -0
  244. package/server/types.ts +146 -0
  245. package/skills/aurawallet/SKILL.md +739 -0
  246. package/skills/aurawallet-setup/SKILL.md +74 -0
  247. package/skills/security-review/SKILL.md +148 -0
  248. package/src/app/api/agent-requests/route.ts +30 -0
  249. package/src/app/api/apps/install/route.ts +126 -0
  250. package/src/app/api/apps/manifests/route.ts +16 -0
  251. package/src/app/api/apps/static/[...path]/route.ts +57 -0
  252. package/src/app/api/events/route.ts +92 -0
  253. package/src/app/api/page.tsx +212 -0
  254. package/src/app/api/workspace/[id]/apps/[wid]/route.ts +119 -0
  255. package/src/app/api/workspace/[id]/apps/route.ts +81 -0
  256. package/src/app/api/workspace/[id]/export/route.ts +67 -0
  257. package/src/app/api/workspace/[id]/route.ts +168 -0
  258. package/src/app/api/workspace/auth.ts +34 -0
  259. package/src/app/api/workspace/config/route.ts +106 -0
  260. package/src/app/api/workspace/import/route.ts +127 -0
  261. package/src/app/api/workspace/route.ts +116 -0
  262. package/src/app/app/page.tsx +2122 -0
  263. package/src/app/apple-icon.png +0 -0
  264. package/src/app/docs/page.tsx +178 -0
  265. package/src/app/favicon.ico +0 -0
  266. package/src/app/globals.css +572 -0
  267. package/src/app/health/page.tsx +5 -0
  268. package/src/app/hello/page.tsx +15 -0
  269. package/src/app/icon.png +0 -0
  270. package/src/app/layout.tsx +34 -0
  271. package/src/app/page.tsx +986 -0
  272. package/src/app/providers.tsx +90 -0
  273. package/src/app/share/[token]/page.tsx +295 -0
  274. package/src/components/ChainSelector.tsx +144 -0
  275. package/src/components/HumanActionBar.tsx +695 -0
  276. package/src/components/NotificationDrawer.tsx +129 -0
  277. package/src/components/apps/AgentKeysApp.tsx +490 -0
  278. package/src/components/apps/App.tsx +153 -0
  279. package/src/components/apps/AppGrid.tsx +15 -0
  280. package/src/components/apps/DetailedAddressDrawer.tsx +325 -0
  281. package/src/components/apps/DraggableApp.tsx +562 -0
  282. package/src/components/apps/IFrameApp.tsx +73 -0
  283. package/src/components/apps/LogsApp.tsx +360 -0
  284. package/src/components/apps/SendApp.tsx +394 -0
  285. package/src/components/apps/SetupWizardApp.tsx +1004 -0
  286. package/src/components/apps/SystemDefaultsApp.tsx +845 -0
  287. package/src/components/apps/ThirdPartyApp.tsx +428 -0
  288. package/src/components/apps/TokenApp.tsx +319 -0
  289. package/src/components/apps/TransactionsApp.tsx +438 -0
  290. package/src/components/apps/WalletDetailApp.tsx +1505 -0
  291. package/src/components/apps/index.ts +13 -0
  292. package/src/components/design-system/Button.tsx +53 -0
  293. package/src/components/design-system/ChainIndicator.tsx +65 -0
  294. package/src/components/design-system/ChainSelector.tsx +137 -0
  295. package/src/components/design-system/ConfirmationModal.tsx +106 -0
  296. package/src/components/design-system/ConfirmationPopover.tsx +81 -0
  297. package/src/components/design-system/Drawer.tsx +123 -0
  298. package/src/components/design-system/FilterDropdown.tsx +72 -0
  299. package/src/components/design-system/Modal.tsx +206 -0
  300. package/src/components/design-system/Popover.tsx +142 -0
  301. package/src/components/design-system/TextInput.tsx +85 -0
  302. package/src/components/design-system/Toggle.tsx +58 -0
  303. package/src/components/design-system/index.ts +11 -0
  304. package/src/components/docs/DocsThemeToggle.tsx +49 -0
  305. package/src/components/health/CredentialHealthDashboard.tsx +214 -0
  306. package/src/components/icons/ChainIcons.tsx +72 -0
  307. package/src/components/layout/AppStoreDrawer.tsx +369 -0
  308. package/src/components/layout/ContentArea.tsx +21 -0
  309. package/src/components/layout/TabBar.tsx +278 -0
  310. package/src/components/layout/WalletSidebar.tsx +1033 -0
  311. package/src/components/layout/index.ts +4 -0
  312. package/src/components/marketing/AuraWalletSpecOverlay.tsx +635 -0
  313. package/src/components/marketing/DeviceMorphExperience.tsx +216 -0
  314. package/src/components/vault/ApiKeysConsole.tsx +1080 -0
  315. package/src/components/vault/AuditConsole.tsx +584 -0
  316. package/src/components/vault/CredentialDetail.tsx +455 -0
  317. package/src/components/vault/CredentialEmpty.tsx +55 -0
  318. package/src/components/vault/CredentialField.tsx +361 -0
  319. package/src/components/vault/CredentialForm.tsx +1212 -0
  320. package/src/components/vault/CredentialList.tsx +165 -0
  321. package/src/components/vault/CredentialRow.tsx +97 -0
  322. package/src/components/vault/CredentialShareModal.tsx +178 -0
  323. package/src/components/vault/CredentialVault.tsx +754 -0
  324. package/src/components/vault/CredentialWalletWidget.tsx +103 -0
  325. package/src/components/vault/ImportCredentialsModal.tsx +515 -0
  326. package/src/components/vault/LargeTypeModal.tsx +64 -0
  327. package/src/components/vault/PasswordGenerator.tsx +224 -0
  328. package/src/components/vault/TOTPDisplay.tsx +123 -0
  329. package/src/components/vault/VaultSidebar.tsx +413 -0
  330. package/src/components/vault/types.ts +54 -0
  331. package/src/context/AuthContext.tsx +337 -0
  332. package/src/context/PriceContext.tsx +113 -0
  333. package/src/context/ThemeContext.tsx +164 -0
  334. package/src/context/WebSocketContext.tsx +269 -0
  335. package/src/context/WorkspaceContext.tsx +668 -0
  336. package/src/hooks/index.ts +3 -0
  337. package/src/hooks/useAgentActions.ts +368 -0
  338. package/src/hooks/useBalance.ts +103 -0
  339. package/src/hooks/useBalances.ts +129 -0
  340. package/src/instrumentation.ts +12 -0
  341. package/src/lib/api.ts +449 -0
  342. package/src/lib/app-loader.ts +148 -0
  343. package/src/lib/app-registry.ts +178 -0
  344. package/src/lib/app-sdk.ts +157 -0
  345. package/src/lib/audit-console-adapter.ts +151 -0
  346. package/src/lib/auth-client.ts +75 -0
  347. package/src/lib/config.ts +74 -0
  348. package/src/lib/crypto.ts +112 -0
  349. package/src/lib/db.ts +21 -0
  350. package/src/lib/docs.ts +390 -0
  351. package/src/lib/events.ts +361 -0
  352. package/src/lib/pino.ts +24 -0
  353. package/src/lib/theme-handlers.ts +168 -0
  354. package/src/lib/theme.ts +351 -0
  355. package/src/lib/tokenData.ts +378 -0
  356. package/src/lib/vault-crypto.ts +129 -0
  357. package/src/lib/websocket-server.ts +302 -0
  358. package/src/lib/websocket-setup.ts +79 -0
  359. package/src/lib/wordlist.ts +2050 -0
  360. package/src/lib/workspace-handlers.ts +285 -0
  361. package/start.sh +80 -0
  362. package/tailwind.config.ts +99 -0
  363. package/tsconfig.json +42 -0
package/docs/API.md ADDED
@@ -0,0 +1,2679 @@
1
+ # Wallet Server API
2
+
3
+ HTTP REST API for wallet operations. Server runs on `http://localhost:4242`.
4
+
5
+ ---
6
+
7
+ ## Authentication
8
+
9
+ ### Agent Token
10
+
11
+ Most agent endpoints require a Bearer token in the Authorization header:
12
+
13
+ ```bash
14
+ Authorization: Bearer <token>
15
+ ```
16
+
17
+ Tokens are obtained by requesting `agent_access` and having a human approve it.
18
+
19
+ ---
20
+
21
+ ## Public Endpoints
22
+
23
+ ### Health Check
24
+
25
+ ```http
26
+ GET /health
27
+ ```
28
+
29
+ Returns server status.
30
+
31
+ ### Server Public Key
32
+
33
+ ```http
34
+ GET /auth/connect
35
+ ```
36
+
37
+ Returns the server's ephemeral RSA public key for encrypting passwords (used by `/unlock` and `/setup`).
38
+
39
+ **Response:**
40
+ ```json
41
+ {
42
+ "publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBI..."
43
+ }
44
+ ```
45
+
46
+ ### Event Logs
47
+
48
+ ```http
49
+ GET /logs
50
+ ```
51
+
52
+ Returns historical event logs from the database. Supports filtering and pagination.
53
+
54
+ **Query params:**
55
+ - `type`: Filter by exact event type (e.g., `token:created`)
56
+ - `category`: Filter by category prefix (e.g., `auth` matches `auth:unlocked`, `auth:auth_failed`, etc.)
57
+ - `agentId`: Filter events by agent ID (searches JSON data field)
58
+ - `since`: Start timestamp (ms epoch or ISO string)
59
+ - `until`: End timestamp (ms epoch or ISO string)
60
+ - `limit`: Max results (default 50, max 250)
61
+ - `offset`: Pagination offset
62
+
63
+ **Response:**
64
+ ```json
65
+ {
66
+ "success": true,
67
+ "logs": [
68
+ {
69
+ "id": "cuid123",
70
+ "type": "auth:unlocked",
71
+ "source": "express",
72
+ "data": "{\"description\":\"Wallet unlocked\"}",
73
+ "timestamp": "2026-02-01T12:00:00.000Z"
74
+ }
75
+ ],
76
+ "count": 50,
77
+ "total": 120,
78
+ "pagination": { "limit": 50, "offset": 0, "hasMore": true }
79
+ }
80
+ ```
81
+
82
+ ### ENS Name Resolution
83
+
84
+ ```http
85
+ GET /resolve/:name
86
+ ```
87
+
88
+ Resolves an ENS name (`.eth`) to an Ethereum address. Public endpoint — no authentication required. Uses Ethereum mainnet RPC for ENS resolution.
89
+
90
+ **Example:**
91
+ ```bash
92
+ GET /resolve/vitalik.eth
93
+ ```
94
+
95
+ **Response:**
96
+ ```json
97
+ {
98
+ "success": true,
99
+ "address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
100
+ "name": "vitalik.eth"
101
+ }
102
+ ```
103
+
104
+ **Error:**
105
+ ```json
106
+ {
107
+ "error": "Could not resolve: nonexistent.eth"
108
+ }
109
+ ```
110
+
111
+ Only `.eth` names are supported. Solana `.sol` names are out of scope.
112
+
113
+ ### Token Price Lookup
114
+
115
+ ```http
116
+ GET /price/:address?chain=base
117
+ ```
118
+
119
+ Returns USD price for any ERC-20 or SPL token. Public endpoint — no authentication required. Uses a cascading fallback of free APIs: DexScreener → CoinGecko → Alchemy (if configured). Results are cached in memory for 60 seconds.
120
+
121
+ Use `native` as the address to get the native currency price (ETH or SOL).
122
+
123
+ **Query params:**
124
+ - `chain` (optional): Chain to look up price on (default: server default chain). Supported: `base`, `ethereum`, `solana`, `polygon`, `arbitrum`, `optimism`
125
+
126
+ **Example — ERC-20 token:**
127
+ ```bash
128
+ GET /price/0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913?chain=base
129
+ ```
130
+
131
+ **Response:**
132
+ ```json
133
+ {
134
+ "success": true,
135
+ "token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
136
+ "chain": "base",
137
+ "priceUsd": "0.9998",
138
+ "source": "dexscreener",
139
+ "cached": false
140
+ }
141
+ ```
142
+
143
+ **Example — Native currency:**
144
+ ```bash
145
+ GET /price/native?chain=base
146
+ ```
147
+
148
+ **Response:**
149
+ ```json
150
+ {
151
+ "success": true,
152
+ "token": "native",
153
+ "chain": "base",
154
+ "priceUsd": "3200",
155
+ "source": "cache",
156
+ "cached": true
157
+ }
158
+ ```
159
+
160
+ **Error (no price found):**
161
+ ```json
162
+ {
163
+ "success": false,
164
+ "error": "No price found for 0x... on base"
165
+ }
166
+ ```
167
+
168
+ **Error (invalid address):**
169
+ ```json
170
+ {
171
+ "success": false,
172
+ "error": "Invalid EVM address format"
173
+ }
174
+ ```
175
+
176
+ ### Token Search
177
+
178
+ ```http
179
+ GET /token/search?q=PEPE&chain=base&limit=10
180
+ ```
181
+
182
+ Search for tokens by ticker symbol or name. Returns deduplicated results sorted by liquidity. Uses DexScreener search API with CoinGecko fallback. Results cached for 5 minutes.
183
+
184
+ **Query parameters:**
185
+ | Param | Required | Default | Description |
186
+ |---------|----------|---------|-------------|
187
+ | `q` | Yes | — | Search query (ticker, name, or address) |
188
+ | `chain` | No | — | Filter to specific chain (`base`, `ethereum`, `solana`, etc.) |
189
+ | `limit` | No | 10 | Max results (1–50) |
190
+
191
+ **Response:**
192
+ ```json
193
+ {
194
+ "success": true,
195
+ "query": "PEPE",
196
+ "results": [
197
+ {
198
+ "address": "0x6982508145454Ce325dDbE47a25d4ec3d2311933",
199
+ "chain": "ethereum",
200
+ "symbol": "PEPE",
201
+ "name": "Pepe",
202
+ "priceUsd": "0.00001234",
203
+ "liquidity": 5000000,
204
+ "volume24h": 12000000,
205
+ "marketCap": 5200000000,
206
+ "fdv": 5200000000,
207
+ "imageUrl": "https://dd.dexscreener.com/ds-data/tokens/ethereum/0x698.png",
208
+ "websites": ["https://pepe.vip"],
209
+ "socials": [{ "type": "twitter", "url": "https://twitter.com/pepecoineth" }],
210
+ "dexId": "uniswap",
211
+ "pairAddress": "0xA43fe16908251ee70EF74718545e4FE6C5cCEc9f"
212
+ }
213
+ ]
214
+ }
215
+ ```
216
+
217
+ **Error (missing query):**
218
+ ```json
219
+ {
220
+ "success": false,
221
+ "error": "Missing required query parameter: q"
222
+ }
223
+ ```
224
+
225
+ ### Token Balance Lookup
226
+
227
+ ```http
228
+ GET /token/:tokenAddress/balance/:walletAddress?chain=base
229
+ ```
230
+
231
+ Returns the on-chain token balance for any wallet address. Works for both registered AuraWallet wallets and arbitrary external addresses. Performs a direct RPC call — no database lookup required.
232
+
233
+ **Path params:**
234
+ - `tokenAddress` — ERC-20 contract address (EVM) or SPL mint address (Solana)
235
+ - `walletAddress` — Wallet address to check balance for
236
+
237
+ **Query params:**
238
+ - `chain` (optional): Chain to query (default: server default chain). Supported: `base`, `ethereum`, `solana`, `solana-devnet`
239
+
240
+ **Example — EVM (ERC-20):**
241
+ ```bash
242
+ GET /token/0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913/balance/0x498581ff718922c3f8e6a244956af099b2652b2b?chain=base
243
+ ```
244
+
245
+ **Response:**
246
+ ```json
247
+ {
248
+ "success": true,
249
+ "tokenAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
250
+ "walletAddress": "0x498581ff718922c3f8e6a244956af099b2652b2b",
251
+ "chain": "base",
252
+ "balance": "1000000",
253
+ "formatted": "1.0",
254
+ "decimals": 6,
255
+ "symbol": "USDC",
256
+ "name": "USD Coin",
257
+ "priceUsd": "0.9998",
258
+ "valueUsd": "1.00"
259
+ }
260
+ ```
261
+
262
+ **Example — Solana (SPL):**
263
+ ```bash
264
+ GET /token/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v/balance/5Gh7s2...?chain=solana
265
+ ```
266
+
267
+ **Response:**
268
+ ```json
269
+ {
270
+ "success": true,
271
+ "tokenAddress": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
272
+ "walletAddress": "5Gh7s2...",
273
+ "chain": "solana",
274
+ "balance": "1000000",
275
+ "formatted": "1.0",
276
+ "decimals": 6,
277
+ "priceUsd": "0.9998",
278
+ "valueUsd": "1.00"
279
+ }
280
+ ```
281
+
282
+ **Error (invalid address):**
283
+ ```json
284
+ {
285
+ "success": false,
286
+ "error": "Invalid EVM token address format"
287
+ }
288
+ ```
289
+
290
+ **Error (RPC failure):**
291
+ ```json
292
+ {
293
+ "success": false,
294
+ "error": "Failed to query token balance from RPC"
295
+ }
296
+ ```
297
+
298
+ ### Token Safety Check
299
+
300
+ ```http
301
+ GET /token/safety/:address?chain=ethereum
302
+ ```
303
+
304
+ Returns a safety report for a token contract via GoPlusLabs. Includes honeypot detection, tax analysis, holder data, LP info, and contract red flags. 10-minute cache.
305
+
306
+ **Query parameters:**
307
+ | Param | Required | Default | Description |
308
+ |---------|----------|------------|-------------|
309
+ | `chain` | No | `ethereum` | Chain name (`ethereum`, `base`, `solana`, `polygon`, `arbitrum`, `optimism`) |
310
+
311
+ **Response:**
312
+ ```json
313
+ {
314
+ "success": true,
315
+ "address": "0x6982...",
316
+ "chain": "ethereum",
317
+ "safety": {
318
+ "tokenName": "Pepe",
319
+ "tokenSymbol": "PEPE",
320
+ "totalSupply": "420689899653542",
321
+ "isHoneypot": false,
322
+ "isMintable": false,
323
+ "isOpenSource": true,
324
+ "isProxy": false,
325
+ "isBlacklisted": false,
326
+ "buyTax": "0",
327
+ "sellTax": "0",
328
+ "holderCount": 513429,
329
+ "holders": [
330
+ { "address": "0x...", "balance": "100000000", "percent": "0.05", "isLocked": false, "isContract": true, "tag": "Uniswap V2" }
331
+ ],
332
+ "lpHolderCount": 67,
333
+ "lpHolders": [
334
+ { "address": "0x...", "balance": "500000", "percent": "0.5", "isLocked": true, "isContract": true }
335
+ ],
336
+ "dexInfo": [
337
+ { "name": "Uniswap V2", "liquidity": "5000000", "pair": "0x..." }
338
+ ]
339
+ }
340
+ }
341
+ ```
342
+
343
+ ### Token Holders
344
+
345
+ ```http
346
+ GET /token/holders/:address?chain=ethereum
347
+ ```
348
+
349
+ Returns top holders for a token (convenience endpoint — subset of safety data from GoPlusLabs).
350
+
351
+ **Response:**
352
+ ```json
353
+ {
354
+ "success": true,
355
+ "address": "0x6982...",
356
+ "chain": "ethereum",
357
+ "tokenName": "Pepe",
358
+ "tokenSymbol": "PEPE",
359
+ "holderCount": 513429,
360
+ "holders": [
361
+ { "address": "0x...", "balance": "100000000", "percent": "0.05", "isLocked": false, "isContract": true, "tag": "Uniswap V2" }
362
+ ]
363
+ }
364
+ ```
365
+
366
+ ### Batch Requests
367
+
368
+ ```http
369
+ POST /batch
370
+ Content-Type: application/json
371
+ ```
372
+
373
+ Executes multiple API calls in a single HTTP request with dependency chaining. Sub-requests within the same wave execute in parallel; waves execute sequentially. Template references (`${id.json.path}`) resolve data from prior responses.
374
+
375
+ **No auth on the batch endpoint itself** — authentication is enforced per-sub-request via inherited headers from the parent request.
376
+
377
+ **Request body:**
378
+
379
+ ```json
380
+ {
381
+ "requests": [
382
+ {
383
+ "id": "search",
384
+ "method": "GET",
385
+ "path": "/token/search?q=PEPE&limit=1"
386
+ },
387
+ {
388
+ "id": "safety",
389
+ "method": "GET",
390
+ "path": "/token/safety/${search.results.0.address}?chain=${search.results.0.chain}",
391
+ "dependsOn": "search"
392
+ }
393
+ ]
394
+ }
395
+ ```
396
+
397
+ **Field reference:**
398
+
399
+ | Field | Type | Required | Description |
400
+ |-------|------|----------|-------------|
401
+ | `requests` | array | yes | Array of sub-requests (1–20) |
402
+ | `requests[].id` | string | yes | Unique identifier for this request |
403
+ | `requests[].method` | string | yes | HTTP method: `GET`, `POST`, `PUT`, `DELETE` |
404
+ | `requests[].path` | string | yes | API path including query params. May contain `${id.json.path}` template references |
405
+ | `requests[].body` | object | no | Request body for POST/PUT. String values may contain template references |
406
+ | `requests[].dependsOn` | string | no | ID of a request that must complete before this one executes |
407
+
408
+ **Template syntax:**
409
+
410
+ Templates use `${requestId.json.path}` where `json.path` is a dot-separated path into the response body:
411
+
412
+ | Template | Resolves to |
413
+ |----------|-------------|
414
+ | `${search.results.0.address}` | First search result's address |
415
+ | `${search.results.0.chain}` | First search result's chain |
416
+ | `${wallets.wallets.0.address}` | First wallet's address |
417
+
418
+ Array elements are accessed by numeric index: `results.0.address`, `results.1.chain`.
419
+
420
+ **Response (always 200):**
421
+
422
+ ```json
423
+ {
424
+ "responses": {
425
+ "search": {
426
+ "status": 200,
427
+ "body": { "success": true, "query": "PEPE", "results": [...] }
428
+ },
429
+ "safety": {
430
+ "status": 200,
431
+ "body": { "success": true, "address": "0x6982...", "safety": { ... } }
432
+ }
433
+ },
434
+ "meta": {
435
+ "total": 2,
436
+ "succeeded": 2,
437
+ "failed": 0,
438
+ "timings": { "search": 245, "safety": 312 }
439
+ }
440
+ }
441
+ ```
442
+
443
+ **Error handling:**
444
+
445
+ | Scenario | Behavior |
446
+ |----------|----------|
447
+ | Invalid request format | `400` on the batch endpoint |
448
+ | Circular dependency | `400` with descriptive error |
449
+ | Unknown `dependsOn` target | `400` with descriptive error |
450
+ | Too many requests (>20) | `400` |
451
+ | Sub-request fails (4xx/5xx) | Other independent sub-requests still execute; dependent ones get `424` |
452
+ | Template reference not found | Sub-request gets `422` |
453
+ | Sub-request timeout (>30s) | Sub-request gets `504`; dependents get `424` |
454
+
455
+ **Example — search + safety in one call:**
456
+
457
+ ```bash
458
+ curl -X POST http://localhost:4242/batch \
459
+ -H 'Content-Type: application/json' \
460
+ -d '{
461
+ "requests": [
462
+ { "id": "s", "method": "GET", "path": "/token/search?q=PEPE&limit=1" },
463
+ { "id": "safety", "method": "GET", "path": "/token/safety/${s.results.0.address}?chain=${s.results.0.chain}", "dependsOn": "s" }
464
+ ]
465
+ }'
466
+ ```
467
+
468
+ **Rate limiting:** The batch request counts as 1 request against the general rate limiter. Individual sub-requests do not count against rate limits.
469
+
470
+ ### Setup Status
471
+
472
+ ```http
473
+ GET /setup
474
+ ```
475
+
476
+ Returns setup status including vault state, adapter configuration, and API key availability.
477
+
478
+ **Response:**
479
+ ```json
480
+ {
481
+ "hasWallet": true,
482
+ "unlocked": true,
483
+ "address": "0x...",
484
+ "adapters": { "telegram": false, "webhook": false },
485
+ "apiKeys": { "alchemy": true, "anthropic": false },
486
+ "defaultChain": "base"
487
+ }
488
+ ```
489
+
490
+ ### Dashboard Data
491
+
492
+ ```http
493
+ GET /dashboard
494
+ ```
495
+
496
+ Returns pending actions, active tokens, and counts for the UI.
497
+
498
+ ---
499
+
500
+ ## Human Endpoints (Require Unlock)
501
+
502
+ ### Setup Cold Wallet
503
+
504
+ ```http
505
+ POST /setup
506
+ Content-Type: application/json
507
+
508
+ {
509
+ "encrypted": "base64...",
510
+ "pubkey": "<RSA public key PEM or base64>"
511
+ }
512
+ ```
513
+
514
+ Creates the cold wallet with encrypted password. Only works once. Returns an admin token (vault is auto-unlocked after creation).
515
+
516
+ **Response:**
517
+ ```json
518
+ {
519
+ "success": true,
520
+ "address": "0x...",
521
+ "mnemonic": "word1 word2 ... word12",
522
+ "token": "eyJ...",
523
+ "message": "Cold wallet created. SAVE YOUR MNEMONIC SECURELY."
524
+ }
525
+ ```
526
+
527
+ ### Change Primary Vault Password
528
+
529
+ ```http
530
+ POST /setup/password
531
+ Authorization: Bearer <admin-token>
532
+ Content-Type: application/json
533
+
534
+ {
535
+ "currentEncrypted": "base64...",
536
+ "newEncrypted": "base64..."
537
+ }
538
+ ```
539
+
540
+ Rotates the primary vault password by decrypting with the current password and re-encrypting with the new password.
541
+
542
+ **Response:**
543
+ ```json
544
+ {
545
+ "success": true,
546
+ "message": "Primary vault password updated"
547
+ }
548
+ ```
549
+
550
+ **Errors:**
551
+ - `400` if new password is shorter than 8 characters
552
+ - `401` if current password is invalid
553
+
554
+ ### Unlock Page
555
+
556
+ ```http
557
+ GET /unlock
558
+ ```
559
+
560
+ Returns a self-contained HTML page for unlocking the vault in a browser. The page handles RSA-OAEP password encryption client-side and submits to `POST /unlock`. **This is a fallback for headless environments** where the dashboard (`:4747/app`) isn't running. When the dashboard is available, always direct users to `http://localhost:4747/app` instead — it provides the full UI experience including setup wizard, wallet management, and approval flows.
561
+
562
+ ### Unlock Vault
563
+
564
+ ```http
565
+ POST /unlock
566
+ Content-Type: application/json
567
+
568
+ {
569
+ "encrypted": "base64...",
570
+ "pubkey": "<RSA public key PEM or base64>"
571
+ }
572
+ ```
573
+
574
+ Unlocks the primary vault for wallet operations.
575
+
576
+ ### Unlock Specific Vault
577
+
578
+ ```http
579
+ POST /unlock/:vaultId
580
+ Content-Type: application/json
581
+
582
+ {
583
+ "encrypted": "base64...",
584
+ "pubkey": "<RSA public key PEM or base64>"
585
+ }
586
+ ```
587
+
588
+ Unlocks a specific vault by ID. Each vault has its own independent password. Returns:
589
+
590
+ ```json
591
+ {
592
+ "success": true,
593
+ "vaultId": "vault-abc123",
594
+ "address": "0x...",
595
+ "token": "eyJhZ2VudElkIjoiYWRtaW4i..."
596
+ }
597
+ ```
598
+
599
+ ### Lock Vault
600
+
601
+ ```http
602
+ POST /lock
603
+ ```
604
+
605
+ Locks ALL vaults, preventing further operations until unlock.
606
+
607
+ ### Lock Specific Vault
608
+
609
+ ```http
610
+ POST /lock/:vaultId
611
+ ```
612
+
613
+ Locks a specific vault by ID. Requires admin auth.
614
+
615
+ ### Create Additional Vault
616
+
617
+ ```http
618
+ POST /setup/vault
619
+ Authorization: Bearer <admin-token>
620
+ Content-Type: application/json
621
+
622
+ {
623
+ "encrypted": "base64...",
624
+ "name": "Trading Vault"
625
+ }
626
+ ```
627
+
628
+ Creates an additional vault with its own encrypted seed. Requires admin auth and an unlocked primary vault.
629
+
630
+ **Request body:**
631
+ - `encrypted` (required) - RSA-OAEP encrypted password for the new vault
632
+ - `name` (optional) - Human-readable name for the vault
633
+
634
+ **Response:**
635
+ ```json
636
+ {
637
+ "id": "vault-abc123",
638
+ "address": "0x...",
639
+ "solanaAddress": "5Gh7...",
640
+ "mnemonic": "word1 word2 ... word12",
641
+ "name": "Trading Vault"
642
+ }
643
+ ```
644
+
645
+ ### Import Vault from Seed
646
+
647
+ ```http
648
+ POST /setup/vault/import
649
+ Authorization: Bearer <admin-token>
650
+ Content-Type: application/json
651
+
652
+ {
653
+ "mnemonic": "word1 word2 ... word12",
654
+ "encrypted": "base64...",
655
+ "name": "Imported Vault"
656
+ }
657
+ ```
658
+
659
+ Imports a vault from an existing mnemonic seed phrase. Requires admin auth and an unlocked primary vault.
660
+
661
+ **Request body:**
662
+ - `mnemonic` (required) - BIP-39 mnemonic seed phrase to import
663
+ - `encrypted` (required) - RSA-OAEP encrypted password for the vault
664
+ - `name` (optional) - Human-readable name for the vault
665
+
666
+ **Response:**
667
+ ```json
668
+ {
669
+ "id": "vault-def456",
670
+ "address": "0x...",
671
+ "solanaAddress": "7Kx9...",
672
+ "name": "Imported Vault"
673
+ }
674
+ ```
675
+
676
+ ### List Vaults
677
+
678
+ ```http
679
+ GET /setup/vaults
680
+ ```
681
+
682
+ Lists all vaults and their status.
683
+
684
+ **Response:**
685
+ ```json
686
+ {
687
+ "vaults": [
688
+ {
689
+ "id": "vault-primary",
690
+ "name": "Primary",
691
+ "address": "0x...",
692
+ "solanaAddress": "5Gh7...",
693
+ "isUnlocked": true,
694
+ "isPrimary": true,
695
+ "createdAt": "2026-01-15T10:00:00.000Z"
696
+ },
697
+ {
698
+ "id": "vault-abc123",
699
+ "name": "Trading Vault",
700
+ "address": "0x...",
701
+ "solanaAddress": "7Kx9...",
702
+ "isUnlocked": false,
703
+ "isPrimary": false,
704
+ "createdAt": "2026-02-01T12:00:00.000Z"
705
+ }
706
+ ]
707
+ }
708
+ ```
709
+
710
+ ### Export Seed Phrase
711
+
712
+ ```http
713
+ GET /export-seed?vaultId=vault-abc123
714
+ POST /export-seed
715
+ Content-Type: application/json
716
+
717
+ {
718
+ "vaultId": "vault-abc123"
719
+ }
720
+ ```
721
+
722
+ Exports the seed phrase for a vault. The `vaultId` parameter is optional; if omitted, exports the primary vault's seed. Requires the targeted vault to be unlocked.
723
+
724
+ ### Create Human Action Request
725
+
726
+ ```http
727
+ POST /actions
728
+ Authorization: Bearer <token-with-action:create>
729
+ Content-Type: application/json
730
+
731
+ {
732
+ "summary": "Buy $DOGE2 for 0.005 ETH",
733
+ "pubkey": "<RSA public key PEM or base64>",
734
+ "permissions": ["swap"],
735
+ "limits": { "swap": 0.005 },
736
+ "walletAccess": ["0x..."],
737
+ "ttl": 60
738
+ }
739
+ ```
740
+
741
+ Creates a pending action request that requires human approval. On approval, a temporary scoped token is generated with the requested permissions and limits. The caller polls `GET /auth/:requestId?secret=...` to retrieve the token (same as the agent auth flow).
742
+
743
+ Requires `action:create` permission. Cannot request `admin:*` or `action:create` in the `permissions` array.
744
+
745
+ **Request body:**
746
+ - `type` (optional) - Request type: `'action'` (default, requires approval) or `'notify'` (notification-only, no approval needed)
747
+ - `summary` (required) - Human-readable description of the action
748
+ - `pubkey` (required for `action` type) - RSA public key used for temp token issuance
749
+ - `permissions` (required for `action` type) - Array of permissions for the temp token
750
+ - `limits` (optional) - Spending limits for the temp token
751
+ - `walletAccess` (optional) - Wallet addresses the temp token can access
752
+ - `ttl` (optional) - Token lifetime in seconds (default: 60)
753
+ - `metadata` (optional) - Arbitrary metadata. Known fields:
754
+ - `action` (object) - Pre-computed API call `{ endpoint, method, body }`. On approval, this action auto-executes with the scoped temp token and the result is emitted to the app via `action:executed` and `agent:message` channels
755
+
756
+ **Response:**
757
+ ```json
758
+ {
759
+ "success": true,
760
+ "requestId": "clx...",
761
+ "secret": "hex...",
762
+ "message": "Waiting for human approval"
763
+ }
764
+ ```
765
+
766
+ **Token retrieval:** Poll `GET /auth/:requestId?secret=...` — returns `{ status: "pending" }`, `{ status: "approved", token: "..." }`, or `{ status: "rejected" }`.
767
+
768
+ #### Notification-Only Mode (`type: 'notify'`)
769
+
770
+ When `type` is set to `'notify'`, the endpoint creates a dashboard notification without requiring human approval. No permissions, limits, or token are involved. Adapter fan-out (Telegram, webhook) is **opt-in** via the `notify` flag.
771
+
772
+ ```http
773
+ POST /actions
774
+ Authorization: Bearer <token-with-action:create>
775
+ Content-Type: application/json
776
+
777
+ {
778
+ "type": "notify",
779
+ "notify": true,
780
+ "summary": "$TOKEN — Risk 3/10 — MC $25K",
781
+ "metadata": {
782
+ "evaluation": "AI analysis text...",
783
+ "contractAddress": "0x...",
784
+ "symbol": "TOKEN",
785
+ "risk": 3
786
+ }
787
+ }
788
+ ```
789
+
790
+ **Request body (notify):**
791
+ - `type` (required) - Must be `'notify'`
792
+ - `summary` (required) - Notification text
793
+ - `notify` (optional, default `true`) - When `true`, emits `action:created` to adapters (Telegram, webhook). Set to `false` to create a dashboard-only notification without triggering external adapters.
794
+ - `metadata` (optional) - Arbitrary metadata passed to adapters. Known fields: `evaluation`, `contractAddress`, `symbol`, `name`, `marketCap`, `socialLinks`, `risk`
795
+
796
+ **Response:**
797
+ ```json
798
+ {
799
+ "success": true,
800
+ "id": "clx..."
801
+ }
802
+ ```
803
+
804
+ The request is created with `status: 'acknowledged'` (not `'pending'`), so it does not appear in `GET /actions/pending` and cannot be resolved.
805
+
806
+ ### Resolve Action (Primary)
807
+
808
+ ```http
809
+ POST /actions/:id/resolve
810
+ Content-Type: application/json
811
+
812
+ {
813
+ "approved": true
814
+ }
815
+ ```
816
+
817
+ Approves or rejects a pending action. For `agent_access` and `permission_update` types, generates a token on approval. Set `approved` to `false` to reject. Supports optional `walletAccess` and `limits` overrides.
818
+
819
+ ### List Pending Actions
820
+
821
+ ```http
822
+ GET /actions/pending
823
+ ```
824
+
825
+ Returns all pending human actions.
826
+
827
+ ### Create Token (Direct)
828
+
829
+ ```http
830
+ POST /actions/token
831
+ Content-Type: application/json
832
+
833
+ {
834
+ "agentId": "my-agent",
835
+ "limit": 0.5,
836
+ "permissions": ["wallet:create:hot", "send:hot"],
837
+ "ttl": 3600,
838
+ "credentialAccess": {
839
+ "read": ["vault:primary"],
840
+ "excludeFields": ["password"]
841
+ },
842
+ "pubkey": "<RSA public key PEM or base64>"
843
+ }
844
+ ```
845
+
846
+ Creates a signed agent token directly (admin only).
847
+
848
+ `pubkey` is required for all token mints.
849
+
850
+ Profile policy-pack mode is also supported:
851
+
852
+ ```json
853
+ {
854
+ "agentId": "observer-agent",
855
+ "profile": "observer",
856
+ "profileVersion": "v1",
857
+ "profileOverrides": {
858
+ "ttlSeconds": 900,
859
+ "maxReads": 50
860
+ },
861
+ "pubkey": "<RSA public key PEM or base64>"
862
+ }
863
+ ```
864
+
865
+ In profile mode, `permissions` / `credentialAccess` / `ttl` are resolved from the shared profile resolver, and the response includes `profile`, `effectivePolicyHash`, `overrideDelta`, and `warnings`.
866
+
867
+ ### Request Agent Token (Public Bootstrap)
868
+
869
+ ```http
870
+ POST /auth
871
+ Content-Type: application/json
872
+
873
+ {
874
+ "agentId": "my-agent",
875
+ "permissions": ["wallet:list", "swap", "action:create"],
876
+ "limits": { "fund": 0.5, "send": 1.0, "swap": 0.5 },
877
+ "ttl": 3600,
878
+ "pubkey": "<RSA public key PEM or base64>"
879
+ }
880
+ ```
881
+
882
+ Creates a pending auth request for human approval. Returns `requestId` and `secret` for polling `GET /auth/:requestId?secret=...`.
883
+
884
+ ### List Tokens
885
+
886
+ ```http
887
+ GET /actions/tokens
888
+ ```
889
+
890
+ Lists all agent tokens grouped by status (active, inactive, expired, revoked, depleted).
891
+
892
+ ### Request Permission Upgrade
893
+
894
+ ```http
895
+ POST /auth/request-permissions
896
+ Authorization: Bearer <token>
897
+ Content-Type: application/json
898
+
899
+ {
900
+ "requestedPermissions": ["swap", "launch"],
901
+ "requestedWalletAccess": ["0x..."],
902
+ "requestedLimits": { "swap": 1.0 },
903
+ "requestedPubkey": "<RSA public key PEM or base64>"
904
+ }
905
+ ```
906
+
907
+ Requests additional permissions, wallet access, or higher spending limits for an existing token. Creates a `permission_update` pending request that requires human approval. On approval, the agent polls `GET /auth/:requestId?secret=...` to retrieve a new token with the upgraded permissions (same flow as initial token request).
908
+
909
+ Requires a valid agent token. Admin tokens are rejected (already have all permissions).
910
+
911
+ **Request body** (at least one required):
912
+ - `requestedPermissions` (optional) - Additional permission strings to add
913
+ - `requestedWalletAccess` (optional) - Additional wallet addresses to grant access to
914
+ - `requestedLimits` (optional) - New spending limits (replaces existing limits for specified types)
915
+ - `requestedPubkey` (required) - RSA public key for replacement token issuance
916
+
917
+ **Response:**
918
+ ```json
919
+ {
920
+ "success": true,
921
+ "requestId": "clx...",
922
+ "secret": "hex...",
923
+ "message": "Permission update request created, waiting for human approval",
924
+ "currentPermissions": ["trade:all"],
925
+ "requestedPermissions": ["swap", "launch"],
926
+ "requestedWalletAccess": ["0x..."],
927
+ "requestedLimits": { "swap": 1.0 }
928
+ }
929
+ ```
930
+
931
+ **Token retrieval:** Poll `GET /auth/:requestId?secret=...` — same as the initial auth flow.
932
+
933
+ ### Revoke Token
934
+
935
+ ```http
936
+ POST /actions/tokens/revoke
937
+ Content-Type: application/json
938
+
939
+ {
940
+ "tokenHash": "abc123..."
941
+ }
942
+ ```
943
+
944
+ Revokes an active agent token. Admins can revoke any token; agents can only revoke their own.
945
+
946
+ ### List Backups
947
+
948
+ ```http
949
+ GET /backup
950
+ Authorization: Bearer <admin-token>
951
+ ```
952
+
953
+ Lists all database backups. Requires admin permission.
954
+
955
+ ### Create Backup
956
+
957
+ ```http
958
+ POST /backup
959
+ Authorization: Bearer <admin-token>
960
+ ```
961
+
962
+ Creates a new database backup. Keeps last 10 backups. Requires admin permission.
963
+
964
+ ### Restore Backup
965
+
966
+ ```http
967
+ PUT /backup
968
+ Authorization: Bearer <admin-token>
969
+ Content-Type: application/json
970
+
971
+ {
972
+ "filename": "aurawallet.db.20240201_120000.bak"
973
+ }
974
+ ```
975
+
976
+ Restores database from a backup. Requires admin permission.
977
+
978
+ ### Nuke (Reset)
979
+
980
+ ```http
981
+ POST /nuke
982
+ Authorization: Bearer <admin-token>
983
+ ```
984
+
985
+ Resets the wallet database. Requires admin permission. **Destructive — cannot be undone.**
986
+
987
+ ### Import Wallet from Seed
988
+
989
+ ```http
990
+ POST /nuke/import
991
+ Authorization: Bearer <admin-token>
992
+ Content-Type: application/json
993
+
994
+ {
995
+ "mnemonic": "word1 word2 ... word12",
996
+ "encrypted": "base64..."
997
+ }
998
+ ```
999
+
1000
+ Imports a wallet from an existing mnemonic seed phrase. Supports encrypted password transport (`encrypted`) or plaintext (`password`). Requires admin permission. Password must be at least 8 characters.
1001
+
1002
+ ---
1003
+
1004
+ ## Agent Endpoints (Require Bearer Token)
1005
+
1006
+ ### List Wallets
1007
+
1008
+ ```http
1009
+ GET /wallets
1010
+ Authorization: Bearer <token>
1011
+ ```
1012
+
1013
+ Returns all wallets the agent has access to. The response includes separate cold wallet entries per chain (e.g., one for EVM/Base and one for Solana). Each wallet includes a `chain` field and a `balance` field with the native currency balance for that chain (served from cache when available, with RPC fallback). The `balanceUpdatedAt` field indicates when the cached balance was last synced. The response also includes a `vaults` array listing all vaults and their status (see `GET /setup/vaults` for the vault object shape).
1014
+
1015
+ ### List All Transactions
1016
+
1017
+ ```http
1018
+ GET /wallets/transactions
1019
+ Authorization: Bearer <token> (optional)
1020
+ ```
1021
+
1022
+ Returns all transactions across all wallets. Without auth (human), returns all. Agents without `wallet:list` see only transactions for their own wallets. Agents with `wallet:list` see all.
1023
+
1024
+ **Query params:**
1025
+ - `wallet`: Filter by wallet address
1026
+ - `type`: Filter by type (send, receive, swap, contract, manual)
1027
+ - `status`: Filter by status (confirmed, pending)
1028
+ - `chain`: Filter by chain
1029
+ - `token`: Filter by token address
1030
+ - `search`: Search description, txHash, from, to
1031
+ - `limit`: Max results (default 50, max 250)
1032
+ - `offset`: Pagination offset
1033
+ - `sortBy`: Sort field (default: createdAt)
1034
+ - `sortDir`: Sort direction (asc, desc)
1035
+
1036
+ **Response:**
1037
+ ```json
1038
+ {
1039
+ "success": true,
1040
+ "transactions": [
1041
+ {
1042
+ "id": "cuid123",
1043
+ "walletAddress": "0x...",
1044
+ "txHash": "0x...",
1045
+ "type": "swap",
1046
+ "status": "confirmed",
1047
+ "amount": "0.1",
1048
+ "tokenAddress": "0x...",
1049
+ "description": "Bought TOKEN with 0.1 ETH",
1050
+ "chain": "base",
1051
+ "createdAt": "2026-02-01T12:00:00.000Z"
1052
+ }
1053
+ ],
1054
+ "pagination": {
1055
+ "total": 120,
1056
+ "limit": 50,
1057
+ "offset": 0,
1058
+ "hasMore": true
1059
+ }
1060
+ }
1061
+ ```
1062
+
1063
+ ### Create Wallet
1064
+
1065
+ ```http
1066
+ POST /wallet/create
1067
+ Authorization: Bearer <token>
1068
+ Content-Type: application/json
1069
+
1070
+ {
1071
+ "tier": "hot", // or "temp"
1072
+ "chain": "base", // Optional: "base", "ethereum", "solana", "solana-devnet" (default: "base")
1073
+ "name": "Trading",
1074
+ "color": "#ff4d00",
1075
+ "emoji": "🔥",
1076
+ "vaultId": "vault-abc123" // Optional: create under a specific vault (default: primary)
1077
+ }
1078
+ ```
1079
+
1080
+ Creates a new hot or temp wallet. When `vaultId` is provided, the wallet is created under the specified vault and its private key is encrypted with that vault's mnemonic. If omitted, the primary vault is used.
1081
+
1082
+ ### Search Wallets
1083
+
1084
+ ```http
1085
+ GET /wallets/search?q=trading
1086
+ Authorization: Bearer <token> (optional)
1087
+ ```
1088
+
1089
+ Searches hot wallets by name or address. Agents with tokens only see their accessible wallets. Includes balance information.
1090
+
1091
+ **Query params:**
1092
+ - `q` (required): Search query string
1093
+
1094
+ **Response:**
1095
+ ```json
1096
+ {
1097
+ "success": true,
1098
+ "wallets": [
1099
+ {
1100
+ "address": "0x...",
1101
+ "name": "Trading",
1102
+ "chain": "base",
1103
+ "tier": "hot",
1104
+ "balance": "500000000000000000"
1105
+ }
1106
+ ]
1107
+ }
1108
+ ```
1109
+
1110
+ ### Rename/Update Wallet
1111
+
1112
+ ```http
1113
+ POST /wallet/rename
1114
+ Authorization: Bearer <token>
1115
+ Content-Type: application/json
1116
+
1117
+ {
1118
+ "address": "0x...",
1119
+ "name": "New Name",
1120
+ "color": "#ff4d00",
1121
+ "emoji": "🔥",
1122
+ "description": "Trading wallet",
1123
+ "hidden": false
1124
+ }
1125
+ ```
1126
+
1127
+ Updates hot wallet metadata. Requires `wallet:rename` permission and wallet access. All fields except `address` are optional.
1128
+
1129
+ ### Export Wallet Private Key
1130
+
1131
+ ```http
1132
+ POST /wallet/:address/export
1133
+ Authorization: Bearer <token> (optional)
1134
+ ```
1135
+
1136
+ Exports the private key for a hot wallet. Requires the vault to be unlocked. Agents need `wallet:export` permission and wallet access. Humans (no token) can export when unlocked.
1137
+
1138
+ **Response:**
1139
+ ```json
1140
+ {
1141
+ "success": true,
1142
+ "address": "0x...",
1143
+ "privateKey": "0x..."
1144
+ }
1145
+ ```
1146
+
1147
+ ### Send Transaction
1148
+
1149
+ ```http
1150
+ POST /send
1151
+ Authorization: Bearer <token>
1152
+ Content-Type: application/json
1153
+
1154
+ {
1155
+ "from": "0x...", // Hot wallet address (EVM or Solana base58)
1156
+ "to": "0x...", // Recipient address or ENS name (e.g. "vitalik.eth")
1157
+ "amount": "100000000000000000", // Amount in wei (EVM) or lamports (Solana). 0.1 ETH = 100000000000000000 wei, 0.1 SOL = 100000000 lamports.
1158
+ "tokenAddress": "0x...", // Optional: ERC-20/SPL token contract address for token sends
1159
+ "chain": "base", // Optional: chain to send on (default: configured default)
1160
+ "description": "..." // Optional: description for transaction history
1161
+ }
1162
+ ```
1163
+
1164
+ Sends native currency or tokens from a hot wallet. Supports both EVM chains (ETH) and Solana (SOL). **Amounts must be in wei (EVM, 18 decimals) or lamports (Solana, 9 decimals).** Send spending limit enforced for agent tokens (if `limits.send` is set). Sends to the cold wallet address bypass the limit (returning funds to vault). Admin tokens bypass all limits.
1165
+
1166
+ **ENS resolution**: The `to` field accepts ENS names (e.g., `"vitalik.eth"`). Names are resolved to addresses before processing.
1167
+
1168
+ #### ERC-20/SPL Token Send
1169
+
1170
+ When `tokenAddress` is provided, the endpoint sends tokens instead of native currency:
1171
+
1172
+ ```http
1173
+ POST /send
1174
+ Authorization: Bearer <token>
1175
+ Content-Type: application/json
1176
+
1177
+ {
1178
+ "from": "0x...",
1179
+ "to": "0x...",
1180
+ "amount": "1000000", // Token amount in raw units (e.g. 1 USDC = 1000000 for 6 decimals)
1181
+ "tokenAddress": "0xA0b86991...", // ERC-20 contract address (EVM) or SPL mint address (Solana)
1182
+ "chain": "base"
1183
+ }
1184
+ ```
1185
+
1186
+ - **EVM**: Encodes ERC-20 `transfer(to, amount)` calldata and sends to the token contract
1187
+ - **Solana**: Uses SPL token transfer with automatic ATA creation for the recipient
1188
+ - **Spending limits**: Token sends do NOT count against the native currency send limit (tokens are spent, not ETH/SOL)
1189
+ - Auto-tracks the token after a successful send
1190
+ - Response includes `tokenAddress` and `tokenAmount` instead of `amount`/`value`
1191
+
1192
+ #### Raw Solana Transaction
1193
+
1194
+ For Solana chains, you can submit a pre-built `VersionedTransaction` instead of a simple transfer. This enables interaction with any Solana program (pump.fun, Tensor, Marinade, Raydium, etc.):
1195
+
1196
+ ```http
1197
+ POST /send
1198
+ Authorization: Bearer <token>
1199
+ Content-Type: application/json
1200
+
1201
+ {
1202
+ "from": "5Gh7...", // Solana hot/temp wallet address
1203
+ "transaction": "base64...", // Base64-encoded VersionedTransaction
1204
+ "chain": "solana",
1205
+ "to": "ProgramId...", // Optional: for logging only
1206
+ "description": "Buy on pump.fun bonding curve" // Optional
1207
+ }
1208
+ ```
1209
+
1210
+ When `transaction` is provided:
1211
+ - The transaction is deserialized, signed with the wallet's keypair, and submitted
1212
+ - `to` and `amount` are not required (the transaction encodes its own instructions)
1213
+ - Spending limits are not tracked (value is encoded in instructions, same tradeoff as EVM `data` field)
1214
+ - Permission checks (`send:hot`/`send:temp`, wallet access) still apply
1215
+ - Response includes `type: "program"` and the transaction is logged as type `contract`
1216
+
1217
+ ### Estimate Gas
1218
+
1219
+ ```http
1220
+ POST /send/estimate
1221
+ Content-Type: application/json
1222
+
1223
+ {
1224
+ "from": "0x...",
1225
+ "to": "0x...",
1226
+ "amount": "100000000000000000",
1227
+ "data": "0x...",
1228
+ "chain": "base"
1229
+ }
1230
+ ```
1231
+
1232
+ Estimates gas fees for a transaction (EVM only). No authentication required.
1233
+
1234
+ **Response:**
1235
+ ```json
1236
+ {
1237
+ "success": true,
1238
+ "gasLimit": "21000",
1239
+ "gasPrice": "1000000000",
1240
+ "maxFeePerGas": "2000000000",
1241
+ "maxPriorityFeePerGas": "1000000",
1242
+ "estimatedCostWei": "42000000000000",
1243
+ "estimatedCostEth": "0.000042"
1244
+ }
1245
+ ```
1246
+
1247
+ ### Fund Hot Wallet
1248
+
1249
+ ```http
1250
+ POST /fund
1251
+ Authorization: Bearer <token>
1252
+ Content-Type: application/json
1253
+
1254
+ {
1255
+ "to": "0x...", // Hot wallet to fund (EVM or Solana base58)
1256
+ "amount": "1000000000000000000", // Amount in wei (EVM) or lamports (Solana). 1.0 ETH = 1000000000000000000 wei.
1257
+ "chain": "base" // Optional: chain to fund on (default: configured default)
1258
+ }
1259
+ ```
1260
+
1261
+ Transfers native currency from cold wallet to hot wallet. Supports both EVM (ETH) and Solana (SOL). **Amounts must be in wei (EVM, 18 decimals) or lamports (Solana, 9 decimals).** Spending limit enforced for agent tokens.
1262
+
1263
+ ### Swap Tokens
1264
+
1265
+ ```http
1266
+ POST /swap
1267
+ Authorization: Bearer <token>
1268
+ Content-Type: application/json
1269
+
1270
+ {
1271
+ "from": "0x...", // Hot wallet address (EVM or Solana base58)
1272
+ "token": "0x...", // Token contract/mint address
1273
+ "direction": "buy", // "buy" or "sell"
1274
+ "amount": "100000000000000000", // Amount in wei (EVM) or lamports (Solana). For buy: native currency amount. For sell: token amount in base units.
1275
+ "slippage": 1, // Required: slippage tolerance % (e.g. 1.0 for 1%)
1276
+ "minOut": "...", // Alternative to slippage: explicit minimum output amount (EVM only)
1277
+ "dex": "relay", // Optional: "relay" (default), "uniswap", or "jupiter" (Solana)
1278
+ "chain": "base", // Optional: chain to swap on (default: configured default)
1279
+ "chainOut": "ethereum", // Optional: destination chain for cross-chain swaps (Relay only)
1280
+ "description": "..." // Optional: description for transaction history
1281
+ }
1282
+ ```
1283
+
1284
+ Swaps tokens via DEX. On EVM chains, uses Relay (relay.link) as the default swap provider. Relay is an aggregator that supports all major EVM chains (Base, Ethereum, Arbitrum, Optimism, Polygon, and more). Uniswap is available as a fallback via `dex: "uniswap"` (Base only). On Solana, uses Jupiter aggregator. Creates Transaction record and auto-tracks the swapped token.
1285
+
1286
+ **Cross-chain swaps**: Set `chainOut` to a different chain name (e.g., `"ethereum"`) to perform a cross-chain swap via Relay. Cross-chain is only supported with Relay (the default DEX). If `chainOut` is omitted, the swap stays on the origin chain.
1287
+
1288
+ **App fee**: Relay swaps include a 1% app fee (Relay retains 25%, AuraWallet retains 75%).
1289
+
1290
+ **Slippage protection**: Either `slippage` or `minOut` must be provided. Slippage of 0% is rejected. Minimum floor: 0.5% for admin (manual swaps), 1% for agents (automated). Maximum: 50%.
1291
+
1292
+ ### Swap Quote (Preview)
1293
+
1294
+ ```http
1295
+ POST /swap/quote
1296
+ Authorization: Bearer <token>
1297
+ Content-Type: application/json
1298
+
1299
+ {
1300
+ "from": "0x...", // Hot wallet address
1301
+ "token": "0x...", // Token contract/mint address
1302
+ "direction": "buy", // "buy" or "sell"
1303
+ "amount": "100000000000000000", // Amount in wei/lamports
1304
+ "slippage": 1, // Optional: slippage tolerance %
1305
+ "dex": "relay", // Optional: DEX to quote from
1306
+ "chain": "base", // Optional: chain
1307
+ "chainOut": "ethereum" // Optional: destination chain (Relay only)
1308
+ }
1309
+ ```
1310
+
1311
+ Returns a swap quote without executing. Same auth and validation as `POST /swap` (requires `swap` permission + wallet access), but no transaction is created and no spending limit is consumed.
1312
+
1313
+ **Response (Relay):**
1314
+ ```json
1315
+ {
1316
+ "success": true,
1317
+ "inputAmount": "100000000000000000",
1318
+ "inputFormatted": "0.1",
1319
+ "inputUsd": "350.00",
1320
+ "outputAmount": "350000000",
1321
+ "outputFormatted": "350.0",
1322
+ "outputUsd": "350.00",
1323
+ "rate": "3500.0",
1324
+ "fees": { "gas": { "amount": "21000", "amountUsd": "0.05" } },
1325
+ "slippage": 1,
1326
+ "dex": "relay",
1327
+ "chain": "base"
1328
+ }
1329
+ ```
1330
+
1331
+ **Response (Jupiter/Solana):**
1332
+ ```json
1333
+ {
1334
+ "success": true,
1335
+ "inputAmount": "100000000",
1336
+ "outputAmount": "5000000000",
1337
+ "priceImpact": "0.12",
1338
+ "route": [{ "label": "Raydium", "percent": 100, "inAmount": "100000000", "outAmount": "5000000000" }],
1339
+ "slippage": 1,
1340
+ "dex": "jupiter",
1341
+ "chain": "solana"
1342
+ }
1343
+ ```
1344
+
1345
+ ### List Available DEXes
1346
+
1347
+ ```http
1348
+ GET /swap/dexes
1349
+ ```
1350
+
1351
+ Lists all available DEX adapters and their configurations. No authentication required.
1352
+
1353
+ **Response:**
1354
+ ```json
1355
+ {
1356
+ "success": true,
1357
+ "dexes": [
1358
+ { "id": "relay", "name": "Relay", "chains": ["base", "ethereum", "arbitrum", "optimism"] },
1359
+ { "id": "uniswap", "name": "Uniswap", "chains": ["base"] },
1360
+ { "id": "jupiter", "name": "Jupiter", "chains": ["solana"] }
1361
+ ]
1362
+ }
1363
+ ```
1364
+
1365
+ ### Launch Token
1366
+
1367
+ ```http
1368
+ POST /launch
1369
+ Authorization: Bearer <token>
1370
+ Content-Type: application/json
1371
+
1372
+ {
1373
+ "from": "0x...", // Hot wallet address
1374
+ "name": "My Token", // Token name
1375
+ "symbol": "MTK", // Token symbol
1376
+ "tokenURI": "https://...", // Optional: explicit token metadata URI (overrides imageUrl/metadata)
1377
+ "imageUrl": "https://telegra.ph/file/abc.jpg", // Optional: public image URL for token
1378
+ "metadata": { // Optional: extra metadata fields (description, website, twitter, etc.)
1379
+ "description": "A fair launch token",
1380
+ "website": "https://example.com"
1381
+ },
1382
+ "type": "multicurve", // Optional: "static", "dynamic", or "multicurve" (default)
1383
+ "initialSupply": "1000000000", // Optional: total supply (default: 1B)
1384
+ "numTokensToSell": "900000000", // Optional: tokens for sale (default: 90% of supply)
1385
+ "preset": "medium", // Optional: market cap preset ("low", "medium", "high")
1386
+ "migration": "uniswapV2", // Optional: "uniswapV2" (default), "uniswapV3", "uniswapV4", "noOp"
1387
+ "vestingDuration": 31536000, // Optional: vesting period in seconds
1388
+ "startTime": 1707100000, // Optional: scheduled launch (Unix timestamp, multicurve only)
1389
+ "governance": "default", // Optional: "default" or "noOp"
1390
+ "beneficiaries": [ // Optional: fee recipients for the launched pool
1391
+ { "address": "0x...", "shares": "0.5" }, // shares in ETH units (0.5 = 50%)
1392
+ { "address": "0x...", "shares": "0.5" }
1393
+ ],
1394
+ "chain": "base", // Optional: chain (default: configured default)
1395
+ "description": "..." // Optional: description for transaction history
1396
+ }
1397
+ ```
1398
+
1399
+ Launches a new token via the [Doppler protocol](https://doppler.lol) fair launch mechanism. Uses the Doppler SDK to create token auctions on Uniswap. Requires `launch` permission. Creates Transaction record (type: 'launch') and auto-tracks the launched token.
1400
+
1401
+ **Auction types:**
1402
+ - `multicurve` (default): Multicurve initializer using Uniswap V4, supports market cap presets and scheduled launches
1403
+ - `static`: Fixed price range using Uniswap V3, ideal for simple price discovery
1404
+ - `dynamic`: Gradual Dutch auction using Uniswap V4 hooks
1405
+
1406
+ **Market cap presets** (multicurve only): `low` (~$7.5k-$30k), `medium` (~$50k-$150k), `high` (~$250k-$750k).
1407
+
1408
+ **Beneficiaries** (optional): Array of `{ address, shares }` specifying fee recipients for the launched pool. Shares are in ETH units (e.g. `"0.5"` = 50%, shares must sum to `"1.0"` = 100%). Supported on multicurve and static auction types. Ignored on dynamic auctions (SDK limitation).
1409
+
1410
+ **Token metadata:** If `tokenURI` is not provided but `imageUrl` or `metadata` is, the server auto-builds a metadata JSON from name, symbol, imageUrl, and any extra metadata fields, then encodes it as a `data:application/json;base64,...` data URI for the on-chain tokenURI. The agent is responsible for hosting the image at a publicly accessible URL (e.g. upload to [telegra.ph](https://telegra.ph) which requires no API key or signup). If `tokenURI` is explicitly provided, it takes precedence.
1411
+
1412
+ **Supported chains:** Base, Ethereum, Ink, Unichain (any chain supported by Doppler protocol).
1413
+
1414
+ ### Collect Fees (Single Token)
1415
+
1416
+ ```http
1417
+ POST /launch/:tokenAddress/collect-fees
1418
+ Authorization: Bearer <token>
1419
+ Content-Type: application/json
1420
+
1421
+ {
1422
+ "from": "0x...", // Wallet address to pay gas
1423
+ "chain": "base" // Optional: chain (default: configured default)
1424
+ }
1425
+ ```
1426
+
1427
+ Collects accumulated trading fees from a Doppler multicurve pool and distributes them to the configured beneficiaries. The `collectFees` call is permissionless on-chain — anyone can trigger it, but fees always go to the beneficiary addresses configured at launch time. The caller only pays gas. No `launch` permission required, only valid auth token and wallet access for the gas-paying wallet.
1428
+
1429
+ **Response:**
1430
+ ```json
1431
+ {
1432
+ "success": true,
1433
+ "tokenAddress": "0x...",
1434
+ "fees0": "1234567890",
1435
+ "fees1": "9876543210",
1436
+ "transactionHash": "0x...",
1437
+ "chain": "base"
1438
+ }
1439
+ ```
1440
+
1441
+ ### Collect Fees (All Launched Tokens)
1442
+
1443
+ ```http
1444
+ POST /launch/collect-fees
1445
+ Authorization: Bearer <token>
1446
+ Content-Type: application/json
1447
+
1448
+ {
1449
+ "from": "0x...", // Wallet address to pay gas
1450
+ "chain": "base" // Optional: chain (default: configured default)
1451
+ }
1452
+ ```
1453
+
1454
+ Collects fees from ALL tokens previously launched via AuraWallet on the specified chain. Iterates over all `launch` transactions in the database and calls `collectFees()` on each. Individual failures are reported per-token without failing the entire request. Same permissionless semantics as the single-token endpoint.
1455
+
1456
+ **Response:**
1457
+ ```json
1458
+ {
1459
+ "success": true,
1460
+ "chain": "base",
1461
+ "total": 5,
1462
+ "collected": 4,
1463
+ "failed": 1,
1464
+ "results": [
1465
+ { "tokenAddress": "0x...", "success": true, "fees0": "...", "fees1": "...", "transactionHash": "0x..." },
1466
+ { "tokenAddress": "0x...", "success": false, "error": "Pool not found" }
1467
+ ]
1468
+ }
1469
+ ```
1470
+
1471
+ ---
1472
+
1473
+ ## Wallet Data Endpoints
1474
+
1475
+ ### List Transactions
1476
+
1477
+ ```http
1478
+ GET /wallet/:address/transactions
1479
+ Authorization: Bearer <token> (optional for own wallets, not required for external)
1480
+ ```
1481
+
1482
+ **Two modes:**
1483
+
1484
+ 1. **DB path** (our wallets): When the address belongs to a HotWallet in our DB, returns transaction records from the database. Response includes `"source": "db"`.
1485
+
1486
+ 2. **On-chain fallback** (external addresses): When the address is not in our HotWallet table, fetches events from the chain via `eth_getLogs` (EVM) or `getSignaturesForAddress` (Solana). No auth required. Response includes `"source": "on-chain"`, `chain`, and `blockRange`.
1487
+
1488
+ **DB path query params:**
1489
+ - `type`: Filter by type (send, receive, swap, contract, manual)
1490
+ - `status`: Filter by status (confirmed, pending)
1491
+ - `token`: Filter by token address
1492
+ - `search`: Search description, txHash, from, to
1493
+ - `limit`: Max results (default 50, max 250)
1494
+ - `offset`: Pagination offset
1495
+ - `sortBy`: Sort field (default: createdAt)
1496
+ - `sortDir`: Sort direction (asc, desc)
1497
+
1498
+ **On-chain path query params:**
1499
+ - `chain`: Chain to query (default: base). Use `solana` or `solana-devnet` for Solana.
1500
+ - `limit`: Max results (1-100, default: 20)
1501
+ - `types`: Comma-separated event type filter (transfer, swap, swap_v2, swap_v3, swap_v4, approval, wrap)
1502
+ - `token`: Token contract address — when set, queries logs emitted BY the token contract (using the `address` field in `eth_getLogs`) instead of topic-based wallet matching. Useful for fetching all Transfer events for a specific token.
1503
+ - `fromBlock`: Start block (default: latest - 10000). EVM only.
1504
+ - `toBlock`: End block (default: latest). EVM only.
1505
+
1506
+ **V4 swap auto-correlation:** For wallet-level queries (no `token` param), the fetcher automatically discovers Uniswap V4 Swap events. V4 Swap topics don't contain the wallet address (topic1 = poolId, topic2 = Universal Router), so the fetcher looks for Transfer events without matching swaps ("orphan transfers") and queries the V4 PoolManager at those blocks to find correlated V4 Swap events sharing the same txHash.
1507
+
1508
+ **On-chain response format:**
1509
+ ```json
1510
+ {
1511
+ "success": true,
1512
+ "source": "on-chain",
1513
+ "chain": "base",
1514
+ "blockRange": { "from": "90000", "to": "100000" },
1515
+ "transactions": [
1516
+ {
1517
+ "type": "transfer",
1518
+ "summary": "Received 500 USDC from 0x1234...abcd",
1519
+ "txHash": "0x...",
1520
+ "blockNumber": "99500",
1521
+ "timestamp": 1700000000,
1522
+ "details": { "from": "0x...", "to": "0x...", "amount": "500", "symbol": "USDC", "direction": "in" }
1523
+ }
1524
+ ],
1525
+ "pagination": { "total": 42, "limit": 20, "returned": 20 }
1526
+ }
1527
+ ```
1528
+
1529
+ Supported event types: Transfer (ERC-20/721), Swap (Uniswap V2/V3/V4), WETH Wrap/Unwrap, Approval. Note: native ETH transfers are not visible via `eth_getLogs`.
1530
+
1531
+ ### Add Transaction
1532
+
1533
+ ```http
1534
+ POST /wallet/:address/transactions
1535
+ Authorization: Bearer <token>
1536
+ Content-Type: application/json
1537
+
1538
+ {
1539
+ "type": "manual", // send, receive, swap, contract, manual
1540
+ "txHash": "0x...", // Optional
1541
+ "amount": "0.5", // Optional: ETH amount
1542
+ "tokenAddress": "0x...", // Optional: token contract
1543
+ "tokenAmount": "...", // Optional: token amount
1544
+ "from": "0x...", // Optional
1545
+ "to": "0x...", // Optional
1546
+ "description": "...", // Optional
1547
+ "executedAt": "..." // Optional: ISO timestamp
1548
+ }
1549
+ ```
1550
+
1551
+ Requires `wallet:tx:add` permission.
1552
+
1553
+ ### List Tracked Assets
1554
+
1555
+ ```http
1556
+ GET /wallet/:address/assets
1557
+ Authorization: Bearer <token> (optional)
1558
+ ```
1559
+
1560
+ Returns tracked assets for a wallet with USD pricing. Each asset includes `priceUsd` (current token price) and `valueUsd` (balance × price) when price data is available. Prices are fetched via the same cascading fallback as `GET /price/:address` (DexScreener → CoinGecko → Alchemy).
1561
+
1562
+ Query params:
1563
+ - `search`: Search symbol, name, or address
1564
+ - `includeHidden`: Include hidden assets (default: false)
1565
+ - `limit`, `offset`, `sortBy`, `sortDir`: Pagination/sorting
1566
+
1567
+ ### Add Tracked Asset
1568
+
1569
+ ```http
1570
+ POST /wallet/:address/asset
1571
+ Authorization: Bearer <token>
1572
+ Content-Type: application/json
1573
+
1574
+ {
1575
+ "tokenAddress": "0x...", // Required
1576
+ "symbol": "TKN", // Optional
1577
+ "name": "Token Name", // Optional
1578
+ "decimals": 18, // Optional (default: 18)
1579
+ "chain": "base", // Optional (default: base)
1580
+ "isHidden": false // Optional
1581
+ }
1582
+ ```
1583
+
1584
+ Requires `wallet:asset:add` permission. Upserts if token already tracked.
1585
+
1586
+ ### Portfolio Overview
1587
+
1588
+ ```http
1589
+ GET /portfolio
1590
+ Authorization: Bearer <token> (optional)
1591
+ ```
1592
+
1593
+ Returns an aggregated portfolio view across all wallets. Native balances are grouped by chain, token balances are grouped by token address. Includes cached ETH/SOL USD prices and per-token USD values.
1594
+
1595
+ Agents with tokens need `wallet:list` permission to see all wallets. Without auth (human), returns all.
1596
+
1597
+ **Query params:**
1598
+ - `token` — Filter by token contract address. Returns only that token's aggregated balance plus a `wallets` array with per-wallet breakdown.
1599
+ - `symbol` — Filter by token symbol (case-insensitive). Same behavior as `token` filter.
1600
+ - `chain` — Filter by chain name (e.g., `base`, `ethereum`, `solana`). Applies to both native and token balances.
1601
+
1602
+ **Example — filter by token:**
1603
+ ```bash
1604
+ GET /portfolio?token=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
1605
+ ```
1606
+
1607
+ **Response:**
1608
+ ```json
1609
+ {
1610
+ "success": true,
1611
+ "byChain": [
1612
+ { "chain": "base", "totalBalance": 4.0, "walletCount": 2, "valueUsd": "12002.00" },
1613
+ { "chain": "ethereum", "totalBalance": 10.0, "walletCount": 1, "valueUsd": "30005.00" }
1614
+ ],
1615
+ "byToken": [
1616
+ {
1617
+ "tokenAddress": "0xaaa...",
1618
+ "chain": "base",
1619
+ "symbol": "TKN",
1620
+ "name": "Test Token",
1621
+ "totalBalance": 300.75,
1622
+ "walletCount": 2,
1623
+ "priceUsd": "1.00",
1624
+ "valueUsd": "300.75"
1625
+ }
1626
+ ],
1627
+ "prices": { "ETH": 3000.50, "SOL": 150.25 },
1628
+ "totalValueUsd": "42307.75"
1629
+ }
1630
+ ```
1631
+
1632
+ **Response with `token` or `symbol` filter** (includes per-wallet breakdown):
1633
+ ```json
1634
+ {
1635
+ "success": true,
1636
+ "byChain": [],
1637
+ "byToken": [
1638
+ {
1639
+ "tokenAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
1640
+ "chain": "base",
1641
+ "symbol": "USDC",
1642
+ "name": "USD Coin",
1643
+ "totalBalance": 800.0,
1644
+ "walletCount": 2,
1645
+ "priceUsd": "1.00",
1646
+ "valueUsd": "800.00"
1647
+ }
1648
+ ],
1649
+ "wallets": [
1650
+ { "walletAddress": "0xaaa...", "chain": "base", "balance": 500, "valueUsd": "500.00" },
1651
+ { "walletAddress": "0xbbb...", "chain": "base", "balance": 300, "valueUsd": "300.00" }
1652
+ ],
1653
+ "prices": { "ETH": 3000.50, "SOL": 150.25 },
1654
+ "totalValueUsd": "800.00"
1655
+ }
1656
+ ```
1657
+
1658
+ ### Remove Tracked Asset
1659
+
1660
+ ```http
1661
+ DELETE /wallet/:address/asset/:assetId
1662
+ Authorization: Bearer <token>
1663
+ ```
1664
+
1665
+ Removes a tracked asset from the wallet. Requires `wallet:asset:remove` permission.
1666
+
1667
+ Emits `asset:changed` event with `removed: true`.
1668
+
1669
+ ---
1670
+
1671
+ ## Address Book
1672
+
1673
+ Label external addresses with nicknames, emojis, and colors.
1674
+
1675
+ ### List Address Labels
1676
+
1677
+ ```
1678
+ GET /address-labels?q=search_term
1679
+ ```
1680
+
1681
+ Returns all labels, optionally filtered by search query (matches label or address).
1682
+
1683
+ ### Create/Update Address Label
1684
+
1685
+ ```
1686
+ POST /address-labels
1687
+ {
1688
+ "address": "0x1234...",
1689
+ "label": "Vitalik",
1690
+ "emoji": "🦄", // optional
1691
+ "color": "#FF5733", // optional
1692
+ "notes": "ETH co-founder" // optional
1693
+ }
1694
+ ```
1695
+
1696
+ Requires `addressbook:write` permission. Upserts by address (lowercased).
1697
+
1698
+ `createdBy` is auto-set: `"human"` for admin tokens, agent ID for agent tokens.
1699
+
1700
+ ### Delete Address Label
1701
+
1702
+ ```
1703
+ DELETE /address-labels/:id
1704
+ ```
1705
+
1706
+ Requires `addressbook:write` permission.
1707
+
1708
+ ---
1709
+
1710
+ ## Bookmarks (Token Watchlist)
1711
+
1712
+ Bookmark tokens without owning them. Creates a `TrackedAsset` row with `walletAddress: null`.
1713
+
1714
+ ### List Bookmarks
1715
+
1716
+ ```
1717
+ GET /bookmarks?chain=base&q=search_term
1718
+ ```
1719
+
1720
+ Returns all bookmarks, enriched with `TokenMetadata` when available.
1721
+
1722
+ ### Create Bookmark
1723
+
1724
+ ```
1725
+ POST /bookmarks
1726
+ {
1727
+ "tokenAddress": "0xabcd...",
1728
+ "chain": "base" // optional, defaults to "base"
1729
+ }
1730
+ ```
1731
+
1732
+ Requires `bookmark:write` permission. Idempotent — re-creating the same bookmark is a no-op. Seeds `TokenMetadata` cache on creation.
1733
+
1734
+ ### Delete Bookmark
1735
+
1736
+ ```
1737
+ DELETE /bookmarks/:id
1738
+ ```
1739
+
1740
+ Requires `bookmark:write` permission. Only deletes bookmarks (null walletAddress), not wallet-tracked assets.
1741
+
1742
+ ---
1743
+
1744
+ ## System Defaults (Admin Only)
1745
+
1746
+ Centralized management of system-wide defaults (limits, permissions, TTLs, rate limits, etc.).
1747
+
1748
+ All endpoints require `admin:*` permission.
1749
+
1750
+ ### List Defaults
1751
+
1752
+ ```http
1753
+ GET /defaults
1754
+ Authorization: Bearer <admin-token>
1755
+ ```
1756
+
1757
+ Returns all defaults grouped by type.
1758
+
1759
+ **Response:**
1760
+ ```json
1761
+ {
1762
+ "success": true,
1763
+ "defaults": {
1764
+ "financial": [
1765
+ { "key": "limits.fund", "value": 0.1, "type": "financial", "label": "Default Fund Limit (ETH)", "description": "...", "updatedAt": "..." }
1766
+ ],
1767
+ "permissions": [...],
1768
+ "ttl": [...],
1769
+ "rate_limit": [...],
1770
+ "swap": [...],
1771
+ "ai_safety": [...],
1772
+ "launch": [...],
1773
+ "app": [...]
1774
+ }
1775
+ }
1776
+ ```
1777
+
1778
+ ### Update Default
1779
+
1780
+ ```http
1781
+ PATCH /defaults/:key
1782
+ Authorization: Bearer <admin-token>
1783
+ Content-Type: application/json
1784
+
1785
+ { "value": 0.05 }
1786
+ ```
1787
+
1788
+ Updates a single default value. Validates type against seed definition.
1789
+
1790
+ **Response:**
1791
+ ```json
1792
+ { "success": true, "key": "limits.fund", "value": 0.05 }
1793
+ ```
1794
+
1795
+ ### Reset Default
1796
+
1797
+ ```http
1798
+ POST /defaults/reset
1799
+ Authorization: Bearer <admin-token>
1800
+ Content-Type: application/json
1801
+
1802
+ { "key": "limits.fund" }
1803
+ ```
1804
+
1805
+ Resets a single key to its seed value. Use `"key": "*"` to reset all defaults.
1806
+
1807
+ **Response:**
1808
+ ```json
1809
+ { "success": true, "key": "limits.fund", "reset": true }
1810
+ ```
1811
+
1812
+ ---
1813
+
1814
+ ## Configuration Endpoints (Require Auth)
1815
+
1816
+ ### Credential Vault Management (Admin)
1817
+
1818
+ #### List Credential Vaults
1819
+
1820
+ ```http
1821
+ GET /vaults/credential
1822
+ Authorization: Bearer <admin-token>
1823
+ ```
1824
+
1825
+ Returns wallet vaults with credential unlock status and credential counts.
1826
+
1827
+ #### Create Credential Vault
1828
+
1829
+ ```http
1830
+ POST /vaults/credential
1831
+ Authorization: Bearer <admin-token>
1832
+ Content-Type: application/json
1833
+
1834
+ {
1835
+ "encrypted": "<rsa-oaep password>",
1836
+ "name": "work"
1837
+ }
1838
+ ```
1839
+
1840
+ Creates an additional vault and unlocks it.
1841
+
1842
+ #### Lock Credential Vault
1843
+
1844
+ ```http
1845
+ POST /vaults/credential/:id/lock
1846
+ Authorization: Bearer <admin-token>
1847
+ ```
1848
+
1849
+ Locks the vault and clears credential subkeys from memory.
1850
+
1851
+ #### Delete Credential Vault
1852
+
1853
+ ```http
1854
+ DELETE /vaults/credential/:id
1855
+ Authorization: Bearer <admin-token>
1856
+ ```
1857
+
1858
+ Deletes the vault and all credentials assigned to it.
1859
+
1860
+ ### Credential Management
1861
+
1862
+ #### List Credentials (Metadata)
1863
+
1864
+ ```http
1865
+ GET /credentials?vault=<id>&type=<type>&tag=<tag>&q=<query>
1866
+ Authorization: Bearer <token>
1867
+ ```
1868
+
1869
+ Requires `secret:read` (or `admin:*`). Results are scope-filtered by `credentialAccess.read`.
1870
+
1871
+ #### Create Credential
1872
+
1873
+ ```http
1874
+ POST /credentials
1875
+ Authorization: Bearer <token>
1876
+ Content-Type: application/json
1877
+
1878
+ {
1879
+ "vaultId": "primary",
1880
+ "type": "login",
1881
+ "name": "GitHub",
1882
+ "meta": { "tags": ["deploy"] },
1883
+ "fields": [
1884
+ { "key": "username", "value": "alice", "type": "text", "sensitive": false },
1885
+ { "key": "password", "value": "hunter2", "type": "secret", "sensitive": true }
1886
+ ]
1887
+ }
1888
+ ```
1889
+
1890
+ Requires `secret:write` (or `admin:*`) and matching write scope.
1891
+
1892
+ #### Read Credential (Encrypted Response)
1893
+
1894
+ ```http
1895
+ POST /credentials/:id/read
1896
+ Authorization: Bearer <token>
1897
+ ```
1898
+
1899
+ Requires `secret:read` (or `admin:*`), matching read scope, and `agentPubkey` on the token.
1900
+ Enforces `credentialAccess.ttl` and `credentialAccess.maxReads`.
1901
+
1902
+ **Response:**
1903
+
1904
+ ```json
1905
+ {
1906
+ "success": true,
1907
+ "credentialId": "cred-abc123",
1908
+ "encrypted": "<base64 ciphertext>"
1909
+ }
1910
+ ```
1911
+
1912
+ `encrypted` may be direct RSA-OAEP ciphertext (small payloads) or a base64-encoded hybrid envelope (RSA-wrapped AES key + AES-GCM data) for larger payloads.
1913
+
1914
+ ### API Key Management
1915
+
1916
+ #### List API Keys
1917
+
1918
+ ```http
1919
+ GET /apikeys
1920
+ Authorization: Bearer <token>
1921
+ ```
1922
+
1923
+ Permission: `apikey:get` (or `trade:all`)
1924
+
1925
+ Returns masked API key entries served from credential vault storage (`type: "apikey"`).
1926
+
1927
+ #### Create/Update API Key
1928
+
1929
+ ```http
1930
+ POST /apikeys
1931
+ Authorization: Bearer <token>
1932
+ Content-Type: application/json
1933
+
1934
+ {
1935
+ "service": "alchemy",
1936
+ "name": "default",
1937
+ "key": "your-api-key"
1938
+ }
1939
+ ```
1940
+
1941
+ Permission: `apikey:set`
1942
+
1943
+ Upserts by `service` + `name` composite key.
1944
+ The value is stored in credential vault as an encrypted `apikey` credential (legacy DB row is kept in sync for compatibility).
1945
+
1946
+ #### Validate API Key
1947
+
1948
+ ```http
1949
+ POST /apikeys/validate
1950
+ Authorization: Bearer <token>
1951
+ Content-Type: application/json
1952
+
1953
+ {
1954
+ "service": "alchemy",
1955
+ "key": "your-api-key"
1956
+ }
1957
+ ```
1958
+
1959
+ Permission: `apikey:set`
1960
+
1961
+ Validates an API key against its external service before saving. All validation calls have a 5-second timeout.
1962
+
1963
+ **Supported services:**
1964
+
1965
+ | Service | Validation | Success Info |
1966
+ |---------|-----------|--------------|
1967
+ | `alchemy` | `eth_blockNumber` JSON-RPC call | — |
1968
+ | `anthropic` | Minimal Messages API request (200 or 429 = valid) | — |
1969
+ | `openai` | OpenAI Models API (200 = valid) | — |
1970
+ | `adapter:telegram` | Telegram Bot API `getMe` | `{ botUsername }` |
1971
+
1972
+ **Response:**
1973
+ ```json
1974
+ { "valid": true, "info": { "botUsername": "MyBot" } }
1975
+ ```
1976
+
1977
+ ```json
1978
+ { "valid": false, "error": "Invalid API key" }
1979
+ ```
1980
+
1981
+ #### Delete API Key
1982
+
1983
+ ```http
1984
+ DELETE /apikeys/:id
1985
+ Authorization: Bearer <token>
1986
+ ```
1987
+
1988
+ Permission: `apikey:set`
1989
+
1990
+ Soft-deletes by setting `isActive = false`.
1991
+
1992
+ ### Adapter Management
1993
+
1994
+ #### List Adapters
1995
+
1996
+ ```http
1997
+ GET /adapters
1998
+ Authorization: Bearer <token>
1999
+ ```
2000
+
2001
+ Permission: `adapter:manage`
2002
+
2003
+ Returns configured adapters with secret status and running state.
2004
+
2005
+ #### Save Adapter Config
2006
+
2007
+ ```http
2008
+ POST /adapters
2009
+ Authorization: Bearer <token>
2010
+ Content-Type: application/json
2011
+
2012
+ {
2013
+ "type": "telegram",
2014
+ "enabled": true,
2015
+ "config": { "chatId": "123456789" }
2016
+ }
2017
+ ```
2018
+
2019
+ Permission: `adapter:manage`
2020
+
2021
+ #### Test Adapter
2022
+
2023
+ ```http
2024
+ POST /adapters/test
2025
+ Authorization: Bearer <token>
2026
+ Content-Type: application/json
2027
+
2028
+ {
2029
+ "type": "telegram"
2030
+ }
2031
+ ```
2032
+
2033
+ Permission: `adapter:manage`
2034
+
2035
+ Sends a test message through a configured adapter. Returns 404 if the adapter's required config (bot token, chat ID, webhook URL) is not configured.
2036
+
2037
+ **Supported types:**
2038
+
2039
+ | Type | Behavior |
2040
+ |------|----------|
2041
+ | `telegram` | Sends test message via Telegram Bot API `sendMessage` |
2042
+ | `webhook` | POSTs `{ type: "test", data: {}, timestamp }` to webhook URL |
2043
+
2044
+ **Response:**
2045
+ ```json
2046
+ { "success": true }
2047
+ ```
2048
+
2049
+ ```json
2050
+ { "success": false, "error": "Failed to send test message" }
2051
+ ```
2052
+
2053
+ #### Update Chat Config
2054
+
2055
+ ```http
2056
+ POST /adapters/chat
2057
+ Authorization: Bearer <token>
2058
+ Content-Type: application/json
2059
+
2060
+ {
2061
+ "defaultApp": "swap-chat"
2062
+ }
2063
+ ```
2064
+
2065
+ Permission: `adapter:manage`
2066
+
2067
+ Sets the default app for adapter chat routing. The `defaultApp` determines which app's AI handles incoming chat messages from adapters.
2068
+
2069
+ **Response:**
2070
+ ```json
2071
+ { "success": true, "chat": { "defaultApp": "swap-chat" } }
2072
+ ```
2073
+
2074
+ #### Send Chat Message (Webhook Inbound)
2075
+
2076
+ ```http
2077
+ POST /adapters/:type/message
2078
+ Content-Type: application/json
2079
+ X-Signature-256: sha256=<hmac>
2080
+
2081
+ {
2082
+ "text": "What is my balance?",
2083
+ "senderId": "user-123",
2084
+ "targetApp": "swap-chat"
2085
+ }
2086
+ ```
2087
+
2088
+ Inbound chat endpoint for adapter webhooks. Routes the message to the target app's AI via `handleAppMessage()`.
2089
+
2090
+ **Authentication:** HMAC-SHA256 signature required if the adapter has a secret stored (`POST /apikeys` with `service: "adapter:<type>"`). Uses the same `X-Signature-256` header format as webhook notifications.
2091
+
2092
+ **Request body:**
2093
+ - `text` (required) - Message text
2094
+ - `senderId` (required) - Sender identifier
2095
+ - `targetApp` (optional) - Explicit app target. If omitted, uses `chat.defaultApp` from adapter config.
2096
+
2097
+ **Response:**
2098
+ ```json
2099
+ {
2100
+ "success": true,
2101
+ "reply": "You have 1.5 ETH in your hot wallet.",
2102
+ "error": null
2103
+ }
2104
+ ```
2105
+
2106
+ #### Restart Adapters
2107
+
2108
+ ```http
2109
+ POST /adapters/restart
2110
+ Authorization: Bearer <token>
2111
+ ```
2112
+
2113
+ Permission: `adapter:manage`
2114
+
2115
+ Restarts the approval router with current DB config.
2116
+
2117
+ #### Delete Adapter
2118
+
2119
+ ```http
2120
+ DELETE /adapters/:type
2121
+ Authorization: Bearer <token>
2122
+ ```
2123
+
2124
+ Permission: `adapter:manage`
2125
+
2126
+ ---
2127
+
2128
+ ## Request Types
2129
+
2130
+ When agents call endpoints that require approval:
2131
+
2132
+ | Type | Trigger | What Happens |
2133
+ |------|---------|--------------|
2134
+ | `agent_access` | Agent requests token | Human approves → Token generated |
2135
+ | `fund` | `/fund` endpoint | If over limit → Pending approval |
2136
+ | `send` | `/send` endpoint | Send limit enforced (if `limits.send` set). Cold wallet returns bypass limit |
2137
+ | `launch` | `/launch` endpoint | Launch limit enforced (if `limits.launch` set) |
2138
+
2139
+ ---
2140
+
2141
+ ## WebSocket Events
2142
+
2143
+ The wallet server broadcasts events to `ws://localhost:4748`:
2144
+
2145
+ | Event | Description |
2146
+ |-------|-------------|
2147
+ | `token:created` | New agent token issued |
2148
+ | `token:revoked` | Token was revoked |
2149
+ | `token:spent` | Token spending updated |
2150
+ | `vault:unlocked` | Vault was unlocked |
2151
+ | `action:created` | New human action pending |
2152
+ | `action:resolved` | Human action approved/rejected |
2153
+ | `wallet:created` | New wallet created |
2154
+ | `wallet:changed` | Wallet data updated |
2155
+ | `asset:changed` | Token asset tracked or pool info updated |
2156
+ | `tx:created` | New transaction recorded |
2157
+ | `balance:updated` | Cached balance synced (from cron server) |
2158
+
2159
+ ### asset:changed Event
2160
+
2161
+ Emitted when:
2162
+ - A new token is tracked for a wallet
2163
+ - Pool detection discovers DEX pool info
2164
+ - An asset is removed (`removed: true`)
2165
+
2166
+ ```json
2167
+ {
2168
+ "type": "asset:changed",
2169
+ "timestamp": 1707052800000,
2170
+ "source": "express",
2171
+ "data": {
2172
+ "walletAddress": "0x123...",
2173
+ "tokenAddress": "0xabc...",
2174
+ "symbol": "TOKEN",
2175
+ "name": "My Token",
2176
+ "poolAddress": "0xdef...",
2177
+ "poolVersion": "v3",
2178
+ "removed": false
2179
+ }
2180
+ }
2181
+ ```
2182
+
2183
+ ### tx:created Event
2184
+
2185
+ Emitted when:
2186
+ - A send transaction is recorded
2187
+ - A swap transaction is recorded
2188
+ - A manual transaction is added
2189
+
2190
+ ```json
2191
+ {
2192
+ "type": "tx:created",
2193
+ "timestamp": 1707052800000,
2194
+ "source": "express",
2195
+ "data": {
2196
+ "walletAddress": "0x123...",
2197
+ "id": "cuid123",
2198
+ "type": "swap",
2199
+ "txHash": "0x789...",
2200
+ "amount": "0.1",
2201
+ "tokenAddress": "0xabc...",
2202
+ "description": "Bought TOKEN with 0.1 ETH"
2203
+ }
2204
+ }
2205
+ ```
2206
+
2207
+ ---
2208
+
2209
+ ## AI Status (Admin Only)
2210
+
2211
+ ### Get AI Provider Status
2212
+
2213
+ ```http
2214
+ GET /ai/status
2215
+ Authorization: Bearer <admin-token>
2216
+ ```
2217
+
2218
+ Returns the active AI provider, default model, and availability status of all providers. Used by the SystemDefaultsApp to populate the AI Engine settings.
2219
+
2220
+ **Response:**
2221
+ ```json
2222
+ {
2223
+ "activeProvider": "claude-cli",
2224
+ "defaultModel": "sonnet",
2225
+ "providers": [
2226
+ { "mode": "claude-cli", "label": "Claude Max (CLI)", "available": true, "reason": "claude CLI found in PATH", "models": ["haiku", "sonnet", "opus"] },
2227
+ { "mode": "claude-api", "label": "Claude API Key", "available": false, "reason": "No Anthropic API key configured", "models": ["haiku", "sonnet", "opus"] },
2228
+ { "mode": "codex-cli", "label": "Codex Max (CLI)", "available": false, "reason": "codex CLI not found in PATH", "models": ["codex-mini", "codex", "codex-max"] },
2229
+ { "mode": "openai-api", "label": "OpenAI API Key", "available": false, "reason": "No OpenAI API key configured", "models": ["codex-mini", "codex", "codex-max"] }
2230
+ ]
2231
+ }
2232
+ ```
2233
+
2234
+ Provider/model selection is configured via the system defaults `ai.provider` and `ai.default_model` (use `PATCH /defaults/:key`).
2235
+
2236
+ ---
2237
+
2238
+ ## Strategy Endpoints
2239
+
2240
+ Strategy endpoints manage strategy templates, creation, install, lifecycle, config/state, and approvals.
2241
+ All endpoints are mounted at `/strategies`.
2242
+
2243
+ ### List Strategies
2244
+
2245
+ ```http
2246
+ GET /strategies
2247
+ Authorization: Bearer <token>
2248
+ ```
2249
+
2250
+ Permission: `strategy:read`
2251
+
2252
+ Returns DB-backed strategies with current runtime/status metadata.
2253
+
2254
+ **Response:**
2255
+ ```json
2256
+ {
2257
+ "success": true,
2258
+ "strategies": [
2259
+ {
2260
+ "id": "strategy-123",
2261
+ "name": "ETH DCA Daily",
2262
+ "enabled": true,
2263
+ "running": false,
2264
+ "ticker": "maintenance",
2265
+ "lastTick": 1760000000000,
2266
+ "lastError": null,
2267
+ "errorCount": 0
2268
+ }
2269
+ ]
2270
+ }
2271
+ ```
2272
+
2273
+ ### List Strategy Templates
2274
+
2275
+ ```http
2276
+ GET /strategies/templates
2277
+ Authorization: Bearer <token>
2278
+ ```
2279
+
2280
+ Permission: `strategy:read`
2281
+
2282
+ Returns the v1 template catalog (`recurring_buy`, `buy_on_drop`, `stop_loss`, `portfolio_report`).
2283
+
2284
+ ### Create Template Strategy
2285
+
2286
+ ```http
2287
+ POST /strategies
2288
+ Authorization: Bearer <token>
2289
+ Content-Type: application/json
2290
+
2291
+ {
2292
+ "template": "recurring_buy",
2293
+ "name": "Buy $100 BNKR Daily",
2294
+ "mode": "headless",
2295
+ "config": {
2296
+ "chain": "base",
2297
+ "wallet": "0x1111111111111111111111111111111111111111",
2298
+ "token": "0x2222222222222222222222222222222222222222",
2299
+ "amountUsd": "100"
2300
+ },
2301
+ "enabled": false
2302
+ }
2303
+ ```
2304
+
2305
+ Permission: `strategy:manage`
2306
+
2307
+ Creates a DB-backed strategy from a supported template. `permissions`/`limits` overrides are rejected for template strategies.
2308
+
2309
+ ### Install Third-Party Strategy
2310
+
2311
+ ```http
2312
+ POST /strategies/install
2313
+ Authorization: Bearer <token>
2314
+ Content-Type: application/json
2315
+ ```
2316
+
2317
+ Permission: `strategy:manage`
2318
+
2319
+ Provide exactly one of:
2320
+ - `source`: local path / git / tarball / zip source
2321
+ - `manifest`: inline strategy manifest
2322
+
2323
+ Supports `enabled`, `mode`, `config`, `name`, and `approve` flags. Third-party strategies with permissions/limits require explicit install approval before enable.
2324
+
2325
+ ### Strategy Runtime Health
2326
+
2327
+ ```http
2328
+ GET /strategies/health
2329
+ Authorization: Bearer <token>
2330
+ ```
2331
+
2332
+ Permission: `strategy:read`
2333
+
2334
+ Returns cron runtime health for strategy execution.
2335
+
2336
+ **Response (healthy):**
2337
+ ```json
2338
+ {
2339
+ "success": true,
2340
+ "strategyRuntime": {
2341
+ "owner": "cron",
2342
+ "cronEnabled": true,
2343
+ "apiEngineStarted": false,
2344
+ "healthy": true,
2345
+ "staleAfterMs": 30000,
2346
+ "isStale": false,
2347
+ "lastSyncAt": "2026-02-14T19:11:22.123Z",
2348
+ "lastStatus": "ok",
2349
+ "lastError": null,
2350
+ "syncCount": 42
2351
+ }
2352
+ }
2353
+ ```
2354
+
2355
+ ### Enable Strategy
2356
+
2357
+ ```http
2358
+ POST /strategies/:id/enable
2359
+ Authorization: Bearer <token>
2360
+ ```
2361
+
2362
+ Permission: `strategy:manage`
2363
+
2364
+ Enables a strategy.
2365
+
2366
+ **Response:**
2367
+ ```json
2368
+ {
2369
+ "success": true,
2370
+ "enabled": true,
2371
+ "owner": "cron-runtime"
2372
+ }
2373
+ ```
2374
+
2375
+ ### Disable Strategy
2376
+
2377
+ ```http
2378
+ POST /strategies/:id/disable
2379
+ Authorization: Bearer <token>
2380
+ ```
2381
+
2382
+ Permission: `strategy:manage`
2383
+
2384
+ Disables a strategy.
2385
+
2386
+ **Response:**
2387
+ ```json
2388
+ {
2389
+ "success": true,
2390
+ "enabled": false,
2391
+ "owner": "cron-runtime"
2392
+ }
2393
+ ```
2394
+
2395
+ ### Toggle Strategy (Compatibility)
2396
+
2397
+ ```http
2398
+ POST /strategies/:id/toggle
2399
+ Authorization: Bearer <token>
2400
+ ```
2401
+
2402
+ Permission: `strategy:manage`
2403
+
2404
+ Compatibility endpoint that flips current enabled state.
2405
+
2406
+ ### Get Strategy Config
2407
+
2408
+ ```http
2409
+ GET /strategies/:id/config
2410
+ Authorization: Bearer <token>
2411
+ ```
2412
+
2413
+ Permission: `strategy:read`
2414
+
2415
+ Returns the effective config (manifest defaults merged with overrides).
2416
+
2417
+ **Response:**
2418
+ ```json
2419
+ {
2420
+ "success": true,
2421
+ "config": { "amount": "0.05", "interval": "daily" },
2422
+ "manifest": { "amount": "0.01", "interval": "daily" },
2423
+ "overrides": { "amount": "0.05" }
2424
+ }
2425
+ ```
2426
+
2427
+ ### Update Strategy Config
2428
+
2429
+ ```http
2430
+ PUT /strategies/:id/config
2431
+ Authorization: Bearer <token>
2432
+ Content-Type: application/json
2433
+
2434
+ {
2435
+ "amount": "0.05"
2436
+ }
2437
+ ```
2438
+
2439
+ Permission: `strategy:manage`
2440
+
2441
+ Sets config overrides. Request body is merged on top of manifest defaults.
2442
+
2443
+ **Response:**
2444
+ ```json
2445
+ {
2446
+ "success": true,
2447
+ "config": { "amount": "0.05", "interval": "daily" }
2448
+ }
2449
+ ```
2450
+
2451
+ ### Approve/Reject Pending Intents
2452
+
2453
+ ```http
2454
+ POST /strategies/:id/approve
2455
+ Authorization: Bearer <token>
2456
+ Content-Type: application/json
2457
+
2458
+ {
2459
+ "approvalId": "approval-123",
2460
+ "approved": true
2461
+ }
2462
+ ```
2463
+
2464
+ Permission: `strategy:manage`
2465
+
2466
+ Resolves pending approval records (`strategy:approve` or `strategy:install:approve`). Set `approved` to `false` to reject.
2467
+
2468
+ ### Get Strategy State (Debug)
2469
+
2470
+ ```http
2471
+ GET /strategies/:id/state
2472
+ Authorization: Bearer <token>
2473
+ ```
2474
+
2475
+ Permission: `strategy:read`
2476
+
2477
+ Returns internal strategy state and pending approvals for debugging.
2478
+
2479
+ **Response:**
2480
+ ```json
2481
+ {
2482
+ "success": true,
2483
+ "state": { "lastPrice": "3200.50", "positions": [] },
2484
+ "pendingApprovals": []
2485
+ }
2486
+ ```
2487
+
2488
+ ### Strategy Action History
2489
+
2490
+ ```http
2491
+ GET /strategies/history
2492
+ Authorization: Bearer <token>
2493
+ ```
2494
+
2495
+ Permission: `strategy:read`
2496
+
2497
+ Query params:
2498
+ - `strategyId`: Filter by strategy ID
2499
+ - `limit`: Max results (default 50, max 250)
2500
+ - `offset`: Pagination offset
2501
+
2502
+ Returns strategy events from the Event table (all events with `strategy:*` type prefix).
2503
+
2504
+ ### Reload Runtime Metadata
2505
+
2506
+ ```http
2507
+ POST /strategies/reload
2508
+ Authorization: Bearer <token>
2509
+ ```
2510
+
2511
+ Permission: `strategy:manage`
2512
+
2513
+ Returns runtime reload metadata. DB-backed strategy rows remain the source of truth.
2514
+
2515
+ ---
2516
+
2517
+ ## Error Responses
2518
+
2519
+ All endpoints return JSON with `success` field:
2520
+
2521
+ ```json
2522
+ {
2523
+ "success": false,
2524
+ "error": "Error message here"
2525
+ }
2526
+ ```
2527
+
2528
+ Common HTTP status codes:
2529
+ - `401` - Unauthorized (missing/invalid token)
2530
+ - `403` - Forbidden (vault locked, insufficient permissions)
2531
+ - `404` - Not found
2532
+ - `400` - Bad request (validation error)
2533
+
2534
+ ---
2535
+
2536
+ ## Frontend API Client
2537
+
2538
+ Use the unified `api` helper from `@/lib/api` for all frontend API calls:
2539
+
2540
+ ```typescript
2541
+ import { api, Api } from '@/lib/api';
2542
+
2543
+ // Wallet operations (Express :4242)
2544
+ const wallets = await api.get(Api.Wallet, '/wallets');
2545
+ await api.post(Api.Wallet, '/send', { from, to, amount }); // amount in wei or lamports
2546
+ await api.post(Api.Wallet, '/swap', { from, token, direction, amount });
2547
+
2548
+ // Workspace operations (Next.js :4747)
2549
+ const workspaces = await api.get(Api.Workspace, '/workspace');
2550
+ await api.post(Api.Workspace, '/workspace', { name: 'My Workspace' });
2551
+
2552
+ // Events (Next.js :4747)
2553
+ const events = await api.get(Api.Events, '/events', { limit: 50, category: 'auth' });
2554
+
2555
+ // Agent dashboard (Next.js :4747)
2556
+ const dashboard = await api.get(Api.AgentDashboard, '/agent-requests');
2557
+ ```
2558
+
2559
+ ### Api Enum
2560
+
2561
+ | Target | Backend | Purpose |
2562
+ |--------|---------|---------|
2563
+ | `Api.Wallet` | Express `:4242` | Wallet operations, auth, agents, transactions |
2564
+ | `Api.Workspace` | Next.js `:4747/api` | Workspace CRUD, app management |
2565
+ | `Api.Events` | Next.js `:4747/api` | Event logs from database |
2566
+ | `Api.AgentDashboard` | Next.js `:4747/api` | Agent dashboard (requests + tokens) |
2567
+
2568
+ ### Available Methods
2569
+
2570
+ - `api.get<T>(target, path, params?)` - GET request with optional query params
2571
+ - `api.post<T>(target, path, body?)` - POST request with optional body
2572
+ - `api.put<T>(target, path, body?)` - PUT request with optional body
2573
+ - `api.patch<T>(target, path, body?)` - PATCH request with optional body
2574
+ - `api.delete<T>(target, path)` - DELETE request
2575
+
2576
+ The helper automatically:
2577
+ - Adds Bearer token from sessionStorage
2578
+ - Constructs the correct base URL based on target
2579
+ - Parses JSON responses and handles errors
2580
+
2581
+ ---
2582
+
2583
+ ## Next.js API Endpoints
2584
+
2585
+ UI-specific endpoints on `:4747`:
2586
+
2587
+ ### Workspace
2588
+
2589
+ | Method | Path | Description |
2590
+ |--------|------|-------------|
2591
+ | GET | `/api/workspace` | List all workspaces |
2592
+ | POST | `/api/workspace` | Create workspace |
2593
+ | GET | `/api/workspace/:id` | Get workspace by ID |
2594
+ | PUT | `/api/workspace/:id` | Update workspace |
2595
+ | DELETE | `/api/workspace/:id` | Delete workspace |
2596
+ | GET | `/api/workspace/:id/apps` | List apps in workspace |
2597
+ | POST | `/api/workspace/:id/apps` | Add app to workspace |
2598
+ | PATCH | `/api/workspace/:id/apps/:wid` | Update app |
2599
+ | DELETE | `/api/workspace/:id/apps/:wid` | Remove app |
2600
+ | GET | `/api/workspace/:id/export` | Export workspace config |
2601
+ | POST | `/api/workspace/import` | Import workspace config |
2602
+ | GET | `/api/workspace/config` | Get global app config (chain overrides) |
2603
+ | POST | `/api/workspace/config` | Update global app config |
2604
+
2605
+ #### App Config (`/api/workspace/config`)
2606
+
2607
+ Global application configuration including RPC chain overrides.
2608
+
2609
+ **GET** - Returns current config:
2610
+ ```json
2611
+ {
2612
+ "success": true,
2613
+ "config": {
2614
+ "chainOverrides": {
2615
+ "base": { "rpc": "https://custom-rpc.com", "chainId": 8453, "explorer": "https://basescan.org" }
2616
+ }
2617
+ }
2618
+ }
2619
+ ```
2620
+
2621
+ **POST** - Update chain overrides:
2622
+ ```json
2623
+ {
2624
+ "chainOverrides": {
2625
+ "base": { "rpc": "https://custom-rpc.com", "chainId": 8453, "explorer": "https://basescan.org" },
2626
+ "zksync": { "rpc": "https://mainnet.era.zksync.io", "chainId": 324, "explorer": "https://explorer.zksync.io" }
2627
+ }
2628
+ }
2629
+ ```
2630
+
2631
+ RPC resolution order: Custom override > Alchemy key (if configured) > Public fallback.
2632
+
2633
+ ### Events
2634
+
2635
+ | Method | Path | Description |
2636
+ |--------|------|-------------|
2637
+ | GET | `/api/events` | Query events from database |
2638
+ | POST | `/api/events` | Webhook for Express to broadcast events |
2639
+
2640
+ #### GET /api/events
2641
+
2642
+ Query parameters:
2643
+ - `type`: Filter by exact event type (e.g., `action:created`)
2644
+ - `category`: Filter by category prefix (e.g., `auth` matches `auth:*`)
2645
+ - `limit`: Max results (default 50, max 250)
2646
+ - `offset`: Pagination offset
2647
+
2648
+ Response:
2649
+ ```json
2650
+ {
2651
+ "success": true,
2652
+ "events": [
2653
+ {
2654
+ "id": "cuid123",
2655
+ "type": "auth:unlocked",
2656
+ "source": "express",
2657
+ "data": { "description": "Wallet unlocked: 0x123..." },
2658
+ "timestamp": "2024-02-01T12:00:00.000Z"
2659
+ }
2660
+ ],
2661
+ "pagination": {
2662
+ "total": 100,
2663
+ "limit": 50,
2664
+ "offset": 0,
2665
+ "hasMore": true
2666
+ }
2667
+ }
2668
+ ```
2669
+
2670
+ ### Agent Keys
2671
+
2672
+ | Method | Path | Description |
2673
+ |--------|------|-------------|
2674
+ | GET | `/api/agent-requests` | Get pending actions and tokens |
2675
+
2676
+ Proxies to Express `/dashboard` endpoint. Returns:
2677
+ - Pending approval requests
2678
+ - Active tokens (including admin tokens with `isAdmin: true`)
2679
+ - Inactive tokens (expired, revoked, or depleted)