auramaxx 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (418) hide show
  1. package/LICENSE +26 -0
  2. package/README.md +77 -0
  3. package/apps/desktop-electron/main.js +428 -0
  4. package/bin/auramaxx.js +1063 -0
  5. package/docs/ADAPTERS.md +466 -0
  6. package/docs/AGENT_SETUP.md +159 -0
  7. package/docs/API.md +127 -0
  8. package/docs/APPS.md +199 -0
  9. package/docs/ARCHITECTURE.md +235 -0
  10. package/docs/AUTH.md +318 -0
  11. package/docs/BEST-PRACTICES.md +82 -0
  12. package/docs/CLI.md +141 -0
  13. package/docs/DESKTOP_ELECTRON.md +26 -0
  14. package/docs/DEVELOPING-APPS.md +453 -0
  15. package/docs/MCP.md +122 -0
  16. package/docs/PACKAGING_POLICY.md +19 -0
  17. package/docs/PERMISSION.md +137 -0
  18. package/docs/PROTOCOL.md +142 -0
  19. package/docs/README.md +50 -0
  20. package/docs/SKILLS.md +132 -0
  21. package/docs/TROUBLESHOOTING.md +376 -0
  22. package/docs/WORKSPACE.md +673 -0
  23. package/docs/agent-auth.md +14 -0
  24. package/docs/api/authentication.md +79 -0
  25. package/docs/api/secrets/api-keys.md +28 -0
  26. package/docs/api/secrets/credentials.md +80 -0
  27. package/docs/api/secrets/sharing.md +48 -0
  28. package/docs/api/system.md +41 -0
  29. package/docs/api/wallets/apps-strategies.md +66 -0
  30. package/docs/api/wallets/core.md +46 -0
  31. package/docs/api/wallets/data-portfolio.md +42 -0
  32. package/docs/aura-file.md +48 -0
  33. package/docs/core-concepts/FEATURES.md +114 -0
  34. package/docs/credentials.md +120 -0
  35. package/docs/external/HOW_TO_AURAMAXX/GETTING_SECRETS.md +33 -0
  36. package/docs/external/HOW_TO_AURAMAXX/README.md +45 -0
  37. package/docs/external/getting-started.md +10 -0
  38. package/docs/external/overview.md +19 -0
  39. package/docs/external/persona-paths.md +7 -0
  40. package/docs/external/share-secret.md +76 -0
  41. package/docs/external/why-aura.md +7 -0
  42. package/docs/security.md +227 -0
  43. package/docs/templates/RELEASE_NOTES_TEMPLATE.md +22 -0
  44. package/docs/wallet/AI.md +508 -0
  45. package/docs/wallet/DEVELOPING-STRATEGIES.md +713 -0
  46. package/docs/wallet/README.md +47 -0
  47. package/docs/wallet/STRATEGY.md +89 -0
  48. package/next.config.ts +28 -0
  49. package/package.json +167 -0
  50. package/postcss.config.mjs +8 -0
  51. package/prisma/migrations/20260214170000_baseline/migration.sql +511 -0
  52. package/prisma/migrations/20260216214537_add_passkey_model/migration.sql +18 -0
  53. package/prisma/migrations/20260217150500_add_credential_access_audit/migration.sql +31 -0
  54. package/prisma/migrations/20260222090000_update_admin_ttl_default/migration.sql +10 -0
  55. package/prisma/migrations/migration_lock.toml +3 -0
  56. package/prisma/schema.prisma +447 -0
  57. package/public/logo.webp +0 -0
  58. package/scripts/add-app.js +245 -0
  59. package/server/abi/SwapHelper.json +438 -0
  60. package/server/cli/approval.ts +447 -0
  61. package/server/cli/commands/actions.ts +474 -0
  62. package/server/cli/commands/api.ts +220 -0
  63. package/server/cli/commands/apikey.ts +277 -0
  64. package/server/cli/commands/app.ts +204 -0
  65. package/server/cli/commands/auth.ts +464 -0
  66. package/server/cli/commands/cron.ts +24 -0
  67. package/server/cli/commands/diary.ts +274 -0
  68. package/server/cli/commands/doctor.ts +1247 -0
  69. package/server/cli/commands/env.ts +476 -0
  70. package/server/cli/commands/experimental.ts +69 -0
  71. package/server/cli/commands/init.ts +798 -0
  72. package/server/cli/commands/lock.ts +157 -0
  73. package/server/cli/commands/mcp.ts +285 -0
  74. package/server/cli/commands/quickhack.ts +86 -0
  75. package/server/cli/commands/release-check.ts +231 -0
  76. package/server/cli/commands/restore.ts +314 -0
  77. package/server/cli/commands/service.ts +320 -0
  78. package/server/cli/commands/shell-hook.ts +512 -0
  79. package/server/cli/commands/skill.ts +216 -0
  80. package/server/cli/commands/start.ts +139 -0
  81. package/server/cli/commands/status.ts +59 -0
  82. package/server/cli/commands/stop.ts +36 -0
  83. package/server/cli/commands/token.ts +180 -0
  84. package/server/cli/commands/unlock.ts +50 -0
  85. package/server/cli/commands/vault.ts +1323 -0
  86. package/server/cli/commands/wallet.ts +209 -0
  87. package/server/cli/index.ts +280 -0
  88. package/server/cli/lib/approval-poll.ts +94 -0
  89. package/server/cli/lib/aura-parser.ts +64 -0
  90. package/server/cli/lib/credential-create.ts +74 -0
  91. package/server/cli/lib/credential-resolve.ts +280 -0
  92. package/server/cli/lib/dotenv-migrate.ts +116 -0
  93. package/server/cli/lib/dotenv-parser.ts +146 -0
  94. package/server/cli/lib/escalation.ts +57 -0
  95. package/server/cli/lib/http.ts +91 -0
  96. package/server/cli/lib/init-steps.ts +76 -0
  97. package/server/cli/lib/local-agent-trust.ts +45 -0
  98. package/server/cli/lib/lock-unlock-helper.ts +71 -0
  99. package/server/cli/lib/process.ts +162 -0
  100. package/server/cli/lib/prompt.ts +294 -0
  101. package/server/cli/lib/theme.ts +240 -0
  102. package/server/cli/socket.ts +579 -0
  103. package/server/cli/transport-client.ts +50 -0
  104. package/server/cron/index.ts +137 -0
  105. package/server/cron/job.ts +31 -0
  106. package/server/cron/jobs/balance-sync.ts +436 -0
  107. package/server/cron/jobs/incoming-scan.ts +506 -0
  108. package/server/cron/jobs/native-price.ts +70 -0
  109. package/server/cron/jobs/orphan-cleanup.ts +40 -0
  110. package/server/cron/jobs/strategy-runner.ts +175 -0
  111. package/server/cron/scheduler.ts +125 -0
  112. package/server/index.ts +420 -0
  113. package/server/lib/adapters/factory.ts +119 -0
  114. package/server/lib/adapters/index.ts +19 -0
  115. package/server/lib/adapters/router.ts +297 -0
  116. package/server/lib/adapters/telegram.ts +645 -0
  117. package/server/lib/adapters/types.ts +89 -0
  118. package/server/lib/adapters/webhook.ts +95 -0
  119. package/server/lib/address.ts +49 -0
  120. package/server/lib/agent-auth/contracts.ts +1194 -0
  121. package/server/lib/agent-profiles.ts +419 -0
  122. package/server/lib/ai.ts +285 -0
  123. package/server/lib/api-registry/contracts.ts +86 -0
  124. package/server/lib/api-registry/validation.ts +172 -0
  125. package/server/lib/apikey-migration.ts +258 -0
  126. package/server/lib/app-installer.ts +505 -0
  127. package/server/lib/app-tokens.ts +247 -0
  128. package/server/lib/approval-link.ts +27 -0
  129. package/server/lib/auth.ts +314 -0
  130. package/server/lib/auto-execute.ts +160 -0
  131. package/server/lib/batch.ts +242 -0
  132. package/server/lib/cold.ts +1048 -0
  133. package/server/lib/config.ts +408 -0
  134. package/server/lib/credential-access-audit.ts +85 -0
  135. package/server/lib/credential-access-policy.ts +111 -0
  136. package/server/lib/credential-health.ts +343 -0
  137. package/server/lib/credential-import.ts +608 -0
  138. package/server/lib/credential-scope.ts +102 -0
  139. package/server/lib/credential-shares.ts +190 -0
  140. package/server/lib/credential-transport.ts +533 -0
  141. package/server/lib/credential-vault.ts +77 -0
  142. package/server/lib/credentials.ts +422 -0
  143. package/server/lib/crypto.ts +8 -0
  144. package/server/lib/db.ts +58 -0
  145. package/server/lib/defaults.ts +386 -0
  146. package/server/lib/dex/index.ts +80 -0
  147. package/server/lib/dex/relay.ts +235 -0
  148. package/server/lib/dex/types.ts +59 -0
  149. package/server/lib/dex/uniswap.ts +370 -0
  150. package/server/lib/diary.ts +34 -0
  151. package/server/lib/dont-ask-again-policy.ts +41 -0
  152. package/server/lib/e2e-agent/artifacts.ts +36 -0
  153. package/server/lib/e2e-agent/contracts.ts +112 -0
  154. package/server/lib/e2e-agent/validation.ts +135 -0
  155. package/server/lib/encrypt.ts +114 -0
  156. package/server/lib/error.ts +20 -0
  157. package/server/lib/events.ts +217 -0
  158. package/server/lib/feature-flags.ts +93 -0
  159. package/server/lib/hot.ts +357 -0
  160. package/server/lib/human-action-summary.ts +80 -0
  161. package/server/lib/key-fingerprint.ts +28 -0
  162. package/server/lib/logger.ts +340 -0
  163. package/server/lib/network.ts +137 -0
  164. package/server/lib/notifications.ts +230 -0
  165. package/server/lib/oauth2-refresh.ts +241 -0
  166. package/server/lib/oursecret.ts +71 -0
  167. package/server/lib/passkey-credential.ts +360 -0
  168. package/server/lib/passkey.ts +68 -0
  169. package/server/lib/permissions.ts +299 -0
  170. package/server/lib/pino.ts +24 -0
  171. package/server/lib/policy-preview.ts +138 -0
  172. package/server/lib/price.ts +338 -0
  173. package/server/lib/prices.ts +34 -0
  174. package/server/lib/project-scope.ts +297 -0
  175. package/server/lib/resolve-action.ts +328 -0
  176. package/server/lib/resolve.ts +36 -0
  177. package/server/lib/secret-gist-share.ts +296 -0
  178. package/server/lib/sessions.ts +634 -0
  179. package/server/lib/socket-path.ts +56 -0
  180. package/server/lib/solana/connection.ts +26 -0
  181. package/server/lib/solana/jupiter.ts +128 -0
  182. package/server/lib/solana/transfer.ts +108 -0
  183. package/server/lib/solana/wallet.ts +136 -0
  184. package/server/lib/strategy/emits.ts +21 -0
  185. package/server/lib/strategy/engine.ts +1305 -0
  186. package/server/lib/strategy/executor.ts +115 -0
  187. package/server/lib/strategy/hook-context.ts +159 -0
  188. package/server/lib/strategy/hooks.ts +990 -0
  189. package/server/lib/strategy/index.ts +28 -0
  190. package/server/lib/strategy/installer.ts +305 -0
  191. package/server/lib/strategy/loader.ts +256 -0
  192. package/server/lib/strategy/message.ts +237 -0
  193. package/server/lib/strategy/repository.ts +218 -0
  194. package/server/lib/strategy/session-logger.ts +693 -0
  195. package/server/lib/strategy/sources.ts +288 -0
  196. package/server/lib/strategy/state.ts +189 -0
  197. package/server/lib/strategy/templates.ts +403 -0
  198. package/server/lib/strategy/tick.ts +404 -0
  199. package/server/lib/strategy/types.ts +230 -0
  200. package/server/lib/swap.ts +3 -0
  201. package/server/lib/temp.ts +86 -0
  202. package/server/lib/token-metadata.ts +86 -0
  203. package/server/lib/token-safety.ts +200 -0
  204. package/server/lib/token-search.ts +444 -0
  205. package/server/lib/totp.ts +194 -0
  206. package/server/lib/transactions.ts +123 -0
  207. package/server/lib/transport.ts +84 -0
  208. package/server/lib/txhistory/decoder.ts +262 -0
  209. package/server/lib/txhistory/enricher.ts +652 -0
  210. package/server/lib/txhistory/index.ts +391 -0
  211. package/server/lib/txhistory/signatures.ts +59 -0
  212. package/server/lib/update-check.ts +35 -0
  213. package/server/lib/verified-summary.ts +414 -0
  214. package/server/lib/view-registry.ts +80 -0
  215. package/server/mcp/profile-policy.ts +30 -0
  216. package/server/mcp/server.ts +1589 -0
  217. package/server/mcp/tools.ts +276 -0
  218. package/server/middleware/auth.ts +119 -0
  219. package/server/middleware/requestLogger.ts +84 -0
  220. package/server/routes/actions.ts +539 -0
  221. package/server/routes/adapters.ts +711 -0
  222. package/server/routes/addressbook.ts +113 -0
  223. package/server/routes/ai.ts +34 -0
  224. package/server/routes/apikeys.ts +343 -0
  225. package/server/routes/apps.ts +601 -0
  226. package/server/routes/auth.ts +406 -0
  227. package/server/routes/backup.ts +404 -0
  228. package/server/routes/batch.ts +270 -0
  229. package/server/routes/bookmarks.ts +162 -0
  230. package/server/routes/credential-shares.ts +380 -0
  231. package/server/routes/credential-vaults.ts +159 -0
  232. package/server/routes/credentials.ts +1782 -0
  233. package/server/routes/dashboard.ts +97 -0
  234. package/server/routes/defaults.ts +124 -0
  235. package/server/routes/flags.ts +11 -0
  236. package/server/routes/fund.ts +225 -0
  237. package/server/routes/heartbeat.ts +375 -0
  238. package/server/routes/import.ts +364 -0
  239. package/server/routes/launch.ts +665 -0
  240. package/server/routes/lock.ts +54 -0
  241. package/server/routes/logs.ts +68 -0
  242. package/server/routes/nuke.ts +111 -0
  243. package/server/routes/passkey-credentials.ts +99 -0
  244. package/server/routes/passkey.ts +366 -0
  245. package/server/routes/portfolio.ts +217 -0
  246. package/server/routes/price.ts +63 -0
  247. package/server/routes/resolve.ts +31 -0
  248. package/server/routes/security.ts +45 -0
  249. package/server/routes/send-evm.ts +241 -0
  250. package/server/routes/send-solana.ts +281 -0
  251. package/server/routes/send.ts +178 -0
  252. package/server/routes/setup.ts +210 -0
  253. package/server/routes/strategy.ts +894 -0
  254. package/server/routes/swap-evm.ts +352 -0
  255. package/server/routes/swap-solana.ts +176 -0
  256. package/server/routes/swap.ts +356 -0
  257. package/server/routes/token.ts +247 -0
  258. package/server/routes/unlock.ts +467 -0
  259. package/server/routes/views.ts +41 -0
  260. package/server/routes/wallet-assets.ts +361 -0
  261. package/server/routes/wallet-transactions.ts +515 -0
  262. package/server/routes/wallet.ts +709 -0
  263. package/server/types.ts +146 -0
  264. package/shared/credential-field-schema.ts +248 -0
  265. package/skills/auramaxx/HEARTBEAT.md +78 -0
  266. package/skills/auramaxx/SKILL.md +745 -0
  267. package/skills/auramaxx/docs/AGENT_SETUP.md +155 -0
  268. package/skills/auramaxx/docs/API.md +127 -0
  269. package/skills/auramaxx/docs/AUTH.md +318 -0
  270. package/skills/auramaxx/docs/CLI.md +130 -0
  271. package/skills/auramaxx/docs/MCP.md +122 -0
  272. package/skills/auramaxx/docs/TROUBLESHOOTING.md +357 -0
  273. package/skills/auramaxx/docs/WORKSPACE.md +673 -0
  274. package/skills/auramaxx/docs/security.md +227 -0
  275. package/skills/task-lifecycle/SKILL.md +378 -0
  276. package/src/app/api/[...doc]/page.tsx +36 -0
  277. package/src/app/api/agent-requests/route.ts +30 -0
  278. package/src/app/api/apps/install/route.ts +132 -0
  279. package/src/app/api/apps/manifests/route.ts +16 -0
  280. package/src/app/api/apps/static/[...path]/route.ts +57 -0
  281. package/src/app/api/docs/plain/route.ts +74 -0
  282. package/src/app/api/events/route.ts +92 -0
  283. package/src/app/api/page.tsx +290 -0
  284. package/src/app/api/workspace/[id]/apps/[wid]/route.ts +119 -0
  285. package/src/app/api/workspace/[id]/apps/route.ts +81 -0
  286. package/src/app/api/workspace/[id]/export/route.ts +67 -0
  287. package/src/app/api/workspace/[id]/route.ts +168 -0
  288. package/src/app/api/workspace/auth.ts +40 -0
  289. package/src/app/api/workspace/config/route.ts +121 -0
  290. package/src/app/api/workspace/import/route.ts +127 -0
  291. package/src/app/api/workspace/route.ts +116 -0
  292. package/src/app/app-legacy-do-not-use/page.tsx +2245 -0
  293. package/src/app/apple-icon.png +0 -0
  294. package/src/app/approve/[actionId]/page.tsx +409 -0
  295. package/src/app/docs/DocsPageContent.tsx +269 -0
  296. package/src/app/docs/[...doc]/page.tsx +41 -0
  297. package/src/app/docs/page.tsx +38 -0
  298. package/src/app/favicon.ico +0 -0
  299. package/src/app/globals.css +819 -0
  300. package/src/app/health/page.tsx +5 -0
  301. package/src/app/hello/page.tsx +102 -0
  302. package/src/app/icon.png +0 -0
  303. package/src/app/layout.tsx +39 -0
  304. package/src/app/page.tsx +1964 -0
  305. package/src/app/privacy/page.tsx +63 -0
  306. package/src/app/providers.tsx +87 -0
  307. package/src/app/share/[token]/page.tsx +295 -0
  308. package/src/app/terms/page.tsx +80 -0
  309. package/src/components/ChainSelector.tsx +44 -0
  310. package/src/components/HumanActionBar.tsx +697 -0
  311. package/src/components/NotificationDrawer.tsx +387 -0
  312. package/src/components/PasskeyEnrollmentPrompt.tsx +235 -0
  313. package/src/components/apps/AgentKeysApp.tsx +490 -0
  314. package/src/components/apps/App.tsx +153 -0
  315. package/src/components/apps/AppGrid.tsx +15 -0
  316. package/src/components/apps/DetailedAddressDrawer.tsx +325 -0
  317. package/src/components/apps/DraggableApp.tsx +562 -0
  318. package/src/components/apps/IFrameApp.tsx +73 -0
  319. package/src/components/apps/LogsApp.tsx +360 -0
  320. package/src/components/apps/SendApp.tsx +394 -0
  321. package/src/components/apps/SetupWizardApp.tsx +1004 -0
  322. package/src/components/apps/SystemDefaultsApp.tsx +845 -0
  323. package/src/components/apps/ThirdPartyApp.tsx +428 -0
  324. package/src/components/apps/TokenApp.tsx +319 -0
  325. package/src/components/apps/TransactionsApp.tsx +438 -0
  326. package/src/components/apps/WalletDetailApp.tsx +1505 -0
  327. package/src/components/apps/index.ts +13 -0
  328. package/src/components/design-system/Button.tsx +88 -0
  329. package/src/components/design-system/ChainIndicator.tsx +65 -0
  330. package/src/components/design-system/ChainSelector.tsx +147 -0
  331. package/src/components/design-system/ConfirmationModal.tsx +107 -0
  332. package/src/components/design-system/ConfirmationPopover.tsx +81 -0
  333. package/src/components/design-system/DownloadButton.tsx +149 -0
  334. package/src/components/design-system/Drawer.tsx +133 -0
  335. package/src/components/design-system/FilterDropdown.tsx +183 -0
  336. package/src/components/design-system/ItemPicker.tsx +157 -0
  337. package/src/components/design-system/Modal.tsx +296 -0
  338. package/src/components/design-system/Popover.tsx +142 -0
  339. package/src/components/design-system/TextInput.tsx +85 -0
  340. package/src/components/design-system/Toggle.tsx +65 -0
  341. package/src/components/design-system/TyvekCollapsibleSection.tsx +55 -0
  342. package/src/components/design-system/index.ts +14 -0
  343. package/src/components/docs/ClientSideMarkdown.tsx +51 -0
  344. package/src/components/docs/DocsSearchBar.tsx +118 -0
  345. package/src/components/docs/DocsThemeToggle.tsx +38 -0
  346. package/src/components/docs/PersistentDocGroup.tsx +91 -0
  347. package/src/components/docs/ShareUrlButton.tsx +33 -0
  348. package/src/components/docs/SidebarScrollMemory.tsx +56 -0
  349. package/src/components/health/CredentialHealthDashboard.tsx +214 -0
  350. package/src/components/icons/ChainIcons.tsx +72 -0
  351. package/src/components/layout/AppStoreDrawer.tsx +369 -0
  352. package/src/components/layout/ContentArea.tsx +21 -0
  353. package/src/components/layout/CreateViewModal.tsx +88 -0
  354. package/src/components/layout/LeftRail.tsx +114 -0
  355. package/src/components/layout/TabBar.tsx +284 -0
  356. package/src/components/layout/WalletSidebar.tsx +1030 -0
  357. package/src/components/layout/index.ts +6 -0
  358. package/src/components/marketing/AuraMaxxSpecOverlay.tsx +653 -0
  359. package/src/components/marketing/DeviceMorphExperience.tsx +216 -0
  360. package/src/components/vault/ApiKeysConsole.tsx +1272 -0
  361. package/src/components/vault/AuditConsole.tsx +600 -0
  362. package/src/components/vault/CredentialDetail.tsx +625 -0
  363. package/src/components/vault/CredentialEmpty.tsx +55 -0
  364. package/src/components/vault/CredentialField.tsx +583 -0
  365. package/src/components/vault/CredentialForm.tsx +1484 -0
  366. package/src/components/vault/CredentialList.tsx +265 -0
  367. package/src/components/vault/CredentialRow.tsx +130 -0
  368. package/src/components/vault/CredentialShareModal.tsx +273 -0
  369. package/src/components/vault/CredentialVault.tsx +1662 -0
  370. package/src/components/vault/CredentialWalletWidget.tsx +103 -0
  371. package/src/components/vault/DocsConsole.tsx +113 -0
  372. package/src/components/vault/ImportCredentialsModal.tsx +578 -0
  373. package/src/components/vault/LargeTypeModal.tsx +88 -0
  374. package/src/components/vault/PasswordGenerator.tsx +232 -0
  375. package/src/components/vault/TOTPDisplay.tsx +108 -0
  376. package/src/components/vault/TotpSetupPanel.tsx +198 -0
  377. package/src/components/vault/VaultSidebar.tsx +881 -0
  378. package/src/components/vault/credentialFormName.ts +91 -0
  379. package/src/components/vault/hooks/useVaultKeyboardShortcuts.ts +69 -0
  380. package/src/components/vault/types.ts +56 -0
  381. package/src/context/AuthContext.tsx +365 -0
  382. package/src/context/PriceContext.tsx +113 -0
  383. package/src/context/ThemeContext.tsx +164 -0
  384. package/src/context/WebSocketContext.tsx +269 -0
  385. package/src/context/WorkspaceContext.tsx +668 -0
  386. package/src/hooks/index.ts +4 -0
  387. package/src/hooks/useAgentActions.ts +552 -0
  388. package/src/hooks/useBalance.ts +103 -0
  389. package/src/hooks/useBalances.ts +129 -0
  390. package/src/hooks/useTheme.ts +156 -0
  391. package/src/instrumentation.ts +12 -0
  392. package/src/lib/api-docs.ts +154 -0
  393. package/src/lib/api.ts +474 -0
  394. package/src/lib/app-loader.ts +148 -0
  395. package/src/lib/app-registry.ts +178 -0
  396. package/src/lib/app-sdk.ts +157 -0
  397. package/src/lib/audit-console-adapter.ts +151 -0
  398. package/src/lib/auth-client.ts +75 -0
  399. package/src/lib/config.ts +74 -0
  400. package/src/lib/credential-field-schema.ts +11 -0
  401. package/src/lib/crypto.ts +112 -0
  402. package/src/lib/db.ts +21 -0
  403. package/src/lib/docs.ts +544 -0
  404. package/src/lib/events.ts +363 -0
  405. package/src/lib/pino.ts +24 -0
  406. package/src/lib/theme-handlers.ts +168 -0
  407. package/src/lib/theme.ts +351 -0
  408. package/src/lib/tokenData.ts +378 -0
  409. package/src/lib/totp-import.ts +57 -0
  410. package/src/lib/vault-crypto.ts +129 -0
  411. package/src/lib/view-registry.ts +57 -0
  412. package/src/lib/websocket-server.ts +302 -0
  413. package/src/lib/websocket-setup.ts +79 -0
  414. package/src/lib/wordlist.ts +2050 -0
  415. package/src/lib/workspace-handlers.ts +285 -0
  416. package/start.sh +170 -0
  417. package/tailwind.config.ts +99 -0
  418. package/tsconfig.json +42 -0
