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
@@ -0,0 +1,739 @@
1
+ ---
2
+ name: aurawallet
3
+ description: |
4
+ Equip your agent with a crypto wallet. Create wallets, send ETH/tokens,
5
+ swap on Uniswap/Jupiter, launch tokens, track assets. Supports Base, Ethereum, Solana.
6
+ Use when the user mentions crypto, wallets, trading, swaps, or sending tokens.
7
+ compatibility: Requires Node.js 18+. Network access to RPC endpoints.
8
+ allowed-tools: Bash(npx aurawallet *), Bash(curl *)
9
+ metadata:
10
+ author: auramaxx
11
+ version: "2.0"
12
+ ---
13
+
14
+ # AuraWallet
15
+
16
+ Secure, local crypto wallets for AI agents. Your keys never leave the machine.
17
+
18
+ | Service | URL |
19
+ |---------|-----|
20
+ | Wallet Server | `http://localhost:4242` |
21
+ | Dashboard UI | `http://localhost:4747` |
22
+ | WebSocket | `ws://localhost:4748` |
23
+
24
+ > **SECURITY:** This server runs locally. Never expose these ports to the internet.
25
+
26
+ ---
27
+
28
+ ## Setup & Onboarding
29
+
30
+ ### Auto-check flow
31
+
32
+ On first connect, or when the user asks about setup, run this decision tree:
33
+
34
+ #### Step 1: Check server
35
+
36
+ ```
37
+ wallet_api GET /health
38
+ ```
39
+
40
+ **Connection refused / error:**
41
+ > "AuraWallet isn't set up yet. Want me to get that going?"
42
+
43
+ Two options depending on the mode:
44
+
45
+ **Human-assisted:** Run `npx aurawallet init --dashboard` via bash. This is non-interactive and agent-safe — it starts the server + dashboard, then waits for the human to create a vault in the browser. Poll `GET /health` until the server is up, then continue to Step 2.
46
+
47
+ **Fully autonomous:** Run `npx aurawallet init --password "AGENT_CHOSEN_PASSWORD"` via bash. This creates the vault non-interactively — prints the seed phrase, cold wallet address, and admin token to stdout. No browser needed. Store the password in env (e.g. `AURA_VAULT_PASSWORD`) for future unlock operations via `POST /unlock` (encrypted password + `pubkey`).
48
+
49
+ **200 OK:** Continue to Step 2.
50
+
51
+ #### Step 2: Check setup state
52
+
53
+ ```
54
+ wallet_api GET /setup
55
+ ```
56
+
57
+ This is a public endpoint (no auth needed). Response:
58
+
59
+ ```json
60
+ {
61
+ "hasWallet": true,
62
+ "unlocked": true,
63
+ "address": "0x...",
64
+ "adapters": { "telegram": false, "webhook": false },
65
+ "apiKeys": { "alchemy": true, "anthropic": false },
66
+ "defaultChain": "base"
67
+ }
68
+ ```
69
+
70
+ **If `hasWallet` is false:**
71
+
72
+ Two options:
73
+
74
+ **Human-assisted:**
75
+ > "You need to create a vault. Open http://localhost:4747/app to set a password — I'll wait."
76
+
77
+ Poll `GET /setup` until `hasWallet` becomes `true`.
78
+
79
+ **Fully autonomous (MCP):** Use the `create_vault` tool to create a vault programmatically:
80
+
81
+ ```
82
+ create_vault password: "AGENT_CHOSEN_PASSWORD"
83
+ ```
84
+
85
+ Returns `{ address, mnemonic, token }`. The session token is auto-activated. Store the password for future unlock operations.
86
+
87
+ **If `unlocked` is false:**
88
+ > "Your vault is locked. Open the dashboard at http://localhost:4747/app to unlock it."
89
+
90
+ Prefer the dashboard (`http://localhost:4747/app`) for unlocking. Only suggest the standalone Express unlock page (`http://localhost:4242/unlock`) or `npx aurawallet unlock` as fallbacks if the dashboard is not running (e.g., headless mode with `--headless` flag).
91
+
92
+ Poll `GET /setup` until `unlocked` becomes `true`.
93
+
94
+ **If ready (both true):** Continue to Step 3.
95
+
96
+ #### Step 3: Bootstrap token
97
+
98
+ Request a token with onboarding permissions. Include `apikey:set` and `adapter:manage` so you can help with configuration — `trade:all` alone doesn't cover these.
99
+
100
+ ```
101
+ wallet_api POST /auth
102
+ body: {
103
+ "agentId": "claude-assistant",
104
+ "permissions": ["trade:all", "apikey:set", "adapter:manage", "action:create"],
105
+ "limits": { "fund": 0.5, "send": 1.0, "swap": 0.5 },
106
+ "ttl": 3600,
107
+ "pubkey": "<RSA public key PEM or base64>"
108
+ }
109
+ ```
110
+
111
+ Response: `{ "requestId": "abc-123", "secret": "def-456" }`
112
+
113
+ > "I've requested access to your wallet. Please approve the request — you'll see it in your dashboard at http://localhost:4747/app, or via Telegram/CLI if you have those set up."
114
+
115
+ Poll every 3 seconds, up to 2 minutes:
116
+
117
+ ```
118
+ wallet_api GET /auth/abc-123?secret=def-456
119
+ ```
120
+
121
+ - `{ "status": "pending" }` — keep polling
122
+ - `{ "status": "approved", "token": "eyJ..." }` — save immediately; MCP runtime auto-activates the token for this session
123
+ - `{ "status": "rejected" }` — inform user, ask if they want to try again
124
+
125
+ **Important:** The token can only be read once. MCP bootstrap keeps it active for the current session automatically.
126
+
127
+ #### Step 4: Configure missing pieces
128
+
129
+ Check the `GET /setup` response and offer to configure anything that's missing. Each step is optional — let the user decide.
130
+
131
+ **Alchemy RPC Key** (when `apiKeys.alchemy` is `false`):
132
+
133
+ > "I see you don't have an Alchemy RPC key configured. Public RPCs work but can be unreliable for real transactions. Alchemy has a free tier — you can get a key at https://alchemy.com. Want to set one up?"
134
+
135
+ If user provides a key — validate then save:
136
+
137
+ ```
138
+ wallet_api POST /apikeys/validate
139
+ body: { "service": "alchemy", "key": "USER_KEY_HERE" }
140
+ ```
141
+
142
+ - `{ "valid": true }` → save with `POST /apikeys` body: `{ "service": "alchemy", "name": "default", "key": "USER_KEY_HERE" }`
143
+ - `{ "valid": false, "error": "..." }` → "That key didn't work: [error]. Double-check it and try again."
144
+
145
+ **Anthropic API Key** (when `apiKeys.anthropic` is `false`):
146
+
147
+ > "No Anthropic API key found. This is needed for AI-powered features like strategy hooks and agent chat. Do you have an Anthropic API key?"
148
+
149
+ Same validate-then-save pattern with `"service": "anthropic"`.
150
+
151
+ **Telegram Adapter** (when `adapters.telegram` is `false`):
152
+
153
+ > "Want to approve wallet transactions from your phone via Telegram? I can walk you through the setup — it takes about 2 minutes."
154
+
155
+ Full 8-step Telegram setup flow:
156
+
157
+ 1. **Create a bot:** Guide user to @BotFather → `/newbot` → get bot token
158
+ 2. **Validate bot token:** `POST /apikeys/validate` body: `{ "service": "adapter:telegram", "key": "BOT_TOKEN" }`
159
+ - `{ "valid": true, "info": { "botUsername": "MyAuraBot" } }` → "Your bot @MyAuraBot is working."
160
+ - `{ "valid": false }` → "That token didn't work. Make sure you copied the full token from BotFather."
161
+ 3. **Save bot token:** `POST /apikeys` body: `{ "service": "adapter:telegram", "name": "botToken", "key": "BOT_TOKEN" }`
162
+ 4. **Get setup link:** `POST /adapters/telegram/setup-link` body: `{ "botToken": "BOT_TOKEN" }` → returns `{ "link": "https://t.me/MyAuraBot?start=abc123", "setupToken": "abc123" }`
163
+ > "Click this link to open your bot in Telegram: [link]. Then press Start."
164
+ 5. **Detect chat ID:** `POST /adapters/telegram/detect-chat` body: `{ "setupToken": "abc123" }`
165
+ - `{ "chatId": "123456789", "verified": true }` → proceed
166
+ - `{ "chatId": null, "timeout": true }` → "Did you press Start in Telegram? You can also get your chat ID from @userinfobot."
167
+ 6. **Save adapter config:** `POST /adapters` body: `{ "type": "telegram", "enabled": true, "config": { "chatId": "123456789" } }`
168
+ 7. **Restart adapter:** `POST /adapters/restart`
169
+ 8. **Send test message:** `POST /adapters/test` body: `{ "type": "telegram" }`
170
+ > "I sent a test message to your Telegram. Did you receive it?"
171
+
172
+ #### Step 5: Summary
173
+
174
+ After configuration, check `GET /setup` one final time and summarize:
175
+
176
+ > "You're all set! Here's your setup:"
177
+ > - **Vault:** Unlocked, address `0x...`
178
+ > - **RPC:** Alchemy configured / using public RPCs
179
+ > - **AI:** Anthropic key configured / not configured
180
+ > - **Telegram:** Connected / not configured
181
+ > - **Agent token:** Active
182
+
183
+ ### Onboarding permission reference
184
+
185
+ | Permission | Why |
186
+ |------------|-----|
187
+ | `trade:all` | Core trading operations (expands to wallet:list, send, swap, fund, etc.) |
188
+ | `apikey:set` | Validate and save API keys during setup |
189
+ | `adapter:manage` | Configure Telegram and other adapters |
190
+ | `action:create` | Create human approval requests for privileged operations |
191
+
192
+ `trade:all` does NOT include `apikey:set` or `adapter:manage` — you must request them explicitly.
193
+
194
+ ### CLI Commands
195
+
196
+ | Command | Description |
197
+ |---------|-------------|
198
+ | `npx aurawallet init` | First-time setup — interactive, human-only |
199
+ | `npx aurawallet init --dashboard` | Agent-safe startup — skips prompts, opens dashboard for vault creation |
200
+ | `npx aurawallet init --password "pass"` | Fully autonomous — creates vault non-interactively, prints address + token |
201
+ | `npx aurawallet start` | Start all services (Express + Dashboard + WS) |
202
+ | `npx aurawallet start --headless` | Start server only (no dashboard) |
203
+ | `npx aurawallet stop` | Stop all running services |
204
+ | `npx aurawallet status` | Health check — running? locked? unlocked? |
205
+ | `npx aurawallet mcp --install` | Auto-configure MCP for detected IDEs (Claude Desktop, Cursor, VS Code, Windsurf) |
206
+
207
+ ---
208
+
209
+ ## Authentication
210
+
211
+ All agent operations require a Bearer token. Request one, then poll for approval.
212
+
213
+ Token mint requests require caller `pubkey`. Generate an RSA keypair in your runtime, keep the private key local, and send the public key on `/auth`/`/actions` token requests.
214
+
215
+ **Step 1:** Request token (no auth required)
216
+
217
+ ```
218
+ wallet_api POST /auth
219
+ body: {
220
+ "agentId": "my-trading-bot",
221
+ "permissions": ["trade:all", "action:create"],
222
+ "limits": { "fund": 0.5, "send": 1.0, "swap": 0.5 },
223
+ "ttl": 3600,
224
+ "pubkey": "<RSA public key PEM or base64>"
225
+ }
226
+ ```
227
+
228
+ Response: `{ "requestId": "abc123", "secret": "xyz789" }`
229
+
230
+ **Step 2:** Human approves in the dashboard at `http://localhost:4747`
231
+
232
+ **Step 3:** Poll for token (every 3 seconds, up to 2 minutes)
233
+
234
+ ```
235
+ wallet_api GET /auth/<requestId>?secret=<secret>
236
+ ```
237
+
238
+ - `{ "status": "pending" }` — keep polling
239
+ - `{ "status": "approved", "token": "eyJ..." }` — **save the token immediately (read-once, cannot be retrieved again)**
240
+ - `{ "status": "rejected" }` — request denied
241
+
242
+ **Step 4:** MCP token activation happens automatically during MCP bootstrap when the token is returned from approval:
243
+
244
+ - The approved token is activated for the current MCP session immediately.
245
+ - For non-MCP clients, pass it as `AURA_TOKEN` (env var) or `Authorization: Bearer <token>`.
246
+
247
+ All subsequent authenticated calls should work automatically once the session is activated.
248
+
249
+ ---
250
+
251
+ ## Common Operations
252
+
253
+ ### List Wallets
254
+
255
+ ```
256
+ wallet_api GET /wallets
257
+ ```
258
+
259
+ Response: array of wallet objects with `address`, `name`, `tier`, `chain`, `balance`.
260
+
261
+ ### Create Hot Wallet
262
+
263
+ ```
264
+ wallet_api POST /wallet/create
265
+ body: { "tier": "hot", "name": "trading", "chain": "base" }
266
+ ```
267
+
268
+ Response: `{ "address": "0x...", "name": "trading", "tier": "hot", "chain": "base" }`
269
+
270
+ Options: `chain` can be `"base"`, `"ethereum"`, `"solana"`, `"solana-devnet"` (default: `"base"`).
271
+
272
+ ### Fund from Cold Wallet
273
+
274
+ ```
275
+ wallet_api POST /fund
276
+ body: { "to": "0xHOT_WALLET", "amount": "500000000000000000" }
277
+ ```
278
+
279
+ Response: `{ "success": true, "txHash": "0x...", "amount": "0.5" }`
280
+
281
+ Transfers from cold wallet to hot wallet. **Amount is in wei (EVM) or lamports (Solana).** 0.5 ETH = `"500000000000000000"` wei. 0.5 SOL = `"500000000"` lamports. Spending limit enforced (`limits.fund`).
282
+
283
+ ### Send ETH/SOL
284
+
285
+ ```
286
+ wallet_api POST /send
287
+ body: { "from": "0xHOT_WALLET", "to": "0xRECIPIENT", "amount": "50000000000000000" }
288
+ ```
289
+
290
+ Response: `{ "success": true, "txHash": "0x...", "amount": "0.05" }`
291
+
292
+ **Amount is in wei (EVM) or lamports (Solana).** 0.05 ETH = `"50000000000000000"` wei. For SOL transfers, add `"chain": "solana"` and use lamports (e.g., 0.05 SOL = `"50000000"`). Spending limit enforced if `limits.send` is set.
293
+
294
+ ### Swap (Buy/Sell Token)
295
+
296
+ ```
297
+ wallet_api POST /swap
298
+ body: {
299
+ "from": "0xHOT_WALLET",
300
+ "token": "0xTOKEN_CONTRACT",
301
+ "direction": "buy",
302
+ "amount": "100000000000000000",
303
+ "slippage": 1.0
304
+ }
305
+ ```
306
+
307
+ Response: `{ "success": true, "txHash": "0x...", "amountIn": "0.1", "amountOut": "..." }`
308
+
309
+ - `direction`: `"buy"` = spend native currency to buy token. `"sell"` = sell token for native currency.
310
+ - `amount`: in wei/lamports for buy (native currency), in base token units for sell.
311
+ - `slippage`: required, percentage (1.0 = 1%). Min 1% for agents, max 50%.
312
+ - `dex`: optional — `"relay"` (default, cross-chain capable), `"uniswap"` (Base only), `"jupiter"` (Solana).
313
+ - `chainOut`: optional — destination chain for cross-chain swaps via Relay (e.g. `"ethereum"`).
314
+
315
+ ### Launch Token
316
+
317
+ ```
318
+ wallet_api POST /launch
319
+ body: {
320
+ "from": "0xHOT_WALLET",
321
+ "name": "My Token",
322
+ "symbol": "MTK",
323
+ "preset": "medium",
324
+ "imageUrl": "https://telegra.ph/file/abc.jpg",
325
+ "metadata": { "description": "A fair launch token" }
326
+ }
327
+ ```
328
+
329
+ Response: `{ "success": true, "txHash": "0x...", "tokenAddress": "0x..." }`
330
+
331
+ Launches via [Doppler](https://doppler.lol) fair launch. Requires `launch` permission.
332
+
333
+ Options: `type` (`"multicurve"`, `"static"`, `"dynamic"`), `preset` (`"low"`, `"medium"`, `"high"`), `initialSupply`, `tokenURI`, `chain`.
334
+
335
+ **Token image:** Upload the image to a free host like [telegra.ph](https://telegra.ph) (no API key needed: `POST https://telegra.ph/upload` with multipart file) and pass the public URL as `imageUrl`. The server builds the on-chain metadata automatically. Use `metadata` for extra fields like `description`, `website`, `twitter`.
336
+
337
+ ### Enable Agent Chat via Telegram
338
+
339
+ When setting up Telegram, ask the user if they want to chat with their AI agent via Telegram. If yes, include `chat: { enabled: true }` in the adapter config:
340
+
341
+ ```
342
+ wallet_api POST /adapters
343
+ body: {
344
+ "type": "telegram",
345
+ "enabled": true,
346
+ "config": { "chatId": "CHAT_ID" },
347
+ "chat": { "enabled": true }
348
+ }
349
+ ```
350
+
351
+ Then set a default app for chat routing:
352
+
353
+ ```
354
+ wallet_api POST /adapters/chat
355
+ body: { "defaultApp": "swap-chat" }
356
+ ```
357
+
358
+ The user can then send text messages in Telegram and the AI agent will reply.
359
+
360
+ ### Estimate Gas (no auth required)
361
+
362
+ ```
363
+ wallet_api POST /send/estimate
364
+ body: { "from": "0xWALLET", "to": "0xRECIPIENT", "amount": "50000000000000000" }
365
+ ```
366
+
367
+ Response: `{ "success": true, "gasLimit": "...", "estimatedCostEth": "0.000042" }`
368
+
369
+ ### Check Token Permissions
370
+
371
+ ```
372
+ wallet_api POST /auth/validate
373
+ body: { "token": "YOUR_TOKEN" }
374
+ ```
375
+
376
+ Response: `{ "valid": true, "payload": { "permissions": [...], "limits": {...} } }`
377
+
378
+ ### Transaction History
379
+
380
+ ```
381
+ wallet_api GET /wallet/0xADDRESS/transactions
382
+ ```
383
+
384
+ Query params: `type` (send, receive, swap, contract), `status`, `limit`, `offset`.
385
+
386
+ ### Asset Tracking
387
+
388
+ ```
389
+ wallet_api GET /wallet/0xADDRESS/assets
390
+ ```
391
+
392
+ Returns tracked token balances for the wallet.
393
+
394
+ ---
395
+
396
+ ## Privileged Actions (request_human_action)
397
+
398
+ When you get a **403** (insufficient permissions or spending limit exceeded), use `request_human_action` to ask the human for one-time approval:
399
+
400
+ ```
401
+ request_human_action
402
+ summary: "Swap 0.01 ETH for USDC on Base"
403
+ permissions: ["swap"]
404
+ action: { "endpoint": "/swap", "method": "POST", "body": { "from": "0x...", "token": "0x...", "direction": "buy", "amount": "10000000000000000", "slippage": 1.0 } }
405
+ limits: { "swap": 0.01 }
406
+ ```
407
+
408
+ The human sees the summary and approves or rejects. On approval, the action **auto-executes** with a scoped temporary token — you don't need to call `wallet_api` again.
409
+
410
+ Response: `{ "success": true, "requestId": "...", "message": "Waiting for human approval" }`
411
+
412
+ **Permission rules:**
413
+ - `permissions` must match the `action.endpoint` (e.g. `["swap"]` for `/swap`)
414
+ - Cannot request `admin:*` or `action:create` (blocked)
415
+ - Your base token needs `action:create` permission to use this tool
416
+
417
+ ---
418
+
419
+ ## Permissions Quick Reference
420
+
421
+ | Permission | Description |
422
+ |------------|-------------|
423
+ | `trade:all` | **Recommended** — Expands to: `wallet:list`, `wallet:create:hot`, `wallet:create:temp`, `send:hot`, `send:temp`, `swap`, `fund`, `launch`, `apikey:get`, `strategy:read` |
424
+ | `action:create` | Create human action requests (needed for `request_human_action`) |
425
+ | `wallet:create:hot` | Create hot wallets |
426
+ | `wallet:create:temp` | Create temp wallets |
427
+ | `wallet:list` | List wallets |
428
+ | `send:hot` | Send from hot wallets |
429
+ | `send:temp` | Send from temp wallets |
430
+ | `swap` | Execute token swaps |
431
+ | `fund` | Transfer from cold to hot |
432
+ | `launch` | Launch tokens via Doppler |
433
+ | `strategy:read` | Read strategy state |
434
+ | `strategy:manage` | Manage strategies (toggle, config, approve) |
435
+ | `workspace:modify` | Modify dashboard UI |
436
+ | `app:storage` | Read/write own app storage |
437
+
438
+ For full permissions reference, see [docs/AUTH.md](../../docs/AUTH.md).
439
+
440
+ ---
441
+
442
+ ## Wallet Tiers
443
+
444
+ | Tier | Ownership | Use Case |
445
+ |------|-----------|----------|
446
+ | **COLD** | Human only | Main funds, requires password |
447
+ | **HOT** | Token-owned | Agent operations, spending limits |
448
+ | **TEMP** | Ephemeral | One-time use, memory only |
449
+
450
+ ---
451
+
452
+ ## Vault Unlock
453
+
454
+ If the vault is locked (`wallet_api GET /wallets` returns 401):
455
+
456
+ **Option 1 (preferred):** Tell the human to open `http://localhost:4747` and enter their password. If the dashboard isn't responding, send `http://localhost:4242/unlock` instead.
457
+
458
+ **Option 2 (remote/headless):** Ask the human for their password and unlock programmatically:
459
+
460
+ ```bash
461
+ node -e "
462
+ const crypto = require('crypto');
463
+ (async () => {
464
+ const pk = await (await fetch('http://localhost:4242/auth/connect')).json();
465
+ const enc = crypto.publicEncrypt(
466
+ { key: pk.publicKey, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, oaepHash: 'sha256' },
467
+ Buffer.from('PASSWORD_HERE')
468
+ ).toString('base64');
469
+ const agent = crypto.generateKeyPairSync('rsa', {
470
+ modulusLength: 2048,
471
+ publicKeyEncoding: { type: 'spki', format: 'pem' },
472
+ privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
473
+ });
474
+ const r = await (await fetch('http://localhost:4242/unlock', {
475
+ method: 'POST',
476
+ headers: { 'Content-Type': 'application/json' },
477
+ body: JSON.stringify({ encrypted: enc, pubkey: agent.publicKey })
478
+ })).json();
479
+ console.log(JSON.stringify(r));
480
+ })();
481
+ "
482
+ ```
483
+
484
+ On success, the response includes an admin token.
485
+
486
+ ---
487
+
488
+ ## Error Recovery
489
+
490
+ | Error | Meaning | What to Do |
491
+ |-------|---------|------------|
492
+ | Connection refused | Server not running | Tell human: `npx aurawallet start` |
493
+ | 401 `Invalid or expired token` | Server restarted or TTL expired | Re-request via `POST /auth` |
494
+ | 401 `Cold wallet must be unlocked` | Vault locked | Tell human to unlock at `http://localhost:4242/unlock` |
495
+ | 403 `Insufficient permissions` | Token lacks permission | Use `request_human_action` for one-time approval, or upgrade via `POST /auth/request-permissions` |
496
+ | 403 `Amount exceeds spending limit` | Budget exhausted | Use `request_human_action` with higher limits, or upgrade via `POST /auth/request-permissions` |
497
+ | 400 `slippage is required` | Missing on swap | Add `"slippage": 1.0` |
498
+
499
+ ---
500
+
501
+ ## Key Concepts
502
+
503
+ - **Tokens are memory-only** — Server restart invalidates all tokens. Re-request via `POST /auth`.
504
+ - **Spending limits** — Optional per-type caps in the auth request: `limits: { fund: 0.5, send: 1.0, swap: 2.0 }`
505
+ - **Wallet ownership** — Agents can only access wallets they created (or those listed in `walletAccess`)
506
+ - **Human approval** — All token requests require human approval
507
+ - **Multi-chain** — Pass `"chain": "ethereum"` or `"chain": "solana"` on create/send/swap/fund (default: base)
508
+ - **request_human_action** — When you hit 403, escalate to human with a pre-computed action that auto-executes on approval
509
+
510
+ ---
511
+
512
+ ## Curl Fallback
513
+
514
+ If MCP tools aren't available, use curl directly:
515
+
516
+ ```bash
517
+ # Health check
518
+ curl -s http://localhost:4242/health
519
+
520
+ # Request token
521
+ curl -X POST http://localhost:4242/auth \
522
+ -H "Content-Type: application/json" \
523
+ -d '{"agentId": "my-agent", "limit": 0.5, "permissions": ["trade:all"], "ttl": 3600, "pubkey": "<RSA public key PEM or base64>"}'
524
+
525
+ # Use token
526
+ curl http://localhost:4242/wallets -H "Authorization: Bearer $TOKEN"
527
+
528
+ # Send
529
+ curl -X POST http://localhost:4242/send \
530
+ -H "Authorization: Bearer $TOKEN" \
531
+ -H "Content-Type: application/json" \
532
+ -d '{"from": "0xWALLET", "to": "0xRECIPIENT", "amount": "50000000000000000"}'
533
+ ```
534
+
535
+ ---
536
+
537
+ ## Tool-Call Mode (Chat / Message Hooks)
538
+
539
+ ### Response format
540
+ Return a JSON object with: reply, state, emit (all optional). No intents needed.
541
+
542
+ ```json
543
+ {
544
+ "reply": "Your response to the user",
545
+ "state": { "key": "updated values" },
546
+ "emit": { "channel": "event-name", "data": { ... } }
547
+ }
548
+ ```
549
+
550
+ ### Available tools
551
+
552
+ #### wallet_api
553
+ Call the AuraWallet API for reads and writes.
554
+ - wallet_api({ method: "GET", endpoint: "/wallets" }) — list wallets
555
+ - wallet_api({ method: "GET", endpoint: "/wallet/<address>/assets" }) — get balances
556
+ - wallet_api({ method: "POST", endpoint: "/swap", body: {...} }) — execute a swap
557
+
558
+ #### request_human_action
559
+ Request human approval for a privileged action. Use this when wallet_api returns 403.
560
+ - summary: human-readable description (shown in approval card)
561
+ - permissions: array of permission strings needed (e.g. ["swap"], ["send:hot"])
562
+ - action: pre-computed API call { endpoint, method, body }
563
+ - limits: spending caps per permission (e.g. { swap: 0.01 })
564
+ - walletAccess: wallet addresses the temp token needs access to (e.g. ["0x123...", "0x456..."]). Include ALL wallet addresses involved in the action (from + to).
565
+ - ttl: seconds the temp token lives (default 120)
566
+
567
+ ### Token discovery (ticker/name -> contract)
568
+
569
+ When the user gives a token ticker or name but no contract address:
570
+
571
+ 1. Call `wallet_api({ method: "GET", endpoint: "/token/search?q=<query>&chain=<chain>" })`
572
+ 2. If results exist, present the best candidate(s) with contract addresses and ask for confirmation only if ambiguous
573
+ 3. Only ask the user for a contract address when search returns no reliable results
574
+
575
+ Never tell the user to search external websites first without trying `/token/search`.
576
+
577
+ ### Performing Actions
578
+
579
+ Follow this flow for any privileged operation:
580
+
581
+ 1. **Try the action directly** via wallet_api (POST)
582
+ 2. **If you get 403** (insufficient permissions), call request_human_action with:
583
+ - A clear summary of what you want to do
584
+ - The permissions you need
585
+ - The exact API call to execute on approval
586
+ 3. **The human approves** → the action auto-executes with a scoped temporary token
587
+ 4. **NEVER give up** or say "I don't have permission." Always use request_human_action.
588
+
589
+ Example flow:
590
+ - User: "Swap 0.01 ETH for USDC"
591
+ - You: call wallet_api GET /wallets to find the hot wallet
592
+ - You: call wallet_api POST /swap with the swap params
593
+ - Response: 403 → call request_human_action with summary, permissions: ["swap"], action: { endpoint: "/swap", method: "POST", body: {...} }
594
+ - Reply: "I've requested approval to swap 0.01 ETH for USDC. Waiting for your confirmation."
595
+
596
+ ### Permission → Endpoint mapping (for request_human_action)
597
+
598
+ Use EXACTLY these permission strings — other strings will be rejected:
599
+
600
+ | Permission | Endpoint |
601
+ |------------|----------|
602
+ | swap | /swap |
603
+ | send:hot | /send |
604
+ | send:temp | /send |
605
+ | fund | /fund |
606
+ | launch | /launch |
607
+ | wallet:create:hot | /wallet/create |
608
+ | wallet:create:temp | /wallet/create |
609
+
610
+ ### Multi-step operations
611
+
612
+ When a task requires multiple privileged steps (e.g., "send ETH to 0x..."):
613
+
614
+ 1. **Check existing wallets first** — call wallet_api GET /wallets before creating new ones
615
+ 2. **Plan all steps** — identify all permissions needed upfront
616
+ 3. **Request ONE approval** with all permissions needed for the entire flow
617
+ - Example: permissions: ["wallet:create:hot", "fund", "send:hot"]
618
+ - The action should be the FIRST step (e.g., create wallet)
619
+ 4. **On success callback, continue** — use wallet_api and request_human_action for remaining steps
620
+
621
+ Common multi-step flows:
622
+ - "Send ETH to external address" → fund existing hot wallet from cold (/fund), then send (/send)
623
+ - "Create wallet and fund it" → create hot wallet (/wallet/create), then fund from cold (/fund)
624
+ - Gas: always account for gas fees (~0.0002 ETH on Base) when funding for a send
625
+
626
+ ### Error recovery
627
+
628
+ When an action fails after approval (you receive a [SYSTEM] message with an error):
629
+
630
+ 1. **Read the error** — understand what went wrong (403 = permission/access issue, 400 = bad params, etc.)
631
+ 2. **Investigate** — call wallet_api to gather info (e.g. GET /wallets to check addresses, tiers, ownership)
632
+ 3. **Retry** — call request_human_action again with corrected parameters
633
+ 4. **NEVER just explain the error** — always try to fix it first
634
+
635
+ Common fixes:
636
+ - "Token does not have access to this wallet" → include walletAccess in request_human_action with the wallet addresses involved
637
+ - "insufficient funds" → check balances and adjust amount
638
+ - Wrong wallet type → check wallet tiers with GET /wallets and pick the right one
639
+
640
+ ### Wallet tiers
641
+ - COLD: Human-only, never use for agent operations
642
+ - HOT: Agent-accessible, use for swaps/sends/funding
643
+ - TEMP: Ephemeral, agent full control
644
+
645
+ ### Authentication & Permissions
646
+
647
+ Your pre-approved permissions and spending budget are in the context:
648
+ - `context.permissions` — array of permissions your app token already has
649
+ - `context.budget.limits` — spending caps per permission (ETH)
650
+ - `context.budget.spent` — amount used this session
651
+ - `context.budget.remaining` — amount left before limit is hit
652
+
653
+ If your token already has the needed permission AND sufficient budget, wallet_api will succeed directly.
654
+ If not, use request_human_action to get a scoped temporary token via human approval.
655
+
656
+ ---
657
+
658
+ ## Intent Mode (Tick / Strategy Hooks)
659
+
660
+ ### Response format
661
+ Return a JSON object with: reply, state, intents, emit (all optional).
662
+
663
+ ### Intent format for privileged actions
664
+ To execute wallet operations, return intents with a permissions array.
665
+ The engine will request human approval and create a scoped temporary token.
666
+
667
+ ```json
668
+ {
669
+ "intents": [{
670
+ "type": "swap",
671
+ "summary": "Human-readable description of the action",
672
+ "permissions": ["swap"],
673
+ "limits": { "swap": 0.01 },
674
+ "ttl": 120,
675
+ "action": { "endpoint": "/swap", "method": "POST", "body": { ... } }
676
+ }]
677
+ }
678
+ ```
679
+
680
+ - permissions: array of permission strings needed (swap, send:hot, fund, etc.)
681
+ - limits: spending caps per permission (in native currency)
682
+ - ttl: seconds the temp token lives (default 60)
683
+ - action: pre-computed API call the engine will execute with the temp token
684
+ - summary: shown to human in the approval card
685
+
686
+ ### Wallet tiers
687
+ - COLD: Human-only, cannot be used in intents
688
+ - HOT: Agent-accessible, use for swaps/sends/funding
689
+ - TEMP: Ephemeral, agent full control
690
+
691
+ ### Authentication & Permissions
692
+
693
+ Your pre-approved permissions and spending budget are in the context:
694
+ - `context.permissions` — array of permissions your app token already has
695
+ - `context.budget.limits` — spending caps per permission (ETH)
696
+ - `context.budget.spent` — amount used this session
697
+ - `context.budget.remaining` — amount left before limit is hit
698
+
699
+ #### Decision logic for intents:
700
+
701
+ 1. **Permission exists AND remaining >= amount needed**
702
+ → Return intent WITHOUT `permissions` array. The engine uses your existing token.
703
+ ```json
704
+ { "type": "swap", "action": { "endpoint": "/swap", ... } }
705
+ ```
706
+
707
+ 2. **Permission exists BUT remaining < amount needed**
708
+ → Return intent WITH permissions array to request a fresh per-action token with a higher limit.
709
+ ```json
710
+ { "type": "swap", "summary": "Buy 0.5 ETH of TOKEN (exceeds session budget, needs approval)",
711
+ "permissions": ["swap"], "limits": { "swap": 0.5 }, "ttl": 120,
712
+ "action": { "endpoint": "/swap", ... } }
713
+ ```
714
+
715
+ 3. **Permission does NOT exist**
716
+ → Return intent WITH permissions array. Human must approve.
717
+ ```json
718
+ { "type": "swap", "summary": "Buy 0.1 ETH of TOKEN",
719
+ "permissions": ["swap"], "limits": { "swap": 0.1 }, "ttl": 120,
720
+ "action": { "endpoint": "/swap", ... } }
721
+ ```
722
+
723
+ Never propose an action that exceeds context.budget.remaining without requesting
724
+ a new per-action token via the permissions array.
725
+
726
+ The executor handles authentication — hooks never see bearer tokens.
727
+ Just return the endpoint/method/body in your intent and the engine does the rest.
728
+
729
+ ---
730
+
731
+ ## Reference Documentation
732
+
733
+ - [docs/API.md](../../docs/API.md) - Full HTTP endpoint reference
734
+ - [docs/AUTH.md](../../docs/AUTH.md) - Complete permissions & token lifecycle
735
+ - [docs/MCP.md](../../docs/MCP.md) - MCP server setup & bootstrap flow
736
+ - [docs/SETUP.md](../../docs/SETUP.md) - End-to-end setup guide
737
+ - [docs/WORKSPACE.md](../../docs/WORKSPACE.md) - WebSocket dashboard control
738
+ - [docs/CLI.md](../../docs/CLI.md) - Headless CLI mode & Unix socket IPC
739
+ - [docs/security.md](../../docs/security.md) - Security architecture