├── .changeset ├── README.md └── config.json ├── .cursor └── rules │ ├── org-general-practices.mdc │ ├── org-typescript-standards.mdc │ └── repo-specific-config.mdc ├── .dockerignore ├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── actions │ └── api-sdk-check │ │ └── action.yml ├── changeset-version.js └── workflows │ ├── api-ci.yml │ ├── code-quality.yml │ └── release.yml ├── .gitignore ├── .gitmodules ├── .npmrc ├── .prettierignore ├── .prettierrc ├── .vscode └── settings.json ├── .zed └── settings.json ├── README.md ├── apps ├── api │ ├── .env.example │ ├── .env.test │ ├── README.md │ ├── drizzle.config.ts │ ├── drizzle │ │ ├── 0000_mighty_psynapse.sql │ │ ├── 0001_naive_ben_grimm.sql │ │ ├── 0002_polite_obadiah_stane.sql │ │ ├── 0003_yielding_killraven.sql │ │ └── meta │ │ │ ├── 0000_snapshot.json │ │ │ ├── 0001_snapshot.json │ │ │ ├── 0002_snapshot.json │ │ │ ├── 0003_snapshot.json │ │ │ └── _journal.json │ ├── e2e │ │ ├── README.md │ │ ├── run-tests.ts │ │ ├── setup.ts │ │ ├── tests │ │ │ ├── admin.test.ts │ │ │ ├── agent.test.ts │ │ │ ├── api-key-retrieval.test.ts │ │ │ ├── auth.test.ts │ │ │ ├── base-trades.test.ts │ │ │ ├── chain-specific.test.ts │ │ │ ├── competition.test.ts │ │ │ ├── deactivate.test.ts │ │ │ ├── leaderboard-access.test.ts │ │ │ ├── multi-agent-competition.test.ts │ │ │ ├── portfolio-snapshots.test.ts │ │ │ ├── price-fetching.test.ts │ │ │ ├── price │ │ │ │ ├── chain-detection-debug.test.ts │ │ │ │ └── multi-chain-provider.test.ts │ │ │ ├── rate-limiter-diagnostic.test.ts │ │ │ ├── rate-limiter.test.ts │ │ │ ├── trading.test.ts │ │ │ └── user.test.ts │ │ └── utils │ │ │ ├── api-client.ts │ │ │ ├── api-types.ts │ │ │ ├── db-manager.ts │ │ │ ├── log-reporter.ts │ │ │ ├── server.ts │ │ │ ├── setup-admin.ts │ │ │ ├── siwe-utils.ts │ │ │ ├── test-helpers.ts │ │ │ └── test-setup.ts │ ├── eslint.config.mjs │ ├── openapi │ │ ├── API.md │ │ └── openapi.json │ ├── package.json │ ├── scripts │ │ ├── clean-db.ts │ │ ├── competition-status.ts │ │ ├── delete-agent.ts │ │ ├── delete-user.ts │ │ ├── drop-all.ts │ │ ├── edit-agent.ts │ │ ├── edit-user.ts │ │ ├── end-competition.ts │ │ ├── generate-secrets.ts │ │ ├── list-agents.ts │ │ ├── list-users.ts │ │ ├── register-agent.ts │ │ ├── register-user.ts │ │ ├── seed-db.ts │ │ ├── setup-admin.ts │ │ ├── setup-competition.ts │ │ └── setup-everything.ts │ ├── src │ │ ├── config │ │ │ ├── index.ts │ │ │ └── swagger.ts │ │ ├── controllers │ │ │ ├── admin.controller.ts │ │ │ ├── agent.controller.ts │ │ │ ├── auth.controller.ts │ │ │ ├── competition.controller.ts │ │ │ ├── docs.controller.ts │ │ │ ├── health.controller.ts │ │ │ ├── price.controller.ts │ │ │ ├── trade.controller.ts │ │ │ └── user.controller.ts │ │ ├── database │ │ │ ├── db.ts │ │ │ ├── repositories │ │ │ │ ├── admin-repository.ts │ │ │ │ ├── agent-repository.ts │ │ │ │ ├── balance-repository.ts │ │ │ │ ├── competition-repository.ts │ │ │ │ ├── helpers.ts │ │ │ │ ├── price-repository.ts │ │ │ │ ├── trade-repository.ts │ │ │ │ ├── types.ts │ │ │ │ └── user-repository.ts │ │ │ └── schema │ │ │ │ ├── core │ │ │ │ ├── defs.ts │ │ │ │ ├── relations.ts │ │ │ │ └── types.ts │ │ │ │ ├── index.ts │ │ │ │ ├── trading │ │ │ │ ├── defs.ts │ │ │ │ ├── relations.ts │ │ │ │ └── types.ts │ │ │ │ ├── util.ts │ │ │ │ └── voting │ │ │ │ ├── defs.ts │ │ │ │ ├── relations.ts │ │ │ │ └── types.ts │ │ ├── express.d.ts │ │ ├── index.ts │ │ ├── middleware │ │ │ ├── admin-auth.middleware.ts │ │ │ ├── auth-helpers.ts │ │ │ ├── auth.middleware.ts │ │ │ ├── errorHandler.ts │ │ │ ├── rate-limiter.middleware.ts │ │ │ └── siwe.middleware.ts │ │ ├── routes │ │ │ ├── admin-setup.routes.ts │ │ │ ├── admin.routes.ts │ │ │ ├── agent.routes.ts │ │ │ ├── agents.routes.ts │ │ │ ├── auth.routes.ts │ │ │ ├── competitions.routes.ts │ │ │ ├── docs.routes.ts │ │ │ ├── health.routes.ts │ │ │ ├── price.routes.ts │ │ │ ├── trade.routes.ts │ │ │ └── user.routes.ts │ │ ├── services │ │ │ ├── admin-manager.service.ts │ │ │ ├── agent-manager.service.ts │ │ │ ├── auth.service.ts │ │ │ ├── balance-manager.service.ts │ │ │ ├── competition-manager.service.ts │ │ │ ├── configuration.service.ts │ │ │ ├── index.ts │ │ │ ├── portfolio-snapshotter.service.ts │ │ │ ├── price-tracker.service.ts │ │ │ ├── providers │ │ │ │ ├── __tests__ │ │ │ │ │ ├── chain-override.test.ts │ │ │ │ │ ├── dexscreener.provider.test.ts │ │ │ │ │ └── multi-chain.provider.test.ts │ │ │ │ ├── dexscreener.provider.ts │ │ │ │ ├── jupiter.provider.ts │ │ │ │ ├── multi-chain.provider.ts │ │ │ │ ├── noves.provider.ts │ │ │ │ └── raydium.provider.ts │ │ │ ├── scheduler.service.ts │ │ │ ├── trade-simulator.service.ts │ │ │ └── user-manager.service.ts │ │ └── types │ │ │ └── index.ts │ ├── trade-simulator-docker │ │ ├── Dockerfile │ │ ├── docker-compose.yml │ │ ├── instructions.md │ │ └── startup.sh │ ├── tsconfig.json │ ├── turbo.json │ └── vitest.config.ts ├── comps │ ├── .env.example │ ├── README.md │ ├── app │ │ ├── agents │ │ │ └── [id] │ │ │ │ └── page.tsx │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── competitions │ │ │ ├── [id] │ │ │ │ └── page.tsx │ │ │ └── page.tsx │ │ ├── create-agent │ │ │ └── page.tsx │ │ ├── favicon.ico │ │ ├── layout.tsx │ │ ├── leaderboards │ │ │ └── page.tsx │ │ ├── onboarding │ │ │ └── page.tsx │ │ ├── page.tsx │ │ └── profile │ │ │ └── page.tsx │ ├── components.json │ ├── components │ │ ├── .gitkeep │ │ ├── achievement-card │ │ │ └── index.tsx │ │ ├── agent-card.tsx │ │ ├── agent-created.tsx │ │ ├── agent-podium │ │ │ ├── award-icon.tsx │ │ │ └── index.tsx │ │ ├── agent-profile │ │ │ └── index.tsx │ │ ├── agent-spotlight-section.tsx │ │ ├── agents-table │ │ │ ├── index.tsx │ │ │ └── rank-badge.tsx │ │ ├── animations │ │ │ ├── carousel.tsx │ │ │ ├── reveal.tsx │ │ │ ├── text.tsx │ │ │ └── train.tsx │ │ ├── back-button.tsx │ │ ├── bignumber │ │ │ └── index.tsx │ │ ├── breadcrumb-nav.tsx │ │ ├── breadcrumb │ │ │ └── index.tsx │ │ ├── clock │ │ │ └── index.tsx │ │ ├── competition-card.tsx │ │ ├── competition-info.tsx │ │ ├── competition-skeleton.tsx │ │ ├── competition-status-badge.tsx │ │ ├── competition-table.tsx │ │ ├── create-agent.tsx │ │ ├── footer-section │ │ │ └── index.tsx │ │ ├── hexagon │ │ │ └── index.tsx │ │ ├── identicon │ │ │ └── index.tsx │ │ ├── join-swarm-section.tsx │ │ ├── leaderboard-table.tsx │ │ ├── leaderboard │ │ │ └── index.tsx │ │ ├── link-previewer │ │ │ └── index.tsx │ │ ├── main-page │ │ │ ├── agent-section.tsx │ │ │ ├── backed-by.tsx │ │ │ ├── compete-section.tsx │ │ │ ├── discover-section.tsx │ │ │ ├── hero-section.tsx │ │ │ ├── new-hightlights.tsx │ │ │ └── subscribe-section.tsx │ │ ├── mirror-image │ │ │ └── index.tsx │ │ ├── navbar │ │ │ └── index.tsx │ │ ├── newsletter-section.tsx │ │ ├── onboarding │ │ │ ├── add-funds.tsx │ │ │ ├── agent-live.tsx │ │ │ ├── register-agent.tsx │ │ │ └── screen.tsx │ │ ├── ongoing-competition.tsx │ │ ├── ongoing-competition │ │ │ └── leaderboard.tsx │ │ ├── profile-skeleton.tsx │ │ ├── providers.tsx │ │ ├── recently-ended-section.tsx │ │ ├── register-agent-block.tsx │ │ ├── siwe │ │ │ └── index.tsx │ │ ├── social-link-card.tsx │ │ ├── starting-soon-section.tsx │ │ ├── string-list.tsx │ │ ├── upcoming-competition.tsx │ │ ├── update-profile.tsx │ │ ├── user-agents │ │ │ └── index.tsx │ │ └── user-info │ │ │ ├── ProfilePicture.tsx │ │ │ └── index.tsx │ ├── data │ │ └── social.ts │ ├── eslint.config.js │ ├── hooks │ │ ├── .gitkeep │ │ ├── index.ts │ │ ├── useAgent.ts │ │ ├── useAgentCompetitions.ts │ │ ├── useAgents.ts │ │ ├── useAuth.ts │ │ ├── useCompetition.ts │ │ ├── useCompetitionAgents.ts │ │ ├── useCompetitions.ts │ │ ├── useCreateAgent.ts │ │ ├── useInView.ts │ │ ├── useJoinCompetition.ts │ │ ├── useLeaderboards.ts │ │ ├── useLeaveCompetition.ts │ │ └── useProfile.ts │ ├── lib │ │ ├── .gitkeep │ │ └── api-client.ts │ ├── next-env.d.ts │ ├── next.config.mjs │ ├── package.json │ ├── postcss.config.mjs │ ├── public │ │ ├── .gitkeep │ │ ├── agent-placeholder.png │ │ ├── backers │ │ │ ├── 1.png │ │ │ ├── 2.png │ │ │ ├── 3.png │ │ │ ├── 4.png │ │ │ └── 5.png │ │ ├── cards │ │ │ ├── 1.png │ │ │ ├── 2.png │ │ │ ├── 3.png │ │ │ └── 4.png │ │ ├── competition-placeholder.png │ │ ├── default_agent.png │ │ ├── default_agent_2.png │ │ ├── default_user.png │ │ ├── discord-icon.svg │ │ ├── discover_1.png │ │ ├── discover_2.png │ │ ├── discover_3.png │ │ ├── discover_4.png │ │ ├── discover_5.png │ │ ├── discover_6.png │ │ ├── docs-icon.svg │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── frame.png │ │ ├── frame_2_left.png │ │ ├── frame_2_right.png │ │ ├── frame_3.png │ │ ├── frame_4.png │ │ ├── hero.mp4 │ │ ├── logo_white.png │ │ ├── x-icon.svg │ │ └── youtube-icon.svg │ ├── state │ │ └── atoms.ts │ ├── tsconfig.json │ ├── typedoc.json │ ├── types │ │ ├── agent.ts │ │ ├── api.ts │ │ ├── auth.ts │ │ ├── competition.ts │ │ ├── enums.ts │ │ ├── index.ts │ │ └── profile.ts │ ├── utils │ │ ├── filter.ts │ │ ├── index.ts │ │ ├── paginate.ts │ │ └── sort.ts │ └── wagmi-config.ts ├── faucet │ ├── .env.example │ ├── app │ │ ├── _components │ │ │ └── request-tokens-form.tsx │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ ├── layout.tsx │ │ └── page.tsx │ ├── client-actions.ts │ ├── components.json │ ├── components │ │ └── .gitkeep │ ├── eslint.config.js │ ├── hooks │ │ └── .gitkeep │ ├── next-env.d.ts │ ├── next.config.mjs │ ├── package.json │ ├── postcss.config.mjs │ └── tsconfig.json ├── portal │ ├── .env.example │ ├── README.md │ ├── app │ │ ├── _components │ │ │ ├── agent-activity-entry.tsx │ │ │ ├── agent-activity-list.tsx │ │ │ ├── agent-activity.tsx │ │ │ ├── hero.tsx │ │ │ ├── nav.tsx │ │ │ ├── search-and-filter.tsx │ │ │ └── slash.tsx │ │ ├── account │ │ │ ├── _components │ │ │ │ ├── account-tabs.tsx │ │ │ │ ├── account.tsx │ │ │ │ ├── approval.tsx │ │ │ │ ├── approvals-from.tsx │ │ │ │ └── approvals-to.tsx │ │ │ └── page.tsx │ │ ├── agents │ │ │ ├── _components │ │ │ │ ├── agent.tsx │ │ │ │ ├── agents.tsx │ │ │ │ └── cards │ │ │ │ │ ├── auth.tsx │ │ │ │ │ ├── chat.tsx │ │ │ │ │ ├── memory.tsx │ │ │ │ │ ├── objects.tsx │ │ │ │ │ └── settings.tsx │ │ │ └── page.tsx │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── buckets │ │ │ ├── [address] │ │ │ │ ├── _components │ │ │ │ │ ├── add-object-dialog.tsx │ │ │ │ │ ├── bucket.tsx │ │ │ │ │ ├── credit-needed-dialog.tsx │ │ │ │ │ ├── file-preview-placeholder.tsx │ │ │ │ │ ├── metadata-panel.tsx │ │ │ │ │ ├── object-list-item.tsx │ │ │ │ │ ├── object.tsx │ │ │ │ │ ├── objects.tsx │ │ │ │ │ └── prefix-list-item.tsx │ │ │ │ └── page.tsx │ │ │ ├── _components │ │ │ │ ├── bucket-card.tsx │ │ │ │ └── buckets.tsx │ │ │ └── page.tsx │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ ├── layout.tsx │ │ └── page.tsx │ ├── components.json │ ├── components │ │ ├── .gitkeep │ │ ├── copy-button.tsx │ │ ├── file-previewers │ │ │ ├── binary-metadata-preview.tsx │ │ │ ├── detect-content-type.ts │ │ │ ├── file-previewer.tsx │ │ │ ├── plain-text-preview.tsx │ │ │ ├── test-detection.ts │ │ │ └── types.ts │ │ ├── metric.tsx │ │ └── providers.tsx │ ├── eslint.config.js │ ├── hooks │ │ ├── .gitkeep │ │ ├── useHashmark.ts │ │ └── usePrevious.ts │ ├── lib │ │ ├── .gitkeep │ │ ├── __tests__ │ │ │ └── format-bytes.test.ts │ │ ├── convert-matadata.ts │ │ ├── format-bytes.ts │ │ ├── remove-prefix.ts │ │ └── wagmi-config.ts │ ├── middleware.ts │ ├── next-env.d.ts │ ├── next.config.mjs │ ├── package.json │ ├── postcss.config.mjs │ ├── public │ │ ├── .well-known │ │ │ └── walletconnect.txt │ │ └── recall.svg │ ├── tsconfig.json │ ├── typedoc.json │ ├── types │ │ └── agent-activity.ts │ └── utils │ │ └── fetch-agent-activity.ts └── registration │ ├── .env.example │ ├── README.md │ ├── app │ ├── _components │ │ └── nav.tsx │ ├── account │ │ ├── layout.tsx │ │ └── page.tsx │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── api │ │ ├── auth │ │ │ └── [...nextauth] │ │ │ │ └── route.ts │ │ ├── competition │ │ │ └── upcoming │ │ │ │ └── route.ts │ │ ├── loops-update │ │ │ └── route.ts │ │ ├── team-by-wallet │ │ │ └── route.ts │ │ ├── team │ │ │ ├── trades │ │ │ │ └── route.ts │ │ │ └── update-profile │ │ │ │ └── route.ts │ │ └── teams │ │ │ ├── register │ │ │ └── route.ts │ │ │ └── route.ts │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── layout.tsx │ ├── not-found.tsx │ └── page.tsx │ ├── components │ ├── agent-add-form.tsx │ ├── agent-registration-form.tsx │ ├── auth-provider.tsx │ ├── developer-profile-form.tsx │ ├── providers.tsx │ ├── recall-logo.tsx │ ├── registration-form.tsx │ ├── registration-success.tsx │ └── sign-in-button.tsx │ ├── eslint.config.js │ ├── hooks │ └── auth-state.tsx │ ├── instructions.md │ ├── lib │ ├── api-client.ts │ ├── api.ts │ ├── auth.ts │ ├── utils.ts │ ├── validation.ts │ └── wagmi-config.ts │ ├── middleware.ts │ ├── next-env.d.ts │ ├── next.config.mjs │ ├── package.json │ ├── postcss.config.mjs │ ├── public │ ├── agents-twitter.png │ ├── agents.png │ └── og-image.png │ ├── tsconfig.json │ ├── turbo.json │ ├── typedoc.json │ └── types │ └── next-auth.d.ts ├── build-api-sdk.sh ├── flake.lock ├── flake.nix ├── package.json ├── packages ├── address-utils │ ├── README.md │ ├── eslint.config.js │ ├── package.json │ ├── src │ │ └── display.ts │ ├── tsconfig.json │ ├── tsup.config.ts │ └── typedoc.json ├── agent-toolkit │ ├── CHANGELOG.md │ ├── README.md │ ├── eslint.config.js │ ├── examples │ │ ├── .env.example │ │ ├── ai-sdk.ts │ │ ├── langchain.ts │ │ ├── mcp.ts │ │ └── openai.ts │ ├── package.json │ ├── src │ │ ├── ai-sdk │ │ │ ├── index.ts │ │ │ ├── tool.ts │ │ │ └── toolkit.ts │ │ ├── langchain │ │ │ ├── index.ts │ │ │ ├── tool.ts │ │ │ └── toolkit.ts │ │ ├── mcp │ │ │ ├── index.ts │ │ │ └── toolkit.ts │ │ ├── openai │ │ │ ├── index.ts │ │ │ └── toolkit.ts │ │ └── shared │ │ │ ├── api.ts │ │ │ ├── configuration.ts │ │ │ ├── functions.ts │ │ │ ├── index.ts │ │ │ ├── parameters.ts │ │ │ ├── prompts.ts │ │ │ ├── tools.ts │ │ │ └── util.ts │ ├── tsconfig.json │ └── tsup.config.ts ├── api-mcp │ ├── README.md │ ├── eslint.config.js │ ├── package.json │ ├── src │ │ ├── cli.ts │ │ ├── env.ts │ │ ├── index.ts │ │ ├── server.ts │ │ └── types.ts │ ├── tsconfig.json │ └── tsup.config.ts ├── api-sdk │ ├── .devcontainer │ │ ├── README.md │ │ ├── devcontainer.json │ │ └── setup.sh │ ├── .gitattributes │ ├── .gitignore │ ├── .npmignore │ ├── .speakeasy │ │ ├── gen.lock │ │ ├── gen.yaml │ │ ├── workflow.lock │ │ └── workflow.yaml │ ├── CONTRIBUTING.md │ ├── FUNCTIONS.md │ ├── README.md │ ├── RUNTIMES.md │ ├── USAGE.md │ ├── eslint.config.mjs │ ├── jsr.json │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── core.ts │ │ ├── funcs │ │ │ ├── adminDeleteApiAdminAgentsAgentId.ts │ │ │ ├── adminGetApiAdminAgents.ts │ │ │ ├── adminGetApiAdminAgentsAgentId.ts │ │ │ ├── adminGetApiAdminAgentsAgentIdKey.ts │ │ │ ├── adminGetApiAdminCompetitionCompetitionIdSnapshots.ts │ │ │ ├── adminGetApiAdminReportsPerformance.ts │ │ │ ├── adminGetApiAdminSearch.ts │ │ │ ├── adminGetApiAdminUsers.ts │ │ │ ├── adminPostApiAdminAgentsAgentIdDeactivate.ts │ │ │ ├── adminPostApiAdminAgentsAgentIdReactivate.ts │ │ │ ├── adminPostApiAdminCompetitionCreate.ts │ │ │ ├── adminPostApiAdminCompetitionEnd.ts │ │ │ ├── adminPostApiAdminCompetitionStart.ts │ │ │ ├── adminPostApiAdminSetup.ts │ │ │ ├── adminPostApiAdminUsers.ts │ │ │ ├── agentGetApiAgentAgentId.ts │ │ │ ├── agentGetApiAgentBalances.ts │ │ │ ├── agentGetApiAgentPortfolio.ts │ │ │ ├── agentGetApiAgentProfile.ts │ │ │ ├── agentGetApiAgentTrades.ts │ │ │ ├── agentGetApiAgents.ts │ │ │ ├── agentPostApiAgentResetApiKey.ts │ │ │ ├── agentPutApiAgentProfile.ts │ │ │ ├── authGetApiAuthNonce.ts │ │ │ ├── authPostApiAuthLogin.ts │ │ │ ├── authPostApiAuthLogout.ts │ │ │ ├── competitionDeleteApiCompetitionsCompetitionIdAgentsAgentId.ts │ │ │ ├── competitionGetApiCompetitions.ts │ │ │ ├── competitionGetApiCompetitionsCompetitionId.ts │ │ │ ├── competitionGetApiCompetitionsCompetitionIdAgents.ts │ │ │ ├── competitionGetApiCompetitionsLeaderboard.ts │ │ │ ├── competitionGetApiCompetitionsRules.ts │ │ │ ├── competitionGetApiCompetitionsStatus.ts │ │ │ ├── competitionGetApiCompetitionsUpcoming.ts │ │ │ ├── competitionPostApiCompetitionsCompetitionIdAgentsAgentId.ts │ │ │ ├── healthGetApiHealth.ts │ │ │ ├── healthGetApiHealthDetailed.ts │ │ │ ├── priceGetApiPrice.ts │ │ │ ├── priceGetApiPriceTokenInfo.ts │ │ │ ├── tradeGetApiTradeQuote.ts │ │ │ ├── tradePostApiTradeExecute.ts │ │ │ ├── userGetApiUserAgents.ts │ │ │ ├── userGetApiUserAgentsAgentId.ts │ │ │ ├── userGetApiUserProfile.ts │ │ │ ├── userPostApiUserAgents.ts │ │ │ ├── userPutApiUserAgentsAgentIdProfile.ts │ │ │ └── userPutApiUserProfile.ts │ │ ├── hooks │ │ │ ├── hooks.ts │ │ │ ├── index.ts │ │ │ ├── registration.ts │ │ │ └── types.ts │ │ ├── index.ts │ │ ├── lib │ │ │ ├── base64.ts │ │ │ ├── config.ts │ │ │ ├── dlv.ts │ │ │ ├── encodings.ts │ │ │ ├── env.ts │ │ │ ├── files.ts │ │ │ ├── http.ts │ │ │ ├── is-plain-object.ts │ │ │ ├── logger.ts │ │ │ ├── matchers.ts │ │ │ ├── primitives.ts │ │ │ ├── retries.ts │ │ │ ├── schemas.ts │ │ │ ├── sdks.ts │ │ │ ├── security.ts │ │ │ └── url.ts │ │ ├── mcp-server │ │ │ ├── build.mts │ │ │ ├── cli.ts │ │ │ ├── cli │ │ │ │ └── start │ │ │ │ │ ├── command.ts │ │ │ │ │ └── impl.ts │ │ │ ├── console-logger.ts │ │ │ ├── extensions.ts │ │ │ ├── mcp-server.ts │ │ │ ├── prompts.ts │ │ │ ├── resources.ts │ │ │ ├── scopes.ts │ │ │ ├── server.ts │ │ │ ├── shared.ts │ │ │ ├── tools.ts │ │ │ └── tools │ │ │ │ ├── adminDeleteApiAdminAgentsAgentId.ts │ │ │ │ ├── adminGetApiAdminAgents.ts │ │ │ │ ├── adminGetApiAdminAgentsAgentId.ts │ │ │ │ ├── adminGetApiAdminAgentsAgentIdKey.ts │ │ │ │ ├── adminGetApiAdminCompetitionCompetitionIdSnapshots.ts │ │ │ │ ├── adminGetApiAdminReportsPerformance.ts │ │ │ │ ├── adminGetApiAdminSearch.ts │ │ │ │ ├── adminGetApiAdminUsers.ts │ │ │ │ ├── adminPostApiAdminAgentsAgentIdDeactivate.ts │ │ │ │ ├── adminPostApiAdminAgentsAgentIdReactivate.ts │ │ │ │ ├── adminPostApiAdminCompetitionCreate.ts │ │ │ │ ├── adminPostApiAdminCompetitionEnd.ts │ │ │ │ ├── adminPostApiAdminCompetitionStart.ts │ │ │ │ ├── adminPostApiAdminSetup.ts │ │ │ │ ├── adminPostApiAdminUsers.ts │ │ │ │ ├── agentGetApiAgentAgentId.ts │ │ │ │ ├── agentGetApiAgentBalances.ts │ │ │ │ ├── agentGetApiAgentPortfolio.ts │ │ │ │ ├── agentGetApiAgentProfile.ts │ │ │ │ ├── agentGetApiAgentTrades.ts │ │ │ │ ├── agentGetApiAgents.ts │ │ │ │ ├── agentPostApiAgentResetApiKey.ts │ │ │ │ ├── agentPutApiAgentProfile.ts │ │ │ │ ├── authGetApiAuthNonce.ts │ │ │ │ ├── authPostApiAuthLogin.ts │ │ │ │ ├── authPostApiAuthLogout.ts │ │ │ │ ├── competitionDeleteApiCompetitionsCompetitionIdAgentsAgentId.ts │ │ │ │ ├── competitionGetApiCompetitions.ts │ │ │ │ ├── competitionGetApiCompetitionsCompetitionId.ts │ │ │ │ ├── competitionGetApiCompetitionsCompetitionIdAgents.ts │ │ │ │ ├── competitionGetApiCompetitionsLeaderboard.ts │ │ │ │ ├── competitionGetApiCompetitionsRules.ts │ │ │ │ ├── competitionGetApiCompetitionsStatus.ts │ │ │ │ ├── competitionGetApiCompetitionsUpcoming.ts │ │ │ │ ├── competitionPostApiCompetitionsCompetitionIdAgentsAgentId.ts │ │ │ │ ├── healthGetApiHealth.ts │ │ │ │ ├── healthGetApiHealthDetailed.ts │ │ │ │ ├── priceGetApiPrice.ts │ │ │ │ ├── priceGetApiPriceTokenInfo.ts │ │ │ │ ├── tradeGetApiTradeQuote.ts │ │ │ │ └── tradePostApiTradeExecute.ts │ │ ├── models │ │ │ ├── components │ │ │ │ ├── index.ts │ │ │ │ └── security.ts │ │ │ ├── errors │ │ │ │ ├── apierror.ts │ │ │ │ ├── error.ts │ │ │ │ ├── getapiauthnonce.ts │ │ │ │ ├── httpclienterrors.ts │ │ │ │ ├── index.ts │ │ │ │ ├── postapiauthlogin.ts │ │ │ │ ├── postapiauthlogout.ts │ │ │ │ └── sdkvalidationerror.ts │ │ │ └── operations │ │ │ │ ├── deleteapiadminagentsagentid.ts │ │ │ │ ├── deleteapicompetitionscompetitionidagentsagentid.ts │ │ │ │ ├── getapiadminagents.ts │ │ │ │ ├── getapiadminagentsagentid.ts │ │ │ │ ├── getapiadminagentsagentidkey.ts │ │ │ │ ├── getapiadmincompetitioncompetitionidsnapshots.ts │ │ │ │ ├── getapiadminreportsperformance.ts │ │ │ │ ├── getapiadminsearch.ts │ │ │ │ ├── getapiadminusers.ts │ │ │ │ ├── getapiagentagentid.ts │ │ │ │ ├── getapiagentbalances.ts │ │ │ │ ├── getapiagentportfolio.ts │ │ │ │ ├── getapiagentprofile.ts │ │ │ │ ├── getapiagents.ts │ │ │ │ ├── getapiagenttrades.ts │ │ │ │ ├── getapiauthnonce.ts │ │ │ │ ├── getapicompetitions.ts │ │ │ │ ├── getapicompetitionscompetitionid.ts │ │ │ │ ├── getapicompetitionscompetitionidagents.ts │ │ │ │ ├── getapicompetitionsleaderboard.ts │ │ │ │ ├── getapicompetitionsrules.ts │ │ │ │ ├── getapicompetitionsstatus.ts │ │ │ │ ├── getapicompetitionsupcoming.ts │ │ │ │ ├── getapihealth.ts │ │ │ │ ├── getapihealthdetailed.ts │ │ │ │ ├── getapiprice.ts │ │ │ │ ├── getapipricetokeninfo.ts │ │ │ │ ├── getapitradequote.ts │ │ │ │ ├── getapiuseragents.ts │ │ │ │ ├── getapiuseragentsagentid.ts │ │ │ │ ├── getapiuserprofile.ts │ │ │ │ ├── index.ts │ │ │ │ ├── postapiadminagentsagentiddeactivate.ts │ │ │ │ ├── postapiadminagentsagentidreactivate.ts │ │ │ │ ├── postapiadmincompetitioncreate.ts │ │ │ │ ├── postapiadmincompetitionend.ts │ │ │ │ ├── postapiadmincompetitionstart.ts │ │ │ │ ├── postapiadminsetup.ts │ │ │ │ ├── postapiadminusers.ts │ │ │ │ ├── postapiagentresetapikey.ts │ │ │ │ ├── postapiauthlogin.ts │ │ │ │ ├── postapiauthlogout.ts │ │ │ │ ├── postapicompetitionscompetitionidagentsagentid.ts │ │ │ │ ├── postapitradeexecute.ts │ │ │ │ ├── postapiuseragents.ts │ │ │ │ ├── putapiagentprofile.ts │ │ │ │ ├── putapiuseragentsagentidprofile.ts │ │ │ │ └── putapiuserprofile.ts │ │ ├── sdk │ │ │ ├── admin.ts │ │ │ ├── agent.ts │ │ │ ├── auth.ts │ │ │ ├── competition.ts │ │ │ ├── health.ts │ │ │ ├── index.ts │ │ │ ├── price.ts │ │ │ ├── sdk.ts │ │ │ ├── trade.ts │ │ │ └── user.ts │ │ └── types │ │ │ ├── async.ts │ │ │ ├── blobs.ts │ │ │ ├── constdatetime.ts │ │ │ ├── enums.ts │ │ │ ├── fp.ts │ │ │ ├── index.ts │ │ │ ├── operations.ts │ │ │ ├── rfcdate.ts │ │ │ └── streams.ts │ └── tsconfig.json ├── chains │ ├── CHANGELOG.md │ ├── README.md │ ├── eslint.config.js │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ ├── tsup.config.ts │ └── typedoc.json ├── contracts │ ├── CHANGELOG.md │ ├── eslint.config.js │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ ├── tsup.config.ts │ └── wagmi.config.ts ├── conversions │ ├── README.md │ ├── eslint.config.js │ ├── package.json │ ├── src │ │ ├── constants.ts │ │ └── index.ts │ ├── tsconfig.json │ ├── tsup.config.ts │ └── typedoc.json ├── eslint-config │ ├── README.md │ ├── base.js │ ├── next.js │ ├── package.json │ └── react-internal.js ├── fonts │ ├── README.md │ ├── eslint.config.js │ ├── package.json │ ├── scripts │ │ ├── init.sh │ │ ├── open-fonts.ts.template │ │ └── private-fonts.ts.template │ ├── tsconfig.json │ └── turbo.json ├── fvm │ ├── .mocharc.json │ ├── CHANGELOG.md │ ├── README.md │ ├── eslint.config.js │ ├── package.json │ ├── src │ │ ├── address │ │ │ ├── errors.ts │ │ │ └── index.ts │ │ ├── artifacts │ │ │ ├── actors.ts │ │ │ ├── address.ts │ │ │ └── index.ts │ │ └── utils │ │ │ ├── address.ts │ │ │ ├── base32.ts │ │ │ ├── cbor.ts │ │ │ ├── convert.ts │ │ │ ├── index.ts │ │ │ └── leb128 │ │ │ ├── common.ts │ │ │ ├── index.ts │ │ │ ├── signed.ts │ │ │ └── unsigned.ts │ ├── test │ │ ├── address.test.ts │ │ ├── setup.ts │ │ ├── utils.test.ts │ │ └── vectors │ │ │ ├── addresses.json │ │ │ └── addresses_eth.json │ ├── tsconfig.json │ └── tsup.config.ts ├── mcp │ ├── .env.example │ ├── CHANGELOG.md │ ├── README.md │ ├── eslint.config.js │ ├── package.json │ ├── src │ │ ├── config.ts │ │ └── index.ts │ ├── tsconfig.json │ └── tsup.config.ts ├── network-constants │ ├── CHANGELOG.md │ ├── README.md │ ├── eslint.config.js │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ ├── tsup.config.ts │ └── typedoc.json ├── react │ ├── eslint.config.js │ ├── package.json │ ├── src │ │ ├── actions │ │ │ └── credits.ts │ │ └── hooks │ │ │ ├── buckets.ts │ │ │ └── credits.ts │ ├── tsconfig.json │ └── tsup.config.ts ├── sdk │ ├── .mocharc.json │ ├── CHANGELOG.md │ ├── README.md │ ├── eslint.config.js │ ├── package.json │ ├── src │ │ ├── client.ts │ │ ├── entities │ │ │ ├── account.ts │ │ │ ├── blob.ts │ │ │ ├── bucket.ts │ │ │ └── credit.ts │ │ ├── errors.ts │ │ ├── ipc │ │ │ ├── gateway.ts │ │ │ ├── index.ts │ │ │ └── subnet.ts │ │ ├── provider.ts │ │ └── utils.ts │ ├── test │ │ ├── client.test.ts │ │ ├── contracts.test.ts │ │ ├── ipc.test.ts │ │ ├── setup.ts │ │ └── utils.test.ts │ ├── tsconfig.json │ └── tsup.config.ts ├── typescript-config │ ├── README.md │ ├── base.json │ ├── nextjs.json │ ├── package.json │ └── react-library.json ├── ui │ ├── components.json │ ├── eslint.config.js │ ├── package.json │ ├── postcss.config.mjs │ ├── src │ │ ├── components │ │ │ ├── .gitkeep │ │ │ ├── button.tsx │ │ │ ├── buy-credits-dialog.tsx │ │ │ ├── collapsed-string-display.tsx │ │ │ ├── infinite-scroll.tsx │ │ │ ├── logos │ │ │ │ └── recall-logo.tsx │ │ │ ├── shadcn │ │ │ │ ├── avatar.tsx │ │ │ │ ├── badge.tsx │ │ │ │ ├── breadcrumb.tsx │ │ │ │ ├── button.tsx │ │ │ │ ├── card.tsx │ │ │ │ ├── dialog.tsx │ │ │ │ ├── dropdown-menu.tsx │ │ │ │ ├── form.tsx │ │ │ │ ├── input.tsx │ │ │ │ ├── label.tsx │ │ │ │ ├── progress.tsx │ │ │ │ ├── scroll-area.tsx │ │ │ │ ├── select.tsx │ │ │ │ ├── separator.tsx │ │ │ │ ├── sonner.tsx │ │ │ │ ├── switch.tsx │ │ │ │ ├── tabs.tsx │ │ │ │ └── textarea.tsx │ │ │ ├── theme-provider.tsx │ │ │ ├── theme-toggle.tsx │ │ │ ├── toast.tsx │ │ │ └── wallet.tsx │ │ ├── hooks │ │ │ └── .gitkeep │ │ ├── lib │ │ │ └── utils.ts │ │ └── styles │ │ │ └── globals.css │ └── tsconfig.json └── ui2 │ ├── components.json │ ├── eslint.config.js │ ├── package.json │ ├── postcss.config.mjs │ ├── src │ ├── components │ │ ├── avatar.tsx │ │ ├── badge.tsx │ │ ├── breadcrumb.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── collapsible.tsx │ │ ├── dialog.tsx │ │ ├── icon-button.tsx │ │ ├── input.tsx │ │ ├── shadcn │ │ │ ├── .gitkeep │ │ │ ├── dropdown-menu.tsx │ │ │ ├── form.tsx │ │ │ ├── input.tsx │ │ │ └── label.tsx │ │ ├── skeleton.tsx │ │ ├── table.tsx │ │ ├── tabs.tsx │ │ └── theme-provider.tsx │ ├── hooks │ │ └── .gitkeep │ ├── lib │ │ └── utils.ts │ └── styles │ │ └── globals.css │ └── tsconfig.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── tsconfig.json ├── turbo.json └── typedoc.base.json /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.0.5/schema.json", 3 | "changelog": [ 4 | "@changesets/changelog-github", 5 | { 6 | "repo": "recallnet/js-recall" 7 | } 8 | ], 9 | "commit": false, 10 | "fixed": [], 11 | "linked": [], 12 | "access": "public", 13 | "baseBranch": "main", 14 | "updateInternalDependencies": "patch", 15 | "ignore": [ 16 | "comps", 17 | "faucet", 18 | "portal", 19 | "api", 20 | "@recallnet/api-mcp", 21 | "registration", 22 | "@recallnet/ui", 23 | "@recallnet/ui2", 24 | "@recallnet/react", 25 | "@recallnet/api-sdk" 26 | ] 27 | } -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Version control 2 | .git 3 | .gitignore 4 | .github 5 | 6 | # Node.js 7 | **/node_modules 8 | npm-debug.log 9 | .pnpm-store 10 | 11 | # Build artifacts 12 | **/dist 13 | *.log 14 | coverage 15 | .nyc_output 16 | 17 | # Environment files 18 | .env 19 | .env.* 20 | !.env.example 21 | 22 | # Docker files 23 | Dockerfile 24 | docker-compose.yml 25 | .dockerignore 26 | 27 | # Development files 28 | .vscode 29 | .idea 30 | *.md 31 | !README.md 32 | DEPLOYMENT.md 33 | LICENSE 34 | .editorconfig 35 | .prettier* 36 | .eslint* 37 | jest.config.js 38 | tsconfig.tsbuildinfo 39 | 40 | # Backup files 41 | backups 42 | *.dump 43 | *.backup 44 | *.sql 45 | 46 | # Test directories 47 | test 48 | tests 49 | e2e 50 | __tests__ 51 | 52 | # OS specific files 53 | .DS_Store 54 | Thumbs.db 55 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // This configuration only applies to the package manager root. 2 | /** @type {import("eslint").Linter.Config} */ 3 | module.exports = { 4 | ignorePatterns: ["apps/**", "packages/**"], 5 | extends: ["@recallnet/eslint-config/library.js"], 6 | parser: "@typescript-eslint/parser", 7 | parserOptions: { 8 | project: true, 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | **Bug Description** 10 | A clear and concise description of what the bug is. 11 | 12 | **Steps to Reproduce** 13 | E.g "Go to x, click on Y, see error" 14 | 15 | **Screenshots** 16 | If applicable, add screenshots to help explain your problem. 17 | 18 | **Additional context** 19 | Add any other context about the problem here. 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE]" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | **Problem Statement** 10 | What is the problem you are trying to solve? Ex. I'm always frustrated when [...] 11 | 12 | **Proposed Solution** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Impact** 16 | Who is impacted by this change? How will it affect them? 17 | 18 | **Priority** 19 | How urgent is this change? When does it need to be delivered by? How does the priority compare to that of other in-flight work? 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # Location of all agent context files. 4 | .agent 5 | 6 | # Ignore all fonts files since we pull them from a private repository at build time and generate source code. 7 | packages/fonts/src/* 8 | 9 | .direnv 10 | 11 | # Dependencies 12 | node_modules 13 | .pnp 14 | .pnp.js 15 | 16 | # Local env files 17 | .env 18 | .env.local 19 | .env.development.local 20 | .env.test.local 21 | .env.production.local 22 | .envrc 23 | 24 | # Testing 25 | coverage 26 | 27 | # Turbo 28 | .turbo 29 | 30 | # Vercel 31 | .vercel 32 | 33 | # Build Outputs 34 | .next/ 35 | out/ 36 | build 37 | dist 38 | 39 | # TypeDoc Documentation 40 | docs/ 41 | **/docs/ 42 | .typedoc-coverage/ 43 | **/.typedoc-coverage/ 44 | 45 | # Debug 46 | npm-debug.log* 47 | 48 | # API server logs Logs 49 | # Specific pattern for apps/api logs, including subdirectories 50 | apps/api/logs/ 51 | apps/api/**/*.log 52 | apps/api/*.log 53 | 54 | # Misc 55 | .DS_Store 56 | *.pem 57 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "packages/contracts/contracts"] 2 | path = packages/contracts/contracts 3 | url = git@github.com:recallnet/contracts.git 4 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=false -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | packages/contracts/contracts 2 | **/pnpm-lock.yaml 3 | packages/contracts/src/generated.ts 4 | packages/ui/src/components/shadcn 5 | packages/ui/src/hooks 6 | packages/ui/src/lib 7 | packages/ui/src/styles 8 | packages/ui2/src/components/shadcn 9 | packages/ui2/src/hooks 10 | packages/ui2/src/lib 11 | packages/ui2/src/styles -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "importOrder": [ 3 | "^.*.css", 4 | "", 5 | "^@recallnet/(.*)$", 6 | "^@/(.*)$", 7 | "^[./]" 8 | ], 9 | "importOrderSeparation": true, 10 | "importOrderSortSpecifiers": true, 11 | "plugins": [ 12 | "@trivago/prettier-plugin-sort-imports", 13 | "prettier-plugin-tailwindcss" 14 | ], 15 | "tailwindStylesheet": "./packages/ui/src/styles/globals.css", 16 | "tailwindFunctions": ["cn", "clsx", "cva"] 17 | } 18 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": "esbenp.prettier-vscode", 3 | "editor.formatOnSave": true, 4 | "eslint.enable": true, 5 | "editor.codeActionsOnSave": { 6 | "source.fixAll.eslint": "explicit", 7 | "source.fixAll": "explicit", 8 | "source.organizeImports": "never" 9 | }, 10 | "eslint.validate": [ 11 | "javascript", 12 | "javascriptreact", 13 | "typescript", 14 | "typescriptreact" 15 | ], 16 | "eslint.codeActionsOnSave.mode": "all", 17 | "eslint.lintTask.enable": true, 18 | "typescript.tsdk": "node_modules/typescript/lib", 19 | "tailwindCSS.experimental.configFile": { 20 | "packages/ui/src/styles/globals.css": [ 21 | "packages/ui/src/**", 22 | "apps/faucet/**", 23 | "apps/portal/**" 24 | ], 25 | "packages/ui2/src/styles/globals.css": [ 26 | "packages/ui2/src/**", 27 | "apps/comps/**" 28 | ] 29 | }, 30 | "tailwindCSS.classFunctions": ["cn", "cva", "cx"] 31 | } 32 | -------------------------------------------------------------------------------- /.zed/settings.json: -------------------------------------------------------------------------------- 1 | // Folder-specific settings 2 | // 3 | // For a full list of overridable settings, and general information on folder-specific settings, 4 | // see the documentation: https://zed.dev/docs/configuring-zed#settings-files 5 | { 6 | "languages": { 7 | "JavaScript": { 8 | "code_actions_on_format": { 9 | "source.fixAll.eslint": true 10 | } 11 | }, 12 | "TypeScript": { 13 | "code_actions_on_format": { 14 | "source.fixAll.eslint": true 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /apps/api/drizzle.config.ts: -------------------------------------------------------------------------------- 1 | import "dotenv/config"; 2 | import { defineConfig } from "drizzle-kit"; 3 | 4 | export default defineConfig({ 5 | out: "./drizzle", 6 | schema: "./src/database/schema/**/defs.ts", 7 | dialect: "postgresql", 8 | dbCredentials: { 9 | url: process.env.DATABASE_URL!, 10 | }, 11 | verbose: true, 12 | strict: true, 13 | }); 14 | -------------------------------------------------------------------------------- /apps/api/drizzle/0003_yielding_killraven.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE "trading_comps"."trades" ADD COLUMN "from_token_symbol" varchar(20) NOT NULL; -------------------------------------------------------------------------------- /apps/api/drizzle/meta/_journal.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "7", 3 | "dialect": "postgresql", 4 | "entries": [ 5 | { 6 | "idx": 0, 7 | "version": "7", 8 | "when": 1748116940027, 9 | "tag": "0000_mighty_psynapse", 10 | "breakpoints": true 11 | }, 12 | { 13 | "idx": 1, 14 | "version": "7", 15 | "when": 1748448591612, 16 | "tag": "0001_naive_ben_grimm", 17 | "breakpoints": true 18 | }, 19 | { 20 | "idx": 2, 21 | "version": "7", 22 | "when": 1748454089351, 23 | "tag": "0002_polite_obadiah_stane", 24 | "breakpoints": true 25 | }, 26 | { 27 | "idx": 3, 28 | "version": "7", 29 | "when": 1748875766494, 30 | "tag": "0003_yielding_killraven", 31 | "breakpoints": true 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /apps/api/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { config as baseConfig } from "@recallnet/eslint-config/base"; 2 | 3 | /** @type {import("eslint").Linter.Config} */ // Updated type definition 4 | const config = [ 5 | ...baseConfig, 6 | { 7 | ignores: [ 8 | "node_modules/", 9 | "dist/", 10 | "build/", 11 | "coverage/", 12 | "**/*.min.js", 13 | "**/vendor/**", 14 | "docs/examples/**", // Ignore examples directory 15 | ], 16 | }, 17 | ]; 18 | 19 | export default config; // ✅ Explicitly export the properly typed config 20 | -------------------------------------------------------------------------------- /apps/api/scripts/seed-db.ts: -------------------------------------------------------------------------------- 1 | import { pathToFileURL } from "url"; 2 | 3 | import { seedDb } from "@/database/db.js"; 4 | 5 | export async function seed() { 6 | await seedDb(); 7 | } 8 | 9 | // Run if called directly 10 | if ( 11 | process.argv[1] && 12 | import.meta.url === pathToFileURL(process.argv[1]).href 13 | ) { 14 | seed(); 15 | } 16 | -------------------------------------------------------------------------------- /apps/api/src/database/repositories/types.ts: -------------------------------------------------------------------------------- 1 | export type PartialExcept = Pick & Partial; 2 | -------------------------------------------------------------------------------- /apps/api/src/database/schema/core/types.ts: -------------------------------------------------------------------------------- 1 | import * as defs from "./defs.js"; 2 | 3 | export type SelectUser = typeof defs.users.$inferSelect; 4 | export type InsertUser = typeof defs.users.$inferInsert; 5 | 6 | export type SelectAgent = typeof defs.agents.$inferSelect; 7 | export type InsertAgent = typeof defs.agents.$inferInsert; 8 | 9 | export type SelectAdmin = typeof defs.admins.$inferSelect; 10 | export type InsertAdmin = typeof defs.admins.$inferInsert; 11 | 12 | export type SelectCompetition = typeof defs.competitions.$inferSelect; 13 | export type InsertCompetition = typeof defs.competitions.$inferInsert; 14 | 15 | export type SelectCompetitionAgent = typeof defs.competitionAgents.$inferSelect; 16 | export type InsertCompetitionAgent = typeof defs.competitionAgents.$inferInsert; 17 | -------------------------------------------------------------------------------- /apps/api/src/database/schema/index.ts: -------------------------------------------------------------------------------- 1 | import * as coreDefs from "./core/defs.js"; 2 | import * as coreRelations from "./core/relations.js"; 3 | import * as tradingDefs from "./trading/defs.js"; 4 | import * as tradingRelations from "./trading/relations.js"; 5 | import * as votingDefs from "./voting/defs.js"; 6 | import * as votingRelations from "./voting/relations.js"; 7 | 8 | const schema = { 9 | ...coreDefs, 10 | ...coreRelations, 11 | ...tradingDefs, 12 | ...tradingRelations, 13 | ...votingDefs, 14 | ...votingRelations, 15 | }; 16 | 17 | export default schema; 18 | -------------------------------------------------------------------------------- /apps/api/src/database/schema/trading/types.ts: -------------------------------------------------------------------------------- 1 | import * as defs from "./defs.js"; 2 | 3 | export type SelectTradingCompetition = 4 | typeof defs.tradingCompetitions.$inferSelect; 5 | export type InsertTradingCompetition = 6 | typeof defs.tradingCompetitions.$inferInsert; 7 | 8 | export type SelectBalance = typeof defs.balances.$inferSelect; 9 | export type InsertBalance = typeof defs.balances.$inferInsert; 10 | 11 | export type SelectTrade = typeof defs.trades.$inferSelect; 12 | export type InsertTrade = typeof defs.trades.$inferInsert; 13 | 14 | export type SelectPrice = typeof defs.prices.$inferSelect; 15 | export type InsertPrice = typeof defs.prices.$inferInsert; 16 | 17 | export type SelectPortfolioSnapshot = 18 | typeof defs.portfolioSnapshots.$inferSelect; 19 | export type InsertPortfolioSnapshot = 20 | typeof defs.portfolioSnapshots.$inferInsert; 21 | 22 | export type SelectPortfolioTokenValue = 23 | typeof defs.portfolioTokenValues.$inferSelect; 24 | export type InsertPortfolioTokenValue = 25 | typeof defs.portfolioTokenValues.$inferInsert; 26 | -------------------------------------------------------------------------------- /apps/api/src/database/schema/util.ts: -------------------------------------------------------------------------------- 1 | import { numeric, varchar } from "drizzle-orm/pg-core"; 2 | 3 | /** 4 | * PG column for amount of tokens in humanese 5 | */ 6 | export function tokenAmount(name: string) { 7 | return numeric(name, { precision: 30, scale: 18, mode: "number" }); 8 | } 9 | 10 | /** 11 | * PG column for a blockchain address 12 | */ 13 | export function blockchainAddress(name: string) { 14 | return varchar(name, { length: 50 }); 15 | } 16 | -------------------------------------------------------------------------------- /apps/api/src/express.d.ts: -------------------------------------------------------------------------------- 1 | import { IronSession } from "iron-session"; 2 | 3 | import type { SessionData } from "./session-types"; 4 | 5 | declare global { 6 | namespace Express { 7 | interface Request { 8 | session?: IronSession; 9 | agentId?: string; 10 | userId?: string; 11 | adminId?: string; 12 | wallet?: string; 13 | isAdmin?: boolean; 14 | admin?: { 15 | id: string; 16 | name: string; 17 | }; 18 | competitionId?: string; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /apps/api/src/middleware/auth-helpers.ts: -------------------------------------------------------------------------------- 1 | import { Request } from "express"; 2 | 3 | /** 4 | * Extract API key from request's Authorization header 5 | * @param req Express request 6 | * @returns The API key or undefined if not found 7 | */ 8 | export function extractApiKey(req: Request): string | undefined { 9 | const authHeader = req.header("Authorization"); 10 | 11 | if (!authHeader || !authHeader.startsWith("Bearer ")) { 12 | return undefined; 13 | } 14 | 15 | const apiKey = authHeader.substring(7); 16 | 17 | // Log partial key for debugging (only first 8 chars) 18 | const partialKey = apiKey ? `${apiKey.substring(0, 8)}...` : "undefined"; 19 | console.log(`[AuthHelper] Using API Key: ${partialKey}`); 20 | 21 | return apiKey; 22 | } 23 | -------------------------------------------------------------------------------- /apps/api/src/routes/docs.routes.ts: -------------------------------------------------------------------------------- 1 | import { RequestHandler, Router } from "express"; 2 | 3 | import { DocsController } from "@/controllers/docs.controller.js"; 4 | 5 | export function configureDocsRoutes( 6 | controller: DocsController, 7 | ...middlewares: RequestHandler[] 8 | ) { 9 | const router = Router(); 10 | 11 | if (middlewares.length) { 12 | router.use(...middlewares); 13 | } 14 | 15 | // GET /api/docs - Serve Swagger UI 16 | router.use("/", controller.serveAssets); 17 | router.get("/", controller.getApiDocs); 18 | 19 | // GET /api/docs/spec - Get raw OpenAPI specification 20 | router.get("/spec", controller.getApiSpec); 21 | 22 | return router; 23 | } 24 | -------------------------------------------------------------------------------- /apps/api/trade-simulator-docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:22 AS builder 2 | 3 | WORKDIR /workdir 4 | 5 | COPY apps/api apps/api 6 | COPY packages/api-sdk packages/api-sdk 7 | COPY packages/eslint-config packages/eslint-config 8 | COPY packages/typescript-config packages/typescript-config 9 | COPY .npmrc .prettie* *.js *.json *.yaml ./ 10 | 11 | # # Build the application 12 | RUN npm -g install pnpm typescript turbo 13 | RUN cd apps/api; pnpm install 14 | RUN cd packages/api-sdk; pnpm build 15 | RUN cd apps/api; pnpm build 16 | 17 | FROM node:22-alpine 18 | 19 | # Install postgresql-client for database checks and pnpm for migrations 20 | RUN apk add --no-cache postgresql-client 21 | RUN npm install -g pnpm 22 | 23 | COPY --from=builder /workdir /workdir 24 | 25 | # Set environment variables 26 | ENV NODE_ENV=production 27 | ENV PORT=3000 28 | 29 | # Expose the application port (will be overridden by docker-compose) 30 | EXPOSE $PORT 31 | 32 | # Create startup script 33 | COPY apps/api/trade-simulator-docker/startup.sh /workdir/apps/api/startup.sh 34 | RUN chmod +x /workdir/apps/api/startup.sh 35 | 36 | # Start the application 37 | WORKDIR /workdir/apps/api 38 | CMD ["./startup.sh"] 39 | -------------------------------------------------------------------------------- /apps/api/trade-simulator-docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | # Application service 3 | app: 4 | build: 5 | context: ../../.. 6 | dockerfile: apps/api/trade-simulator-docker/Dockerfile 7 | container_name: trading-simulator-app 8 | restart: unless-stopped 9 | ports: 10 | - "${PORT:-3000}:${PORT:-3000}" 11 | # Load all environment variables from .env file 12 | env_file: 13 | - .env 14 | environment: 15 | - PORT=${PORT:-3000} 16 | # Override only the critical variables that need specific values for Docker 17 | volumes: 18 | - ../logs:/app/logs 19 | - .env:/app/.env # Mount the .env file for direct access and modification 20 | healthcheck: 21 | test: 22 | [ 23 | "CMD-SHELL", 24 | "wget --no-verbose --tries=1 --spider http://127.0.0.1:${PORT:-3000}/api/health || exit 1", 25 | ] 26 | interval: 10s 27 | timeout: 5s 28 | retries: 5 29 | start_period: 10s 30 | -------------------------------------------------------------------------------- /apps/api/trade-simulator-docker/startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | # Function to check if database is initialized 5 | check_db_initialized() { 6 | # Check if the main schema exists 7 | psql "$DATABASE_URL" -t -c "SELECT 1 FROM information_schema.schemata WHERE schema_name = 'trading_comps';" 2>/dev/null | grep -q 1 8 | } 9 | 10 | # Wait for database to be ready 11 | echo "Waiting for database to be ready..." 12 | until pg_isready -d "$DATABASE_URL" 2>/dev/null; do 13 | echo "Database not ready, waiting..." 14 | sleep 2 15 | done 16 | 17 | # Check if we need to run migrations 18 | if ! check_db_initialized; then 19 | echo "Database not initialized, running migrations..." 20 | cd /workdir/apps/api && pnpm db:migrate 21 | echo "Migrations completed" 22 | else 23 | echo "Database already initialized, skipping migrations" 24 | fi 25 | 26 | # Start the application 27 | exec node dist/src/index.js -------------------------------------------------------------------------------- /apps/api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@recallnet/typescript-config/base.json", 3 | "compilerOptions": { 4 | "declaration": false, 5 | "declarationMap": false, 6 | "outDir": "./dist", 7 | "rootDir": ".", 8 | "baseUrl": ".", 9 | "paths": { 10 | "@/*": ["./src/*"], 11 | "@/scripts/*": ["./scripts/*"], 12 | "@/e2e/*": ["./e2e/*"] 13 | }, 14 | "forceConsistentCasingInFileNames": true, 15 | "experimentalDecorators": true, 16 | "emitDecoratorMetadata": true, 17 | "sourceMap": true 18 | }, 19 | "include": ["src/**/*.ts", "scripts/**/*.ts", "e2e/**/*.ts", "sum/**/*.ts"], 20 | "exclude": ["node_modules", "dist"] 21 | } 22 | -------------------------------------------------------------------------------- /apps/api/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import tsconfigPaths from "vite-tsconfig-paths"; 2 | import { defineConfig } from "vitest/config"; 3 | 4 | export default defineConfig({ 5 | plugins: [tsconfigPaths()], 6 | test: { 7 | reporters: ["default", "e2e/utils/log-reporter.ts"], 8 | workspace: [ 9 | { 10 | extends: true, 11 | test: { 12 | name: "unit", 13 | root: "./", 14 | dir: "./src", 15 | }, 16 | }, 17 | { 18 | extends: true, 19 | test: { 20 | name: "e2e", 21 | root: "./", 22 | dir: "./e2e", 23 | globalSetup: "./e2e/setup.ts", 24 | setupFiles: "./e2e/utils/test-setup.ts", 25 | testTimeout: 120_000, 26 | sequence: { 27 | concurrent: false, 28 | shuffle: false, 29 | }, 30 | maxConcurrency: 1, 31 | pool: "threads", 32 | poolOptions: { 33 | threads: { 34 | singleThread: true, 35 | }, 36 | }, 37 | }, 38 | }, 39 | ], 40 | }, 41 | }); 42 | -------------------------------------------------------------------------------- /apps/comps/.env.example: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID= 2 | NEXT_PUBLIC_API_BASE_URL= -------------------------------------------------------------------------------- /apps/comps/app/agents/[id]/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React from "react"; 4 | 5 | import AgentProfile from "@/components/agent-profile"; 6 | import { FooterSection } from "@/components/footer-section"; 7 | import { JoinSwarmSection } from "@/components/join-swarm-section"; 8 | import { RegisterAgentBlock } from "@/components/register-agent-block"; 9 | import { getSocialLinksArray } from "@/data/social"; 10 | 11 | export default function LeaderboardPage({ 12 | params, 13 | }: { 14 | params: Promise<{ id: string }>; 15 | }) { 16 | const { id } = React.use(params); 17 | 18 | return ( 19 | <> 20 | 21 | 22 | 23 | 24 | 28 | 29 | 30 | 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /apps/comps/app/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/app/android-chrome-192x192.png -------------------------------------------------------------------------------- /apps/comps/app/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/app/android-chrome-512x512.png -------------------------------------------------------------------------------- /apps/comps/app/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/app/apple-touch-icon.png -------------------------------------------------------------------------------- /apps/comps/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/app/favicon.ico -------------------------------------------------------------------------------- /apps/comps/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import "@rainbow-me/rainbowkit/styles.css"; 2 | import "@recallnet/ui2/globals.css"; 3 | 4 | import { Analytics } from "@vercel/analytics/react"; 5 | import { Metadata } from "next"; 6 | 7 | import { fontMono, fontSans } from "@recallnet/fonts"; 8 | 9 | import { Navbar } from "@/components/navbar"; 10 | import { Providers } from "@/components/providers"; 11 | 12 | export const metadata: Metadata = { 13 | title: "Recall Competitions", 14 | description: "Explore, join, and compete in Recall AI agent competitions.", 15 | }; 16 | 17 | export default function RootLayout({ 18 | children, 19 | }: Readonly<{ 20 | children: React.ReactNode; 21 | }>) { 22 | return ( 23 | 24 | 25 | 26 | 27 | 28 |
{children}
29 |
30 |
31 | 32 | 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /apps/comps/app/leaderboards/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React from "react"; 4 | 5 | import { FooterSection } from "@/components/footer-section"; 6 | import { LeaderboardSection } from "@/components/leaderboard/index"; 7 | import { RegisterAgentBlock } from "@/components/register-agent-block"; 8 | 9 | import { JoinSwarmSection } from "../../components/join-swarm-section"; 10 | import { getSocialLinksArray } from "../../data/social"; 11 | 12 | export default function LeaderboardPage() { 13 | return ( 14 | <> 15 | 16 | 17 | 18 | 19 | 23 | 24 | 25 | 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /apps/comps/app/onboarding/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React, { useState } from "react"; 4 | 5 | import { AddFundsStep } from "@/components/onboarding/add-funds"; 6 | import { AgentLive } from "@/components/onboarding/agent-live"; 7 | import { RegisterAgentStep } from "@/components/onboarding/register-agent"; 8 | import OnboardingScreen from "@/components/onboarding/screen"; 9 | 10 | export default function OnboardingPage() { 11 | const [step, setStep] = useState(0); 12 | 13 | const onSubmitAgent = (args: { name: string; address: string }) => { 14 | console.log("AGENT CREATED", args); 15 | setStep((step) => step + 1); 16 | }; 17 | 18 | const steps = [ 19 | , 20 | , 21 | , 22 | ]; 23 | 24 | return ( 25 | setStep((step) => step + 1)} 29 | /> 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /apps/comps/app/page.tsx: -------------------------------------------------------------------------------- 1 | import AgentSection from "@/components/main-page/agent-section"; 2 | import CompeteSection from "@/components/main-page/compete-section"; 3 | import DiscoverSection from "@/components/main-page/discover-section"; 4 | import HeroSection from "@/components/main-page/hero-section"; 5 | import { SubscribeSection } from "@/components/main-page/subscribe-section"; 6 | 7 | export default function Page() { 8 | return ( 9 |
10 | 11 | 12 | 13 | 14 | 15 |
16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /apps/comps/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "", 8 | "css": "../../packages/ui2/src/styles/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true 11 | }, 12 | "iconLibrary": "lucide", 13 | "aliases": { 14 | "components": "@/components", 15 | "hooks": "@/hooks", 16 | "lib": "@/lib", 17 | "utils": "@recallnet/ui2/lib/utils", 18 | "ui": "@recallnet/ui2/components/shadcn" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /apps/comps/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/components/.gitkeep -------------------------------------------------------------------------------- /apps/comps/components/agent-card.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { ChevronRightIcon } from "@radix-ui/react-icons"; 4 | import Link from "next/link"; 5 | import React from "react"; 6 | 7 | import { AgentResponse } from "@/types"; 8 | 9 | interface AgentCardProps { 10 | agent: AgentResponse; 11 | } 12 | 13 | export const AgentCard: React.FC = ({ agent }) => { 14 | return ( 15 |
16 |

{agent.name}

17 | 18 | 24 | 25 |
26 | ); 27 | }; 28 | -------------------------------------------------------------------------------- /apps/comps/components/agents-table/rank-badge.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { AwardIcon } from "../agent-podium/award-icon"; 4 | 5 | interface RankBadgeProps { 6 | position: number; 7 | } 8 | 9 | export const RankBadge: React.FC = ({ position }) => { 10 | const getBackgroundColor = () => { 11 | switch (position) { 12 | case 0: 13 | return "bg-yellow-800"; 14 | case 1: 15 | return "bg-gray-700"; 16 | case 2: 17 | return "bg-[#1A0E05]"; 18 | default: 19 | return "bg-gray-700"; 20 | } 21 | }; 22 | 23 | return ( 24 | 27 | {position <= 2 ? ( 28 | 36 | ) : ( 37 | position 38 | )} 39 | 40 | ); 41 | }; 42 | -------------------------------------------------------------------------------- /apps/comps/components/back-button.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { ArrowLeftIcon } from "@radix-ui/react-icons"; 4 | import { useRouter } from "next/navigation"; 5 | import React from "react"; 6 | 7 | import { IconButton } from "@recallnet/ui2/components/icon-button"; 8 | 9 | interface BackButtonProps { 10 | className?: string; 11 | } 12 | 13 | export const BackButton: React.FC = ({ className }) => { 14 | const router = useRouter(); 15 | 16 | return ( 17 | router.back()} 22 | /> 23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /apps/comps/components/competition-status-badge.tsx: -------------------------------------------------------------------------------- 1 | import { Badge } from "@recallnet/ui2/components/badge"; 2 | 3 | import { CompetitionStatus } from "@/types"; 4 | 5 | export function CompetitionStatusBadge({ 6 | status, 7 | }: { 8 | status: CompetitionStatus; 9 | }) { 10 | const statusConfig = 11 | status === CompetitionStatus.Active 12 | ? { 13 | text: "On-going", 14 | variant: "green" as const, 15 | } 16 | : status === CompetitionStatus.Pending 17 | ? { 18 | text: "Upcoming", 19 | variant: "blue" as const, 20 | } 21 | : { 22 | text: "Complete", 23 | variant: "gray" as const, 24 | }; 25 | 26 | return {statusConfig.text}; 27 | } 28 | -------------------------------------------------------------------------------- /apps/comps/components/hexagon/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { cn } from "@recallnet/ui2/lib/utils"; 4 | 5 | type HexagonProps = React.HTMLAttributes; 6 | 7 | export const Hexagon: React.FC = ({ 8 | className, 9 | children, 10 | ...props 11 | }) => { 12 | return ( 13 |
27 |
{children}
28 |
29 | ); 30 | }; 31 | -------------------------------------------------------------------------------- /apps/comps/components/identicon/index.tsx: -------------------------------------------------------------------------------- 1 | import { toSvg } from "jdenticon"; 2 | 3 | import { cn } from "@recallnet/ui2/lib/utils"; 4 | 5 | export function Identicon({ 6 | address, 7 | className, 8 | }: { 9 | address: string; 10 | className?: string; 11 | }) { 12 | const svg = toSvg(address, 40, { 13 | padding: 0.9, 14 | hues: [227], 15 | lightness: { 16 | color: [0.74, 1.0], 17 | grayscale: [0.63, 0.82], 18 | }, 19 | saturation: { 20 | color: 0.51, 21 | grayscale: 0.67, 22 | }, 23 | backColor: "#0000", 24 | }); 25 | return ( 26 |
30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /apps/comps/components/join-swarm-section.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React from "react"; 4 | 5 | import { cn } from "@recallnet/ui2/lib/utils"; 6 | 7 | import { SocialLinkCard } from "@/components/social-link-card"; 8 | import { SocialLink } from "@/data/social"; 9 | 10 | interface JoinSwarmSectionProps { 11 | className?: string; 12 | socialLinks: SocialLink[]; 13 | } 14 | 15 | export const JoinSwarmSection: React.FC = ({ 16 | className, 17 | socialLinks, 18 | }) => { 19 | return ( 20 |
21 |

Join the swarm

22 | 23 |
24 |
25 | {socialLinks.map((link) => ( 26 | 31 | ))} 32 |
33 |
34 | ); 35 | }; 36 | -------------------------------------------------------------------------------- /apps/comps/components/starting-soon-section.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React from "react"; 4 | 5 | import { CompetitionCard } from "@/components/competition-card"; 6 | import { Competition } from "@/types"; 7 | 8 | interface StartingSoonSectionProps { 9 | competitions: Competition[]; 10 | } 11 | 12 | export const StartingSoonSection: React.FC = ({ 13 | competitions, 14 | }) => { 15 | return ( 16 |
17 |

Starting Soon

18 |
19 | {competitions.map((competition) => ( 20 | 21 | ))} 22 |
23 |
24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /apps/comps/components/string-list.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | /** 4 | * Props for the StringList component. 5 | * @property strings - The array of strings to display. 6 | * @property separator - The separator string to use between items (default: " / "). 7 | */ 8 | export interface StringListProps { 9 | strings: string[]; 10 | separator?: string; 11 | } 12 | 13 | /** 14 | * Renders a list of strings separated by a custom separator. 15 | * 16 | * @param props - The props for the component. 17 | * @returns The rendered string list. 18 | * @example 19 | * 20 | */ 21 | export const StringList: React.FC = ({ 22 | strings, 23 | separator = "/", 24 | }) => ( 25 |
26 | {strings.map((str, idx) => ( 27 | 28 | {str} 29 | {idx < strings.length - 1 && ( 30 | 31 | )} 32 | 33 | ))} 34 |
35 | ); 36 | -------------------------------------------------------------------------------- /apps/comps/data/social.ts: -------------------------------------------------------------------------------- 1 | export interface SocialLink { 2 | id: string; 3 | name: string; 4 | url: string; 5 | icon: string; 6 | bg?: string; 7 | } 8 | 9 | type SocialLinkId = "x" | "discord" | "youtube" | "docs"; 10 | 11 | export const socialLinks: Record = { 12 | x: { 13 | id: "x", 14 | name: "X.COM", 15 | url: "https://x.com/recallnet", 16 | icon: "/x-icon.svg", 17 | bg: "gray-800", 18 | }, 19 | discord: { 20 | id: "discord", 21 | name: "DISCORD", 22 | url: "https://discord.recall.network", 23 | icon: "/discord-icon.svg", 24 | bg: "blue-500", 25 | }, 26 | youtube: { 27 | id: "youtube", 28 | name: "YOUTUBE", 29 | url: "https://www.youtube.com/@recallnet", 30 | icon: "/youtube-icon.svg", 31 | bg: "red-500", 32 | }, 33 | docs: { 34 | id: "docs", 35 | name: "DOCS", 36 | url: "https://docs.recall.network", 37 | icon: "/docs-icon.svg", 38 | bg: "green-500", 39 | }, 40 | }; 41 | 42 | // Helper function to get social links as an array when needed 43 | export const getSocialLinksArray = (): SocialLink[] => 44 | Object.values(socialLinks); 45 | -------------------------------------------------------------------------------- /apps/comps/eslint.config.js: -------------------------------------------------------------------------------- 1 | import { nextJsConfig } from "@recallnet/eslint-config/next-js"; 2 | 3 | /** @type {import("eslint").Linter.Config} */ 4 | export default nextJsConfig; 5 | -------------------------------------------------------------------------------- /apps/comps/hooks/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/hooks/.gitkeep -------------------------------------------------------------------------------- /apps/comps/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./useAgents"; 2 | export * from "./useAgent"; 3 | export * from "./useCompetitions"; 4 | export * from "./useCompetition"; 5 | export * from "./useCompetitionAgents"; 6 | export * from "./useAgentCompetitions"; 7 | export * from "./useLeaderboards"; 8 | export * from "./useJoinCompetition"; 9 | export * from "./useLeaveCompetition"; 10 | export * from "./useCreateAgent"; 11 | export * from "./useAuth"; 12 | export * from "./useProfile"; 13 | -------------------------------------------------------------------------------- /apps/comps/hooks/useAgent.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from "@tanstack/react-query"; 2 | 3 | import { ApiClient } from "@/lib/api-client"; 4 | import { AgentResponse } from "@/types"; 5 | 6 | const apiClient = new ApiClient(); 7 | 8 | /** 9 | * Hook to fetch a single agent by ID 10 | * @param id Agent ID 11 | * @returns Query result with agent data 12 | */ 13 | export const useAgent = (id?: string) => 14 | useQuery({ 15 | queryKey: ["agent", id], 16 | queryFn: async (): Promise => { 17 | if (!id) throw new Error("Agent ID is required"); 18 | const response = await apiClient.getAgent(id); 19 | 20 | if (!response.success) throw new Error("Error when querying agent"); 21 | 22 | return response.agent; 23 | }, 24 | enabled: !!id, 25 | }); 26 | -------------------------------------------------------------------------------- /apps/comps/hooks/useAgentCompetitions.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from "@tanstack/react-query"; 2 | 3 | import { ApiClient } from "@/lib/api-client"; 4 | import { AgentCompetitionsResponse, GetAgentCompetitionsParams } from "@/types"; 5 | 6 | const apiClient = new ApiClient(); 7 | 8 | /** 9 | * Hook to fetch competitions for a specific agent 10 | * @param agentId Agent ID 11 | * @param params Query parameters for agent competitions endpoint 12 | * @returns Query result with competitions data 13 | */ 14 | export const useAgentCompetitions = ( 15 | agentId?: string, 16 | params: GetAgentCompetitionsParams = {}, 17 | ) => 18 | useQuery({ 19 | queryKey: ["agent-competitions", agentId, params], 20 | queryFn: async (): Promise => { 21 | if (!agentId) throw new Error("Agent ID is required"); 22 | return apiClient.getAgentCompetitions(agentId, params); 23 | }, 24 | enabled: !!agentId, 25 | placeholderData: (prev) => prev, 26 | }); 27 | -------------------------------------------------------------------------------- /apps/comps/hooks/useAgents.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from "@tanstack/react-query"; 2 | 3 | import { ApiClient } from "@/lib/api-client"; 4 | import { AgentsResponse, GetAgentsParams } from "@/types"; 5 | 6 | const apiClient = new ApiClient(); 7 | 8 | /** 9 | * Hook to fetch agents with pagination and filtering 10 | * @param params Query parameters for agents endpoint 11 | * @returns Query result with agents data 12 | */ 13 | export const useAgents = (params: GetAgentsParams = {}) => 14 | useQuery({ 15 | queryKey: ["agents", params], 16 | queryFn: async (): Promise => { 17 | return apiClient.getAgents(params); 18 | }, 19 | placeholderData: (prev) => prev, 20 | }); 21 | 22 | /** 23 | * Hook to fetch agents with pagination and filtering 24 | * @param params Query parameters for agents endpoint 25 | * @returns Query result with agents data 26 | */ 27 | export const useUserAgents = (params: GetAgentsParams = {}) => 28 | useQuery({ 29 | queryKey: ["agents", params], 30 | queryFn: async (): Promise => { 31 | return apiClient.getUserAgents(params); 32 | }, 33 | placeholderData: (prev) => prev, 34 | }); 35 | -------------------------------------------------------------------------------- /apps/comps/hooks/useCompetition.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from "@tanstack/react-query"; 2 | 3 | import { ApiClient } from "@/lib/api-client"; 4 | import { CompetitionResponse } from "@/types"; 5 | 6 | const apiClient = new ApiClient(); 7 | 8 | /** 9 | * Hook to fetch a single competition by ID 10 | * @param id Competition ID 11 | * @returns Query result with competition data 12 | */ 13 | export const useCompetition = (id?: string) => 14 | useQuery({ 15 | queryKey: ["competition", id], 16 | queryFn: async (): Promise => { 17 | if (!id) throw new Error("Competition ID is required"); 18 | return (await apiClient.getCompetition(id)).competition; 19 | }, 20 | enabled: !!id, 21 | }); 22 | -------------------------------------------------------------------------------- /apps/comps/hooks/useCompetitionAgents.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from "@tanstack/react-query"; 2 | 3 | import { ApiClient } from "@/lib/api-client"; 4 | import { AgentCompetitionResponse, GetCompetitionAgentsParams } from "@/types"; 5 | 6 | const apiClient = new ApiClient(); 7 | 8 | /** 9 | * Hook to fetch agents participating in a competition 10 | * @param competitionId Competition ID 11 | * @param params Query parameters for competition agents endpoint 12 | * @returns Query result with agents data 13 | */ 14 | export const useCompetitionAgents = ( 15 | competitionId?: string, 16 | params: GetCompetitionAgentsParams = {}, 17 | ) => 18 | useQuery({ 19 | queryKey: ["competition-agents", competitionId, params], 20 | queryFn: async (): Promise => { 21 | if (!competitionId) throw new Error("Competition ID is required"); 22 | return apiClient.getCompetitionAgents(competitionId, params); 23 | }, 24 | enabled: !!competitionId, 25 | placeholderData: (prev) => prev, 26 | }); 27 | -------------------------------------------------------------------------------- /apps/comps/hooks/useCompetitions.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from "@tanstack/react-query"; 2 | 3 | import { ApiClient } from "@/lib/api-client"; 4 | import { CompetitionsResponse, GetCompetitionsParams } from "@/types"; 5 | 6 | const apiClient = new ApiClient(); 7 | 8 | /** 9 | * Hook to fetch competitions with pagination and filtering 10 | * @param params Query parameters for competitions endpoint 11 | * @returns Query result with competitions data 12 | */ 13 | export const useCompetitions = (params: GetCompetitionsParams = {}) => 14 | useQuery({ 15 | queryKey: ["competitions", params], 16 | queryFn: async (): Promise => { 17 | return apiClient.getCompetitions(params); 18 | }, 19 | placeholderData: (prev) => prev, 20 | }); 21 | -------------------------------------------------------------------------------- /apps/comps/hooks/useCreateAgent.ts: -------------------------------------------------------------------------------- 1 | import { useMutation, useQueryClient } from "@tanstack/react-query"; 2 | 3 | import { ApiClient } from "@/lib/api-client"; 4 | import { CreateAgentRequest } from "@/types"; 5 | 6 | const apiClient = new ApiClient(); 7 | 8 | /** 9 | * Hook to create a new agent 10 | * @returns Mutation for creating an agent 11 | */ 12 | export const useCreateAgent = () => { 13 | const queryClient = useQueryClient(); 14 | 15 | return useMutation({ 16 | mutationFn: async (data: CreateAgentRequest) => { 17 | return apiClient.createAgent(data); 18 | }, 19 | onSuccess: () => { 20 | // Invalidate relevant queries 21 | queryClient.invalidateQueries({ queryKey: ["profile"] }); 22 | queryClient.invalidateQueries({ queryKey: ["agents"] }); 23 | queryClient.invalidateQueries({ queryKey: ["leaderboard"] }); 24 | }, 25 | }); 26 | }; 27 | -------------------------------------------------------------------------------- /apps/comps/hooks/useInView.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef, useState } from "react"; 2 | 3 | export const useInView = (options?: IntersectionObserverInit) => { 4 | const ref = useRef(undefined); 5 | const [inView, setInView] = useState(false); 6 | 7 | useEffect(() => { 8 | if (!ref.current) return; 9 | 10 | const observer = new IntersectionObserver(([entry]) => { 11 | if (entry?.isIntersecting) { 12 | setInView(true); 13 | observer.disconnect(); // trigger only once 14 | } 15 | }, options); 16 | 17 | observer.observe(ref.current); 18 | 19 | return () => observer.disconnect(); 20 | }, [ref, options]); 21 | 22 | return { ref: ref as React.Ref, inView }; 23 | }; 24 | -------------------------------------------------------------------------------- /apps/comps/hooks/useLeaderboards.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from "@tanstack/react-query"; 2 | 3 | import { ApiClient } from "@/lib/api-client"; 4 | import { GetLeaderboardParams, LeaderboardResponse } from "@/types"; 5 | 6 | const apiClient = new ApiClient(); 7 | 8 | /** 9 | * Hook to fetch leaderboards data 10 | * @param params Query parameters for leaderboard endpoint 11 | * @returns Query result with leaderboard data 12 | */ 13 | export const useLeaderboards = (params: GetLeaderboardParams = {}) => 14 | useQuery({ 15 | queryKey: ["leaderboards", params], 16 | queryFn: async (): Promise => { 17 | return apiClient.getLeaderboards(params); 18 | }, 19 | placeholderData: (prev) => prev, 20 | }); 21 | -------------------------------------------------------------------------------- /apps/comps/lib/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/lib/.gitkeep -------------------------------------------------------------------------------- /apps/comps/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. 6 | -------------------------------------------------------------------------------- /apps/comps/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | images: { 4 | remotePatterns: [ 5 | { 6 | protocol: "https", 7 | hostname: "*", 8 | }, 9 | ], 10 | }, 11 | transpilePackages: ["@recallnet/ui2", "@recallnet/fonts"], 12 | }; 13 | 14 | export default nextConfig; 15 | -------------------------------------------------------------------------------- /apps/comps/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | export { default } from "@recallnet/ui2/postcss.config"; 2 | -------------------------------------------------------------------------------- /apps/comps/public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/.gitkeep -------------------------------------------------------------------------------- /apps/comps/public/agent-placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/agent-placeholder.png -------------------------------------------------------------------------------- /apps/comps/public/backers/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/backers/1.png -------------------------------------------------------------------------------- /apps/comps/public/backers/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/backers/2.png -------------------------------------------------------------------------------- /apps/comps/public/backers/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/backers/3.png -------------------------------------------------------------------------------- /apps/comps/public/backers/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/backers/4.png -------------------------------------------------------------------------------- /apps/comps/public/backers/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/backers/5.png -------------------------------------------------------------------------------- /apps/comps/public/cards/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/cards/1.png -------------------------------------------------------------------------------- /apps/comps/public/cards/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/cards/2.png -------------------------------------------------------------------------------- /apps/comps/public/cards/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/cards/3.png -------------------------------------------------------------------------------- /apps/comps/public/cards/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/cards/4.png -------------------------------------------------------------------------------- /apps/comps/public/competition-placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/competition-placeholder.png -------------------------------------------------------------------------------- /apps/comps/public/default_agent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/default_agent.png -------------------------------------------------------------------------------- /apps/comps/public/default_agent_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/default_agent_2.png -------------------------------------------------------------------------------- /apps/comps/public/default_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/default_user.png -------------------------------------------------------------------------------- /apps/comps/public/discover_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/discover_1.png -------------------------------------------------------------------------------- /apps/comps/public/discover_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/discover_2.png -------------------------------------------------------------------------------- /apps/comps/public/discover_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/discover_3.png -------------------------------------------------------------------------------- /apps/comps/public/discover_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/discover_4.png -------------------------------------------------------------------------------- /apps/comps/public/discover_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/discover_5.png -------------------------------------------------------------------------------- /apps/comps/public/discover_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/discover_6.png -------------------------------------------------------------------------------- /apps/comps/public/docs-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/comps/public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/favicon-16x16.png -------------------------------------------------------------------------------- /apps/comps/public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/favicon-32x32.png -------------------------------------------------------------------------------- /apps/comps/public/frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/frame.png -------------------------------------------------------------------------------- /apps/comps/public/frame_2_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/frame_2_left.png -------------------------------------------------------------------------------- /apps/comps/public/frame_2_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/frame_2_right.png -------------------------------------------------------------------------------- /apps/comps/public/frame_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/frame_3.png -------------------------------------------------------------------------------- /apps/comps/public/frame_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/frame_4.png -------------------------------------------------------------------------------- /apps/comps/public/hero.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/hero.mp4 -------------------------------------------------------------------------------- /apps/comps/public/logo_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/comps/public/logo_white.png -------------------------------------------------------------------------------- /apps/comps/public/x-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/comps/public/youtube-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/comps/state/atoms.ts: -------------------------------------------------------------------------------- 1 | import { atom } from "jotai"; 2 | import { atomWithStorage } from "jotai/utils"; 3 | import { zeroAddress } from "viem"; 4 | 5 | import { LeaderboardAgent } from "@/types/agent"; 6 | 7 | type User = { 8 | address: string; 9 | loggedIn: boolean; 10 | }; 11 | 12 | export const userAtom = atomWithStorage("user", { 13 | address: "", 14 | loggedIn: false, 15 | }); 16 | 17 | export const userAgentAtom = atom({ 18 | id: "", 19 | name: "", 20 | imageUrl: "", 21 | metadata: { 22 | walletAddress: zeroAddress, 23 | }, 24 | rank: 0, 25 | skills: [], 26 | apiKey: "", 27 | registeredCompetitionIds: [], 28 | userId: undefined, 29 | stats: undefined, 30 | trophies: undefined, 31 | hasUnclaimedRewards: false, 32 | score: 0, 33 | rewards: undefined, 34 | description: "", 35 | status: "", 36 | }); 37 | -------------------------------------------------------------------------------- /apps/comps/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@recallnet/typescript-config/nextjs.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "skipLibCheck": true, 6 | "module": "esnext", 7 | "moduleResolution": "bundler", 8 | "paths": { 9 | "@/*": ["./*"], 10 | "@/types": ["types/index.ts"], 11 | "@/utils/*": ["utils/*"], 12 | "@/data-mock/*": ["data-mock/*"], 13 | "@recallnet/ui2/*": ["../../packages/ui2/src/*"] 14 | }, 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ] 20 | }, 21 | "include": [ 22 | "next-env.d.ts", 23 | "next.config.ts", 24 | "**/*.ts", 25 | "**/*.tsx", 26 | ".next/types/**/*.ts", 27 | "components/create-agent.tsx", 28 | "../../packages/ui2/src/components/badge.tsx" 29 | ], 30 | "exclude": ["node_modules"] 31 | } 32 | -------------------------------------------------------------------------------- /apps/comps/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://typedoc.org/schema.json", 3 | "extends": ["../../typedoc.base.json"], 4 | "entryPoints": [] 5 | } 6 | -------------------------------------------------------------------------------- /apps/comps/types/api.ts: -------------------------------------------------------------------------------- 1 | export interface PaginationResponse { 2 | total: number; 3 | limit: number; 4 | offset: number; 5 | hasMore: boolean; 6 | } 7 | 8 | // GET /competitions query parameters 9 | export interface GetCompetitionsParams { 10 | status?: string; 11 | limit?: number; 12 | offset?: number; 13 | sort?: string; 14 | } 15 | 16 | // GET /competitions/{competitionId}/agents query parameters 17 | export interface GetCompetitionAgentsParams { 18 | filter?: string; 19 | sort?: string; 20 | limit?: number; 21 | offset?: number; 22 | } 23 | 24 | // GET /agents query parameters 25 | export interface GetAgentsParams { 26 | filter?: string; 27 | sort?: string; 28 | limit?: number; 29 | offset?: number; 30 | } 31 | 32 | // GET /agents/{agentId}/competitions query parameters 33 | export interface GetAgentCompetitionsParams { 34 | status?: string; 35 | claimed?: boolean; 36 | limit?: number; 37 | offset?: number; 38 | sort?: string; 39 | } 40 | 41 | // GET /leaderboard query parameters 42 | export interface GetLeaderboardParams { 43 | type?: string; 44 | limit?: number; 45 | offset?: number; 46 | } 47 | -------------------------------------------------------------------------------- /apps/comps/types/auth.ts: -------------------------------------------------------------------------------- 1 | import { AgentResponse } from "./agent"; 2 | 3 | export interface NonceResponse { 4 | nonce: string; 5 | } 6 | 7 | export interface LoginRequest { 8 | wallet: string; 9 | signature: string; 10 | message: string; 11 | } 12 | 13 | export interface LoginResponse { 14 | userId: string; 15 | wallet: string; 16 | } 17 | -------------------------------------------------------------------------------- /apps/comps/types/enums.ts: -------------------------------------------------------------------------------- 1 | export enum CompetitionStatus { 2 | Pending = "pending", 3 | Active = "active", 4 | Completed = "completed", 5 | } 6 | 7 | export enum LeaderboardTypes { 8 | TRADING = "TRADING", 9 | DERIVATIVES = "DERIVATIVES", 10 | ANALYSIS = "SENTIMENT-ANALYSIS", 11 | } 12 | 13 | export enum CrossChainTradingType { 14 | DisallowAll = "disallowAll", 15 | DisallowXParent = "disallowXParent", 16 | Allow = "allow", 17 | } 18 | -------------------------------------------------------------------------------- /apps/comps/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./enums"; 2 | export * from "./competition"; 3 | export * from "./agent"; 4 | export * from "./auth"; 5 | export * from "./api"; 6 | export * from "./profile"; 7 | -------------------------------------------------------------------------------- /apps/comps/types/profile.ts: -------------------------------------------------------------------------------- 1 | import { AgentResponse } from "./agent"; 2 | 3 | export interface ProfileResponse { 4 | success: boolean; 5 | user: { 6 | createdAt: string; 7 | updatedAt: string; 8 | walletAddress: string; 9 | id: string; 10 | 11 | isVerified?: boolean; 12 | agents?: AgentResponse[]; 13 | name?: string; 14 | email?: string; 15 | imageUrl?: string; 16 | website?: string; 17 | }; 18 | } 19 | 20 | export interface UpdateProfileRequest { 21 | name?: string; 22 | email?: string; 23 | imageUrl?: string; 24 | metadata?: { 25 | website?: string; 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /apps/comps/utils/filter.ts: -------------------------------------------------------------------------------- 1 | export const applyFilters = >( 2 | rows: T[], 3 | filter?: string, 4 | ) => { 5 | if (!filter) return rows; 6 | const clauses = filter.split(",").map((c) => c.split(":")); 7 | return rows.filter((r) => 8 | clauses.every(([k, v]) => { 9 | if (!k || v === undefined) return true; 10 | const val = r[k]; 11 | return Array.isArray(val) ? val.includes(v) : String(val) === v; 12 | }), 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /apps/comps/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./filter"; 2 | export * from "./sort"; 3 | export * from "./paginate"; 4 | -------------------------------------------------------------------------------- /apps/comps/utils/paginate.ts: -------------------------------------------------------------------------------- 1 | export const paginate = (rows: T[], limit = 20, offset = 0) => ({ 2 | metadata: { total: rows.length, limit, offset }, 3 | data: rows.slice(offset, offset + limit), 4 | }); 5 | -------------------------------------------------------------------------------- /apps/comps/utils/sort.ts: -------------------------------------------------------------------------------- 1 | export const applySort = (rows: T[], sort?: string) => { 2 | if (!sort) return rows; 3 | const fields = sort.split(","); 4 | return [...rows].sort((a: any, b: any) => { 5 | for (const f of fields) { 6 | const desc = f.startsWith("-"); 7 | const key = desc ? f.slice(1) : f; 8 | if (a[key] === b[key]) continue; 9 | return (a[key] > b[key] ? 1 : -1) * (desc ? -1 : 1); 10 | } 11 | return 0; 12 | }); 13 | }; 14 | -------------------------------------------------------------------------------- /apps/comps/wagmi-config.ts: -------------------------------------------------------------------------------- 1 | import { getDefaultConfig } from "@rainbow-me/rainbowkit"; 2 | import { Config, createConfig, http } from "wagmi"; 3 | import { baseSepolia } from "wagmi/chains"; 4 | 5 | export const clientConfig: () => Config = () => 6 | getDefaultConfig({ 7 | appName: "js-recall/comps", 8 | projectId: 9 | process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID || 10 | "your_walletconnect_project_id", 11 | chains: [baseSepolia], 12 | ssr: true, 13 | }); 14 | 15 | export const serverConfig = () => 16 | createConfig({ 17 | chains: [baseSepolia], 18 | ssr: true, 19 | transports: { 20 | [baseSepolia.id]: http(), 21 | }, 22 | }) as Config; 23 | -------------------------------------------------------------------------------- /apps/faucet/.env.example: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_CHAIN_NAME=testnet 2 | NEXT_PUBLIC_TS_SITE_KEY=your-turnstile-site-key -------------------------------------------------------------------------------- /apps/faucet/app/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/faucet/app/android-chrome-192x192.png -------------------------------------------------------------------------------- /apps/faucet/app/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/faucet/app/android-chrome-512x512.png -------------------------------------------------------------------------------- /apps/faucet/app/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/faucet/app/apple-touch-icon.png -------------------------------------------------------------------------------- /apps/faucet/app/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/faucet/app/favicon-16x16.png -------------------------------------------------------------------------------- /apps/faucet/app/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/faucet/app/favicon-32x32.png -------------------------------------------------------------------------------- /apps/faucet/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/faucet/app/favicon.ico -------------------------------------------------------------------------------- /apps/faucet/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import "@recallnet/ui/globals.css"; 2 | 3 | import { Analytics } from "@vercel/analytics/react"; 4 | import type { Metadata } from "next"; 5 | 6 | import { fontMono, fontSans } from "@recallnet/fonts"; 7 | import { Toaster } from "@recallnet/ui/components/shadcn/sonner"; 8 | import { ThemeProvider } from "@recallnet/ui/components/theme-provider"; 9 | 10 | export const metadata: Metadata = { 11 | title: "Recall Faucet", 12 | description: "Request RECALL from the Recall faucet", 13 | }; 14 | 15 | export default async function RootLayout({ 16 | children, 17 | }: Readonly<{ 18 | children: React.ReactNode; 19 | }>) { 20 | return ( 21 | 22 | 25 | 32 | {children} 33 | 34 | 35 | 36 | 37 | 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /apps/faucet/app/page.tsx: -------------------------------------------------------------------------------- 1 | import { RecallLogo } from "@recallnet/ui/components/logos/recall-logo"; 2 | import { ThemeToggle } from "@recallnet/ui/components/theme-toggle"; 3 | 4 | import RequestTokensForm from "./_components/request-tokens-form"; 5 | 6 | export default async function Home() { 7 | return ( 8 |
9 | 10 |
11 | 16 | 17 | Testnet Faucet 18 | 19 |
20 | 21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /apps/faucet/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "", 8 | "css": "../../packages/ui/src/styles/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true 11 | }, 12 | "iconLibrary": "lucide", 13 | "aliases": { 14 | "components": "@/components", 15 | "hooks": "@/hooks", 16 | "lib": "@/lib", 17 | "utils": "@recallnet/ui/lib/utils", 18 | "ui": "@recallnet/ui/components/shadcn" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /apps/faucet/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/faucet/components/.gitkeep -------------------------------------------------------------------------------- /apps/faucet/eslint.config.js: -------------------------------------------------------------------------------- 1 | import { nextJsConfig } from "@recallnet/eslint-config/next-js"; 2 | 3 | /** @type {import("eslint").Linter.Config} */ 4 | export default nextJsConfig; 5 | -------------------------------------------------------------------------------- /apps/faucet/hooks/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recallnet/js-recall/b4f91c120c2621a928c33b51983c4d2fac107a13/apps/faucet/hooks/.gitkeep -------------------------------------------------------------------------------- /apps/faucet/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. 6 | -------------------------------------------------------------------------------- /apps/faucet/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | transpilePackages: ["@recallnet/ui", "@recallnet/fonts"], 4 | }; 5 | 6 | export default nextConfig; 7 | -------------------------------------------------------------------------------- /apps/faucet/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "faucet", 3 | "version": "0.0.0", 4 | "type": "module", 5 | "private": true, 6 | "scripts": { 7 | "dev": "next dev --turbopack", 8 | "build": "next build", 9 | "start": "next start", 10 | "lint": "next lint", 11 | "clean": "rm -rf .turbo .next node_modules" 12 | }, 13 | "dependencies": { 14 | "@marsidev/react-turnstile": "^1.1.0", 15 | "@recallnet/chains": "workspace:*", 16 | "@recallnet/fonts": "workspace:*", 17 | "@recallnet/ui": "workspace:*", 18 | "@vercel/analytics": "^1.5.0", 19 | "lucide-react": "0.456.0", 20 | "next": "^15.1.0", 21 | "react": "^19.0.0", 22 | "react-dom": "^19.0.0", 23 | "zod": "^3.25.17" 24 | }, 25 | "devDependencies": { 26 | "@recallnet/eslint-config": "workspace:^", 27 | "@recallnet/typescript-config": "workspace:*", 28 | "@types/node": "^20", 29 | "@types/react": "^19.0.0", 30 | "@types/react-dom": "^19.0.0", 31 | "typescript": "^5.7.3" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /apps/faucet/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | export { default } from "@recallnet/ui/postcss.config"; 2 | -------------------------------------------------------------------------------- /apps/faucet/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@recallnet/typescript-config/nextjs.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": ["./*"], 7 | "@recallnet/ui/*": ["../../packages/ui/src/*"] 8 | }, 9 | "plugins": [ 10 | { 11 | "name": "next" 12 | } 13 | ] 14 | }, 15 | "include": [ 16 | "next-env.d.ts", 17 | "next.config.ts", 18 | "**/*.ts", 19 | "**/*.tsx", 20 | ".next/types/**/*.ts" 21 | ], 22 | "exclude": ["node_modules"] 23 | } 24 | -------------------------------------------------------------------------------- /apps/portal/.env.example: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_walletconnect_project_id 2 | NEXT_PUBLIC_CHAIN_NAME="testnet" -------------------------------------------------------------------------------- /apps/portal/app/_components/agent-activity-list.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import type { AgentActivity } from "@/types/agent-activity"; 4 | 5 | import { AgentActivityEntry } from "./agent-activity-entry"; 6 | 7 | interface AgentActivityListProps { 8 | activities: AgentActivity[]; 9 | } 10 | 11 | export function AgentActivityList({ activities }: AgentActivityListProps) { 12 | return ( 13 |
14 | {activities.map((activity) => ( 15 | 16 | ))} 17 |
18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /apps/portal/app/_components/slash.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from "react"; 2 | 3 | export default function Slash(props: SVGProps) { 4 | return ( 5 | 12 | 17 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /apps/portal/app/account/page.tsx: -------------------------------------------------------------------------------- 1 | import { AccountTabs } from "./_components/account-tabs"; 2 | 3 | export default async function AccountPage() { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /apps/portal/app/agents/_components/agent.tsx: -------------------------------------------------------------------------------- 1 | import { Auth } from "./cards/auth"; 2 | import { Chat } from "./cards/chat"; 3 | import { Memory } from "./cards/memory"; 4 | import { Objects } from "./cards/objects"; 5 | import { Settings } from "./cards/settings"; 6 | 7 | type Props = { 8 | name: string; 9 | apiUrl: string; 10 | apiKey: string; 11 | systemInstructions: string; 12 | persona: string; 13 | human: string; 14 | }; 15 | 16 | export function Agent({ 17 | name, 18 | apiUrl, 19 | apiKey, 20 | systemInstructions, 21 | persona, 22 | human, 23 | }: Props) { 24 | return ( 25 |
26 | 27 | 28 | 29 | 30 | 31 |
32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /apps/portal/app/agents/_components/cards/auth.tsx: -------------------------------------------------------------------------------- 1 | import { ComponentProps } from "react"; 2 | 3 | import { 4 | Card, 5 | CardContent, 6 | CardDescription, 7 | CardHeader, 8 | CardTitle, 9 | } from "@recallnet/ui/components/shadcn/card"; 10 | import { Input } from "@recallnet/ui/components/shadcn/input"; 11 | import { Label } from "@recallnet/ui/components/shadcn/label"; 12 | 13 | type ChatProps = ComponentProps & { 14 | apiUrl: string; 15 | apiKey: string; 16 | }; 17 | 18 | export function Auth({ apiUrl, apiKey, ...props }: ChatProps) { 19 | return ( 20 | 21 | 22 | Agent Authentication 23 | 24 | Connection settings for interacting with the agent endpoint. 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /apps/portal/app/agents/_components/cards/chat.tsx: -------------------------------------------------------------------------------- 1 | import { ComponentProps } from "react"; 2 | 3 | import { Button } from "@recallnet/ui/components/button"; 4 | import { 5 | Card, 6 | CardContent, 7 | CardDescription, 8 | CardHeader, 9 | CardTitle, 10 | } from "@recallnet/ui/components/shadcn/card"; 11 | import { ScrollArea } from "@recallnet/ui/components/shadcn/scroll-area"; 12 | import { Textarea } from "@recallnet/ui/components/shadcn/textarea"; 13 | 14 | type ChatProps = ComponentProps; 15 | 16 | export function Chat(props: ChatProps) { 17 | return ( 18 | 19 | 20 | Agent chat 21 | Interact with your agent. 22 | 23 | 24 | 25 |