@@ -0,0 +1,665 @@
1
+ import { Router, Request, Response } from 'express';
2
+ import { createPublicClient, createWalletClient, http, parseEther } from 'viem';
3
+ import { privateKeyToAccount } from 'viem/accounts';
4
+ import { base, mainnet, ink, unichain } from 'viem/chains';
5
+ import {
6
+ DopplerSDK,
7
+ MulticurveBuilder,
8
+ StaticAuctionBuilder,
9
+ DynamicAuctionBuilder,
10
+ FEE_TIERS,
11
+ DAY_SECONDS,
12
+ getAddresses,
13
+ isSupportedChainId,
14
+ } from '@whetstone-research/doppler-sdk';
15
+ import { getHotWallet, exportHotWallet, tokenCanAccessWallet } from '../lib/hot';
16
+ import { getTempWallet, hasTempWallet } from '../lib/temp';
17
+ import { isUnlocked } from '../lib/cold';
18
+ import { loadConfig, getRpcUrl, resolveChain } from '../lib/config';
19
+ import { prisma } from '../lib/db';
20
+ import { logger, logEvent } from '../lib/logger';
21
+ import { requireWalletAuth } from '../middleware/auth';
22
+ import { hasAnyPermission, isAdmin, buildPermissionDenied } from '../lib/permissions';
23
+ import { getDefault, getDefaultSync } from '../lib/defaults';
24
+ import { getErrorMessage, HttpError } from '../lib/error';
25
+ import { recordTransaction, autoTrackToken } from '../lib/transactions';
26
+
27
+ const router = Router();
28
+
29
+ interface LaunchRequest {
30
+ from: string;
31
+ name: string;
32
+ symbol: string;
33
+ tokenURI?: string;
34
+ type?: 'static' | 'dynamic' | 'multicurve';
35
+
36
+ // Token metadata (builds tokenURI automatically if tokenURI not provided)
37
+ imageUrl?: string; // Public URL of the token image (e.g. telegra.ph)
38
+ metadata?: Record<string, string>; // Extra metadata fields (description, website, twitter, etc.)
39
+
40
+ // Supply config
41
+ initialSupply?: string; // Default: '1000000000' (1B)
42
+ numTokensToSell?: string; // Default: 90% of initialSupply
43
+
44
+ // Multicurve preset (simplest option)
45
+ preset?: 'low' | 'medium' | 'high';
46
+
47
+ // Pool config (advanced)
48
+ fee?: number;
49
+ tickSpacing?: number;
50
+
51
+ // Static auction ticks
52
+ startTick?: number;
53
+ endTick?: number;
54
+
55
+ // Dynamic auction config
56
+ duration?: number; // seconds
57
+ epochLength?: number; // seconds
58
+ minProceeds?: string; // ETH
59
+ maxProceeds?: string; // ETH
60
+
61
+ // Migration after auction
62
+ migration?: 'uniswapV2' | 'uniswapV3' | 'uniswapV4' | 'noOp';
63
+
64
+ // Vesting
65
+ vestingDuration?: number; // seconds
66
+
67
+ // Scheduling (multicurve only)
68
+ startTime?: number; // Unix timestamp
69
+
70
+ // Governance
71
+ governance?: 'default' | 'noOp';
72
+
73
+ // Beneficiaries (fee recipients for the launched pool)
74
+ beneficiaries?: { address: string; shares: string }[];
75
+
76
+ chain?: string;
77
+ description?: string;
78
+ }
79
+
80
+ // Map chain names to viem chain objects
81
+ const VIEM_CHAINS: Record<string, typeof base> = {
82
+ base,
83
+ ethereum: mainnet,
84
+ ink,
85
+ unichain,
86
+ };
87
+
88
+ // POST /launch - Launch a token via Doppler protocol
89
+ router.post('/', requireWalletAuth, async (req: Request, res: Response) => {
90
+ try {
91
+ const {
92
+ from,
93
+ name,
94
+ symbol,
95
+ tokenURI: explicitTokenURI,
96
+ imageUrl,
97
+ metadata: extraMetadata,
98
+ type: auctionType = 'multicurve',
99
+ initialSupply: initialSupplyStr,
100
+ numTokensToSell: numTokensToSellStr,
101
+ preset,
102
+ fee,
103
+ tickSpacing,
104
+ startTick,
105
+ endTick,
106
+ duration,
107
+ epochLength,
108
+ minProceeds: minProceedsStr,
109
+ maxProceeds: maxProceedsStr,
110
+ migration = 'uniswapV2',
111
+ vestingDuration,
112
+ startTime,
113
+ governance = 'default',
114
+ beneficiaries,
115
+ chain,
116
+ description: userDescription,
117
+ } = req.body as LaunchRequest;
118
+
119
+ const auth = req.auth!;
120
+
121
+ // Validate required fields
122
+ if (!from || typeof from !== 'string') {
123
+ res.status(400).json({ error: 'from address is required' });
124
+ return;
125
+ }
126
+
127
+ if (!name || typeof name !== 'string') {
128
+ res.status(400).json({ error: 'name is required' });
129
+ return;
130
+ }
131
+
132
+ if (!symbol || typeof symbol !== 'string') {
133
+ res.status(400).json({ error: 'symbol is required' });
134
+ return;
135
+ }
136
+
137
+ if (!['static', 'dynamic', 'multicurve'].includes(auctionType)) {
138
+ res.status(400).json({ error: 'type must be "static", "dynamic", or "multicurve"' });
139
+ return;
140
+ }
141
+
142
+ // Get chain config
143
+ const { targetChain, chainConfig } = resolveChain(chain);
144
+
145
+ // Doppler only supports EVM chains
146
+ if (!isSupportedChainId(chainConfig.chainId)) {
147
+ res.status(400).json({
148
+ error: `Doppler does not support chain ${targetChain} (chainId: ${chainConfig.chainId})`
149
+ });
150
+ return;
151
+ }
152
+
153
+ // Determine wallet type and verify ownership
154
+ const hotWallet = await getHotWallet(from);
155
+ const tempWallet = getTempWallet(from);
156
+
157
+ if (!hotWallet && !tempWallet) {
158
+ res.status(404).json({ error: 'Wallet not found' });
159
+ return;
160
+ }
161
+
162
+ // Permission checks
163
+ if (!isAdmin(auth) && !hasAnyPermission(auth.token.permissions, ['launch'])) {
164
+ logger.permissionDenied('launch', auth.token.agentId, '/launch');
165
+ res.status(403).json(buildPermissionDenied('Token does not have launch permission', ['launch'], auth.token.permissions));
166
+ return;
167
+ }
168
+
169
+ if (hotWallet) {
170
+ const canAccess = await tokenCanAccessWallet(auth.tokenHash, auth.token.walletAccess, from);
171
+ if (!isAdmin(auth) && !canAccess) {
172
+ logger.permissionDenied('wallet_access', auth.token.agentId, '/launch');
173
+ res.status(403).json(buildPermissionDenied('Token does not have access to this wallet', ['wallet:access'], auth.token.permissions));
174
+ return;
175
+ }
176
+
177
+ if (!isUnlocked()) {
178
+ logger.authFailed('Cold wallet locked', '/launch');
179
+ res.status(401).json({ error: 'Cold wallet must be unlocked to launch from hot wallet' });
180
+ return;
181
+ }
182
+ } else if (tempWallet) {
183
+ if (!isAdmin(auth) && !hasAnyPermission(auth.token.permissions, ['launch'])) {
184
+ logger.permissionDenied('launch', auth.token.agentId, '/launch');
185
+ res.status(403).json(buildPermissionDenied('Token does not have launch permission', ['launch'], auth.token.permissions));
186
+ return;
187
+ }
188
+ }
189
+
190
+ // Get the wallet's private key for viem
191
+ let privateKey: `0x${string}`;
192
+
193
+ if (hotWallet) {
194
+ const exported = await exportHotWallet(from);
195
+ privateKey = exported.privateKey as `0x${string}`;
196
+ if (!privateKey.startsWith('0x')) {
197
+ privateKey = `0x${privateKey}` as `0x${string}`;
198
+ }
199
+ } else if (tempWallet) {
200
+ privateKey = tempWallet.privateKey as `0x${string}`;
201
+ if (!privateKey.startsWith('0x')) {
202
+ privateKey = `0x${privateKey}` as `0x${string}`;
203
+ }
204
+ } else {
205
+ res.status(404).json({ error: 'Wallet not found' });
206
+ return;
207
+ }
208
+
209
+ // Set up viem clients
210
+ const rpcUrl = await getRpcUrl(targetChain);
211
+ const viemChain = VIEM_CHAINS[targetChain];
212
+
213
+ if (!viemChain) {
214
+ res.status(400).json({ error: `No viem chain config for ${targetChain}` });
215
+ return;
216
+ }
217
+
218
+ const account = privateKeyToAccount(privateKey);
219
+
220
+ const publicClient = createPublicClient({
221
+ chain: viemChain,
222
+ transport: http(rpcUrl),
223
+ });
224
+
225
+ const walletClient = createWalletClient({
226
+ chain: viemChain,
227
+ transport: http(rpcUrl),
228
+ account,
229
+ });
230
+
231
+ // Initialize Doppler SDK
232
+ const sdk = new DopplerSDK({
233
+ publicClient,
234
+ walletClient,
235
+ chainId: chainConfig.chainId,
236
+ });
237
+
238
+ const addresses = getAddresses(chainConfig.chainId);
239
+ const defaultSupply = await getDefault<string>('launch.initial_supply', '1000000000');
240
+ const defaultSellPercent = await getDefault<number>('launch.sell_percent', 90);
241
+ const supplyStr = initialSupplyStr || String(defaultSupply);
242
+ const initialSupply = parseEther(supplyStr);
243
+ const numTokensToSell = numTokensToSellStr
244
+ ? parseEther(numTokensToSellStr)
245
+ : (initialSupply * BigInt(defaultSellPercent)) / 100n;
246
+
247
+ // Build tokenURI: explicit tokenURI wins, otherwise build from imageUrl/metadata
248
+ let tokenURI = explicitTokenURI || '';
249
+ if (!tokenURI && (imageUrl || extraMetadata)) {
250
+ const metadataJson: Record<string, unknown> = {
251
+ name,
252
+ symbol,
253
+ ...(imageUrl && { image: imageUrl }),
254
+ ...extraMetadata,
255
+ };
256
+ const encoded = Buffer.from(JSON.stringify(metadataJson)).toString('base64');
257
+ tokenURI = `data:application/json;base64,${encoded}`;
258
+ }
259
+
260
+ const tokenConfig = {
261
+ name,
262
+ symbol,
263
+ tokenURI,
264
+ };
265
+
266
+ const saleConfig = {
267
+ initialSupply,
268
+ numTokensToSell,
269
+ numeraire: addresses.weth,
270
+ };
271
+
272
+ // Protocol fee address (integrator for all launches)
273
+ const protocolFeeAddress = getDefaultSync('protocol.fee_address', '0xa931533E0E0cCE34fc0FafB25ea2046d391eCAA5') as `0x${string}`;
274
+
275
+ // Convert beneficiaries from API format to SDK format
276
+ const sdkBeneficiaries = beneficiaries?.map(b => ({
277
+ beneficiary: b.address as `0x${string}`,
278
+ shares: parseEther(b.shares),
279
+ }));
280
+
281
+ let result: {
282
+ tokenAddress?: string;
283
+ poolAddress?: string;
284
+ hookAddress?: string;
285
+ poolId?: string;
286
+ hash?: string;
287
+ };
288
+
289
+ if (auctionType === 'multicurve') {
290
+ const builder = new MulticurveBuilder(chainConfig.chainId)
291
+ .tokenConfig(tokenConfig)
292
+ .saleConfig(saleConfig);
293
+
294
+ // Use preset or manual config
295
+ if (preset) {
296
+ builder.withMarketCapPresets({
297
+ fee: fee ?? FEE_TIERS.LOW,
298
+ presets: [preset],
299
+ ...(sdkBeneficiaries && { beneficiaries: sdkBeneficiaries }),
300
+ });
301
+ } else {
302
+ builder.poolConfig({
303
+ fee: fee ?? 0,
304
+ tickSpacing: tickSpacing ?? 8,
305
+ curves: [
306
+ { tickLower: 0, tickUpper: 240000, numPositions: 10, shares: parseEther('0.5') },
307
+ { tickLower: 16000, tickUpper: 240000, numPositions: 10, shares: parseEther('0.5') },
308
+ ],
309
+ ...(sdkBeneficiaries && { beneficiaries: sdkBeneficiaries }),
310
+ });
311
+ }
312
+
313
+ if (vestingDuration) {
314
+ builder.withVesting({ duration: BigInt(vestingDuration) });
315
+ }
316
+
317
+ if (startTime) {
318
+ builder.withSchedule({ startTime });
319
+ }
320
+
321
+ builder.withIntegrator(protocolFeeAddress);
322
+ builder.withGovernance({ type: governance === 'noOp' ? 'noOp' : 'default' });
323
+ builder.withMigration({ type: migration as 'uniswapV2' | 'uniswapV3' | 'uniswapV4' | 'noOp' });
324
+ builder.withUserAddress(from as `0x${string}`);
325
+
326
+ const params = builder.build();
327
+ const createResult = await sdk.factory.createMulticurve(params);
328
+
329
+ result = {
330
+ tokenAddress: createResult.tokenAddress,
331
+ poolId: createResult.poolId,
332
+ hash: createResult.transactionHash,
333
+ };
334
+
335
+ } else if (auctionType === 'static') {
336
+ const builder = new StaticAuctionBuilder(chainConfig.chainId)
337
+ .tokenConfig(tokenConfig)
338
+ .saleConfig(saleConfig);
339
+
340
+ if (startTick !== undefined && endTick !== undefined) {
341
+ builder.poolByTicks({
342
+ startTick,
343
+ endTick,
344
+ fee: fee ?? 10000,
345
+ });
346
+ } else {
347
+ builder.poolByTicks({ fee: fee ?? 10000 });
348
+ }
349
+
350
+ if (vestingDuration) {
351
+ builder.withVesting({ duration: BigInt(vestingDuration) });
352
+ }
353
+
354
+ if (sdkBeneficiaries) {
355
+ builder.withBeneficiaries(sdkBeneficiaries);
356
+ }
357
+
358
+ builder.withIntegrator(protocolFeeAddress);
359
+ builder.withGovernance({ type: governance === 'noOp' ? 'noOp' : 'default' });
360
+ builder.withMigration({ type: migration as 'uniswapV2' | 'uniswapV3' | 'uniswapV4' | 'noOp' });
361
+ builder.withUserAddress(from as `0x${string}`);
362
+
363
+ const params = builder.build();
364
+ const createResult = await sdk.factory.createStaticAuction(params);
365
+
366
+ result = {
367
+ tokenAddress: createResult.tokenAddress,
368
+ poolAddress: createResult.poolAddress,
369
+ hash: createResult.transactionHash,
370
+ };
371
+
372
+ } else if (auctionType === 'dynamic') {
373
+ if (beneficiaries?.length) {
374
+ logEvent({ category: 'system', action: 'launch_warning', description: 'Beneficiaries are not supported for dynamic auctions — ignoring' });
375
+ }
376
+
377
+ const builder = new DynamicAuctionBuilder(chainConfig.chainId)
378
+ .tokenConfig(tokenConfig)
379
+ .saleConfig(saleConfig)
380
+ .poolConfig({
381
+ fee: fee ?? 3000,
382
+ tickSpacing: tickSpacing ?? 60,
383
+ });
384
+
385
+ const defaultEpochLength = await getDefault<number>('launch.epoch_length', 3600);
386
+ builder.auctionByTicks({
387
+ duration: duration ?? 7 * DAY_SECONDS,
388
+ epochLength: epochLength ?? defaultEpochLength,
389
+ startTick: startTick ?? -92103,
390
+ endTick: endTick ?? -69080,
391
+ minProceeds: minProceedsStr ? parseEther(minProceedsStr) : parseEther('0.1'),
392
+ maxProceeds: maxProceedsStr ? parseEther(maxProceedsStr) : parseEther('100'),
393
+ });
394
+
395
+ if (vestingDuration) {
396
+ builder.withVesting({ duration: BigInt(vestingDuration) });
397
+ }
398
+
399
+ builder.withIntegrator(protocolFeeAddress);
400
+ builder.withGovernance({ type: governance === 'noOp' ? 'noOp' : 'default' });
401
+ builder.withMigration({ type: migration as 'uniswapV2' | 'uniswapV3' | 'uniswapV4' | 'noOp' });
402
+ builder.withUserAddress(from as `0x${string}`);
403
+
404
+ const params = builder.build();
405
+ const createResult = await sdk.factory.createDynamicAuction(params);
406
+
407
+ result = {
408
+ tokenAddress: createResult.tokenAddress,
409
+ hookAddress: createResult.hookAddress,
410
+ poolId: createResult.poolId,
411
+ hash: createResult.transactionHash,
412
+ };
413
+ } else {
414
+ res.status(400).json({ error: `Unknown auction type: ${auctionType}` });
415
+ return;
416
+ }
417
+
418
+ // Log the launch
419
+ const txHash = result.hash || '';
420
+ const description = userDescription || `Launched ${symbol} (${name}) via Doppler ${auctionType} auction`;
421
+
422
+ await recordTransaction({
423
+ walletAddress: from,
424
+ txHash,
425
+ type: 'launch',
426
+ tokenAddress: result.tokenAddress || undefined,
427
+ from,
428
+ to: result.poolAddress || result.hookAddress || addresses.airlock,
429
+ description,
430
+ chain: targetChain,
431
+ logTitle: `Token Launch: ${symbol}`,
432
+ });
433
+
434
+ // Auto-track the launched token
435
+ if (result.tokenAddress) {
436
+ await autoTrackToken({
437
+ walletAddress: from,
438
+ tokenAddress: result.tokenAddress,
439
+ chain: targetChain,
440
+ symbol,
441
+ name,
442
+ });
443
+ }
444
+
445
+ // Log event
446
+ const agentId = !isAdmin(auth) ? auth.token.agentId : undefined;
447
+ logger.swap(from, 'ETH', symbol, '0', txHash, agentId); // Reuse swap logger for now
448
+
449
+ res.json({
450
+ success: true,
451
+ hash: txHash,
452
+ from,
453
+ tokenAddress: result.tokenAddress,
454
+ ...(result.poolAddress && { poolAddress: result.poolAddress }),
455
+ ...(result.hookAddress && { hookAddress: result.hookAddress }),
456
+ ...(result.poolId && { poolId: result.poolId }),
457
+ type: auctionType,
458
+ name,
459
+ symbol,
460
+ chain: targetChain,
461
+ });
462
+
463
+ } catch (error) {
464
+ if (error instanceof HttpError) { res.status(error.status).json({ error: error.message }); return; }
465
+ res.status(500).json({ error: getErrorMessage(error) });
466
+ }
467
+ });
468
+
469
+ // Helper: set up viem clients + Doppler SDK for fee collection
470
+ async function createSdkForWallet(from: string, targetChain: string) {
471
+ const config = loadConfig();
472
+ const chainConfig = config.chains[targetChain];
473
+ if (!chainConfig) throw new Error(`Unknown chain: ${targetChain}`);
474
+ if (!isSupportedChainId(chainConfig.chainId)) {
475
+ throw new Error(`Doppler does not support chain ${targetChain}`);
476
+ }
477
+
478
+ const hotWallet = await getHotWallet(from);
479
+ const tempWallet = getTempWallet(from);
480
+ if (!hotWallet && !tempWallet) throw new Error('Wallet not found');
481
+
482
+ let privateKey: `0x${string}`;
483
+ if (hotWallet) {
484
+ const exported = await exportHotWallet(from);
485
+ privateKey = exported.privateKey as `0x${string}`;
486
+ if (!privateKey.startsWith('0x')) privateKey = `0x${privateKey}` as `0x${string}`;
487
+ } else {
488
+ privateKey = tempWallet!.privateKey as `0x${string}`;
489
+ if (!privateKey.startsWith('0x')) privateKey = `0x${privateKey}` as `0x${string}`;
490
+ }
491
+
492
+ const rpcUrl = await getRpcUrl(targetChain);
493
+ const viemChain = VIEM_CHAINS[targetChain];
494
+ if (!viemChain) throw new Error(`No viem chain config for ${targetChain}`);
495
+
496
+ const account = privateKeyToAccount(privateKey);
497
+ const publicClient = createPublicClient({ chain: viemChain, transport: http(rpcUrl) });
498
+ const walletClient = createWalletClient({ chain: viemChain, transport: http(rpcUrl), account });
499
+
500
+ const sdk = new DopplerSDK({ publicClient, walletClient, chainId: chainConfig.chainId });
501
+ return { sdk, hotWallet, tempWallet };
502
+ }
503
+
504
+ // POST /launch/collect-fees - Collect fees from ALL launched tokens
505
+ // No launch permission required — collectFees is permissionless on-chain,
506
+ // fees always go to configured beneficiaries. Caller only pays gas.
507
+ router.post('/collect-fees', requireWalletAuth, async (req: Request, res: Response) => {
508
+ try {
509
+ const { from, chain } = req.body as { from: string; chain?: string };
510
+ const auth = req.auth!;
511
+
512
+ if (!from || typeof from !== 'string') {
513
+ res.status(400).json({ error: 'from address is required (wallet to pay gas)' });
514
+ return;
515
+ }
516
+
517
+ const hotWallet = await getHotWallet(from);
518
+ const tempWallet = getTempWallet(from);
519
+ if (!hotWallet && !tempWallet) {
520
+ res.status(404).json({ error: 'Wallet not found' });
521
+ return;
522
+ }
523
+
524
+ if (hotWallet) {
525
+ const canAccess = await tokenCanAccessWallet(auth.tokenHash, auth.token.walletAccess, from);
526
+ if (!isAdmin(auth) && !canAccess) {
527
+ logger.permissionDenied('wallet_access', auth.token.agentId, '/launch/collect-fees');
528
+ res.status(403).json(buildPermissionDenied('Token does not have access to this wallet', ['wallet:access'], auth.token.permissions));
529
+ return;
530
+ }
531
+ }
532
+
533
+ const config = loadConfig();
534
+ const targetChain = chain || config.defaultChain;
535
+
536
+ // Find all launched tokens on this chain
537
+ const launches = await prisma.transaction.findMany({
538
+ where: {
539
+ type: 'launch',
540
+ chain: targetChain,
541
+ tokenAddress: { not: null },
542
+ },
543
+ select: { tokenAddress: true },
544
+ distinct: ['tokenAddress'],
545
+ });
546
+
547
+ if (launches.length === 0) {
548
+ res.json({ success: true, message: 'No launched tokens found', results: [] });
549
+ return;
550
+ }
551
+
552
+ const { sdk } = await createSdkForWallet(from, targetChain);
553
+
554
+ const results: Array<{
555
+ tokenAddress: string;
556
+ success: boolean;
557
+ fees0?: string;
558
+ fees1?: string;
559
+ transactionHash?: string;
560
+ error?: string;
561
+ }> = [];
562
+
563
+ for (const launch of launches) {
564
+ const tokenAddr = launch.tokenAddress!;
565
+ try {
566
+ const pool = await sdk.getMulticurvePool(tokenAddr as `0x${string}`);
567
+ const { fees0, fees1, transactionHash } = await pool.collectFees();
568
+ results.push({
569
+ tokenAddress: tokenAddr,
570
+ success: true,
571
+ fees0: fees0.toString(),
572
+ fees1: fees1.toString(),
573
+ transactionHash,
574
+ });
575
+ } catch (err) {
576
+ results.push({
577
+ tokenAddress: tokenAddr,
578
+ success: false,
579
+ error: getErrorMessage(err),
580
+ });
581
+ }
582
+ }
583
+
584
+ const collected = results.filter(r => r.success).length;
585
+ const failed = results.filter(r => !r.success).length;
586
+
587
+ res.json({
588
+ success: true,
589
+ chain: targetChain,
590
+ total: launches.length,
591
+ collected,
592
+ failed,
593
+ results,
594
+ });
595
+
596
+ } catch (error) {
597
+ if (error instanceof HttpError) { res.status(error.status).json({ error: error.message }); return; }
598
+ res.status(500).json({ error: getErrorMessage(error) });
599
+ }
600
+ });
601
+
602
+ // POST /launch/:tokenAddress/collect-fees - Collect fees from a specific launched token
603
+ // No launch permission required — collectFees is permissionless on-chain,
604
+ // fees always go to configured beneficiaries. Caller only pays gas.
605
+ router.post('/:tokenAddress/collect-fees', requireWalletAuth, async (req: Request<{ tokenAddress: string }>, res: Response) => {
606
+ try {
607
+ const { tokenAddress } = req.params;
608
+ const { from, chain } = req.body as { from: string; chain?: string };
609
+ const auth = req.auth!;
610
+
611
+ if (!from || typeof from !== 'string') {
612
+ res.status(400).json({ error: 'from address is required (wallet to pay gas)' });
613
+ return;
614
+ }
615
+
616
+ const hotWallet = await getHotWallet(from);
617
+ const tempWallet = getTempWallet(from);
618
+ if (!hotWallet && !tempWallet) {
619
+ res.status(404).json({ error: 'Wallet not found' });
620
+ return;
621
+ }
622
+
623
+ if (hotWallet) {
624
+ const canAccess = await tokenCanAccessWallet(auth.tokenHash, auth.token.walletAccess, from);
625
+ if (!isAdmin(auth) && !canAccess) {
626
+ logger.permissionDenied('wallet_access', auth.token.agentId, `/launch/${tokenAddress}/collect-fees`);
627
+ res.status(403).json(buildPermissionDenied('Token does not have access to this wallet', ['wallet:access'], auth.token.permissions));
628
+ return;
629
+ }
630
+ }
631
+
632
+ const config = loadConfig();
633
+ const targetChain = chain || config.defaultChain;
634
+
635
+ const { sdk } = await createSdkForWallet(from, targetChain);
636
+
637
+ const pool = await sdk.getMulticurvePool(tokenAddress as `0x${string}`);
638
+ const { fees0, fees1, transactionHash } = await pool.collectFees();
639
+
640
+ // Log the fee collection
641
+ await prisma.log.create({
642
+ data: {
643
+ walletAddress: from,
644
+ title: `Fee Collection: ${tokenAddress}`,
645
+ description: `Collected fees from launched token ${tokenAddress} (fees0: ${fees0}, fees1: ${fees1})`,
646
+ txHash: transactionHash,
647
+ }
648
+ });
649
+
650
+ res.json({
651
+ success: true,
652
+ tokenAddress,
653
+ fees0: fees0.toString(),
654
+ fees1: fees1.toString(),
655
+ transactionHash,
656
+ chain: targetChain,
657
+ });
658
+
659
+ } catch (error) {
660
+ if (error instanceof HttpError) { res.status(error.status).json({ error: error.message }); return; }
661
+ res.status(500).json({ error: getErrorMessage(error) });
662
+ }
663
+ });
664
+
665
+ export default router;