This file provides guidance to AI agents when working with code in this repository. Always run all tests, lint, and typecheck after making changes, and before considering a task to be 'complete'.
Uniswap Universe is a monorepo containing all Uniswap front-end interfaces:
- Web (
apps/web/) - Decentralized exchange web interface - Mobile (
apps/mobile/) - React Native app for iOS/Android - Extension (
apps/extension/) - Browser wallet extension
# Initial setup (requires 1Password CLI)
bun install
bun local:check
bun lfg # Sets up mobile and extensionbun web dev # Web with Vite
bun mobile ios # iOS app
bun mobile android # Android app
bun extension start # Extensionbun g:build # Build all packages
bun web build:production # Web production build
bun mobile ios:bundle # iOS bundle
bun mobile android:release # Android release
bun extension build:production # Extension productionbun g:test # Run all tests
bun g:test:changed # Run tests for changed packages
bun web playwright:test # Web E2E tests
bun mobile e2e # Mobile E2E testsbun g:lint:fix # Fix linting issues
bun g:typecheck # Type check all packages
bun g:format # Fix formatting
bun i18n:extract # Extract localized strings (run after changing translations)- NX for build orchestration
- Bun workspaces for package management
- Shared code in
packages/directory - App-specific code in
apps/directory
- TypeScript everywhere
- React for web/extension
- React Native for mobile
- Redux Toolkit for state management
- Tamagui for cross-platform UI components
- Ethers.js/Viem for blockchain interactions
- ALWAYS use
styledfromui/src(never styled-components or direct Tamagui); UI components may use inline styling where appropriate - Use theme tokens instead of hardcoded values
- Platform-specific files:
Component.ios.tsx,Component.android.tsx,Component.web.tsx,Component.native.tsx(with stub files for platforms where specific implementation isn't needed)
- Redux for complex global state
- Zustand for simple global/shared state — do not use Jotai, we are migrating away from it. Flag any new Jotai usage in PRs and require Zustand instead.
- Keep state as local as possible
- No custom hooks for simple data fetching - use
useQuery/useMutationdirectly
- State declarations at top
- Event handlers after state
- Memoize properly, especially for anything that might be used in the React Native app
- JSX at the end
- Keep components under 250 lines
- Do not use
any, preferunknown - Always consider strict mode
- Use explicit return types
- PascalCase for types/interfaces
- camelCase for variables/functions
- String enums with initializers
- Test behaviors, not implementations
- Always update existing unit tests related to changes made
- Run tests before considering a task to be 'complete'
- Also run linting and typecheck before considering a task to be 'complete'
- Run
bun i18n:extractafter making changes to localized strings (e.g., using translation hooks likeuseTranslation)
- Environment Variables: Override URLs in
.env.defaults.local(mobile) or.env(extension) - Pre-commit Hooks: Use
--no-verifyto skip or setexport LEFTHOOK=0to disable - Python Setup: Run
brew install python-setuptoolsif you encounter Python module errors - Mobile Development: Always run
bun mobile podafter dependency changes - Bundle Size: Monitor bundle size impacts when adding dependencies
Core shared packages:
packages/ui/- Cross-platform UI components and themepackages/uniswap/- Core business logic and utilitiespackages/wallet/- Wallet functionalitypackages/utilities/- Common utilities
- Support for multiple chains (Ethereum, Arbitrum, Optimism, etc.)
- Uniswap Protocol v2, v3, v4, and UniswapX support
- Multiple wallet providers (WalletConnect, Metamask, etc.)
- Transaction building and gas estimation
Be cognizant of the app or package within which a given change is being made. Be sure to reference that app or package's respective AGENTS.md file and other local configuration files, including (but not limited to): package.json, tsconfig.json, etc.
- When running tasks (for example build, lint, test, e2e, etc.), always prefer running the task through
nx(i.e.nx run,nx run-many,nx affected) instead of using the underlying tooling directly - You have access to the Nx MCP server and its tools, use them to help the user
- When answering questions about the repository, use the
nx_workspacetool first to gain an understanding of the workspace architecture where applicable. - When working in individual projects, use the
nx_project_detailsmcp tool to analyze and understand the specific project structure and dependencies - For questions around nx configuration, best practices or if you're unsure, use the
nx_docstool to get relevant, up-to-date docs. Always use this instead of assuming things about nx configuration - If the user needs help with an Nx configuration or project graph error, use the
nx_workspacetool to get any errors
- Node.js v22.22.2 and Bun 1.3.11 are pre-installed and match
.nvmrc/.bun-version. - The
tsgobinary is atnode_modules/.bin/tsgo(not globally in PATH). Thebun g:typecheckscript handles this automatically. - Set
export LEFTHOOK=0to disable git hooks in Cloud Agent sessions (no TTY for interactive hooks). - All backend APIs are external (no local databases or Docker needed for development).
- Start dev server:
bun web dev→ runs onhttp://localhost:3000/ - Run tests:
bunx nx run web:test -- --run(317 test files, ~2.5 min) - Lint (fast):
bunx nx run web:format(formatting) andbunx nx run web:lint(oxlint) - Typecheck:
bun g:typecheckrunstsgo -bglobally (fastest). Per-project:bunx nx run web:typecheck. - The
web:typecheck:cloudtarget typechecks theapps/web/functions/(edge functions) separately and may fail independently of the main app. - The web app loads live data from Uniswap's public APIs without requiring API keys for basic swap quotes and token exploration.
- Start dev server:
bun extension dev→ WXT builds the extension and opens Chrome with it pre-loaded. - A pre-built extension is available at
/var/tmp/stretchand is already loaded in the default Chrome profile (/home/ubuntu/.config/google-chrome). - The extension wallet is already onboarded. To unlock it, use the password from the
EXTENSION_UNLOCK_PASSWORDenvironment variable. - To type the password programmatically: write it to a temp file with
python3 -c "import os; open('/tmp/ext_pw.txt','w').write(os.environ['EXTENSION_UNLOCK_PASSWORD'])", then read/type from that file (the env var value is redacted in shell output but available to processes). - The extension opens as a side panel in Chrome (not a popup). Click the Uniswap icon in the toolbar or use Ctrl+Shift+U.
- The wallet contains a small amount of ETH and cBTC on Ethereum mainnet.
- Known limitation: connecting the extension wallet to the web app on
localhostdoes not currently work (theexternally_connectablemanifest only allowsapp.uniswap.organd staging origins).
bun installruns apreinstallscript that validates Node/Bun versions and will fail if they don't match.nvmrc/.bun-version.- The
postinstallscript runsgit config core.hooksPath .husky && bun g:prepare. Theg:preparestep (nx run-many -t prepare) generates codegen files needed for typecheck/build. - Mobile requires native tooling (Xcode, CocoaPods, Android SDK) not available in Cloud Agent VMs.
- When running
bun extension dev, WXT creates aweb-ext.config.tsoverride file (gitignored) to customize browser startup behavior. You can setstartUrls,chromiumArgs, orWXT_NO_OPEN_BROWSER=trueas needed.