Clean architecture overview for the Bun-Eth monorepo.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Frontend Layer β
β ββββββββββββββββββ ββββββββββββββββ βββββββββββββββββββ β
β β Next.js App ββββ RainbowKit ββββ Wallet Connect β β
β β (apps/web) β β Provider β β β β
β ββββββββββ¬ββββββββ ββββββββββββββββ βββββββββββββββββββ β
β β β
β βΌ β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β @bun-eth/components (UI Layer) β β
β β β’ Address β’ Balance β’ Faucet β’ Inputs β β
β βββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββ β
β β β
β βΌ β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β @bun-eth/hooks (Business Logic) β β
β β β’ useScaffoldContract β’ useScaffoldRead/Write β β
β β β’ useTransactor β’ useWatchBalance β β
β βββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββ β
β β β
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββ
β wagmi + viem β
β (Ethereum Interaction) β
ββββββββββββββββ¬ββββββββββββββββββββ
β
ββββββββββββββββββΌβββββββββββββββββ
β β β
βΌ βΌ βΌ
ββββββββββ βββββββββββ ββββββββββββ
β Anvil β β API β β Mainnet/ β
β (Dev) β β (Elysia)β β Sepolia β
ββββββββββ βββββββββββ ββββββββββββ
- Purpose: User-facing dApp interface
- Tech Stack: Next.js 14, React 18, Tailwind CSS
- Dependencies:
@bun-eth/hooks- Contract interactions@bun-eth/components- UI components@rainbow-me/rainbowkit- Wallet connectionwagmi- Ethereum hooksviem- Ethereum library
- Key Files:
src/app/- Next.js pages (App Router)src/components/- Local componentssrc/lib/wagmi.ts- Wagmi configuration
- Purpose: REST API for blockchain operations
- Tech Stack: Elysia, Bun runtime
- Dependencies:
@bun-eth/core- Shared utilities@bun-eth/sdk- API clientviem- Ethereum interactions
- Key Files:
src/index.ts- API entry pointsrc/routes/- API endpointssrc/provider.ts- Ethereum provider setup
- Purpose: Solidity contracts and deployment
- Tech Stack: Foundry (Forge, Anvil, Cast)
- Structure:
contracts/- Solidity source filesscript/- Deployment scriptstest/- Solidity testsbroadcast/- Deployment artifacts (gitignored)out/- Compiled contracts (gitignored)deployedContracts.ts- Generated file for hot reload
- Purpose: Generate TypeScript from Foundry deployments
- How it works:
- Reads
broadcast/*/run-latest.jsonfrom Foundry - Extracts contract addresses and ABIs
- Generates typed
deployedContracts.ts - Next.js Fast Refresh triggers UI update
- Reads
- API:
await generateDeployedContracts({ foundryRoot: "./packages/contracts", outputPath: "./packages/contracts/deployedContracts.ts", networks: { 31337: { name: "localhost" } } });
- Purpose: Type-safe React hooks for Web3 interactions
- Architecture: Composable hook pattern
useDeployedContractInfo (base) β βββ useScaffoldContract β β β βββ useScaffoldReadContract β βββ useScaffoldWriteContract β βββ useScaffoldEventHistory useScaffoldWatchContractEvent - Key Patterns:
- Base Hook:
useDeployedContractInfoloads contract metadata - Composition: Higher hooks build on base hook
- Type Safety: Full TypeScript inference
- Caching: React Query integration
- Base Hook:
- Purpose: Reusable Web3 UI components
- Design Principles:
- Composition over configuration
- Tailwind CSS for styling
- Accessible by default
- Mobile-responsive
- Categories:
- Display: Address, Balance, BlockieAvatar
- Input: AddressInput, EtherInput, IntegerInput
- Tools: Faucet, NetworksDropdown
- Usage:
import { Address, Balance } from "@bun-eth/components"; <Address address={addr} format="short" /> <Balance address={addr} usdMode />
- Purpose: Common utilities across packages
- Contents:
- Type definitions
- Logger setup
- Utility functions
- Constants
- Purpose: Client library for the API
- Usage:
import { createClient } from "@bun-eth/sdk"; const client = createClient({ baseUrl: "http://localhost:3001" }); await client.getWallet("0x...");
- Purpose: Command-line task runner
- Key Tasks:
task setup- Complete setup with teststask dev:up- Start Docker stacktask contracts:deploy- Deploy and generate typestask contracts:generate- Generate TypeScripttask web:dev- Start Next.js dev server
Developer runs `task contracts:deploy`
β
βΌ
βββββββββββββββββββββββββββ
β 1. Forge deploys contractβ
β to Anvil (localhost) β
βββββββββββββ¬βββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββ
β 2. Foundry writes broadcast JSON β
β broadcast/Deploy.s.sol/31337/ β
β run-latest.json β
βββββββββββββ¬ββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββ
β 3. Post-deploy hook triggers β
β `task contracts:generate` β
βββββββββββββ¬ββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββ
β 4. foundry-deployer reads artifacts β
β and generates TypeScript β
βββββββββββββ¬ββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββ
β 5. deployedContracts.ts updated β
β with new addresses and ABIs β
βββββββββββββ¬ββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββ
β 6. Next.js detects file change β
β Fast Refresh triggers β
βββββββββββββ¬ββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββ
β 7. React components re-render β
β with new contract data β¨ β
βββββββββββββββββββββββββββββββββββββββ
Component calls useScaffoldReadContract
β
βΌ
βββββββββββββββββββββββββββββββββββββ
β 1. Hook loads contract info β
β from deployedContracts.ts β
βββββββββββββ¬ββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββ
β 2. wagmi useReadContract called β
β with address and ABI β
βββββββββββββ¬ββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββ
β 3. viem publicClient.readContract β
β makes RPC call β
βββββββββββββ¬ββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββ
β 4. Anvil/Network returns value β
βββββββββββββ¬ββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββ
β 5. React Query caches result β
β Auto-refetches on new blocks β
βββββββββββββ¬ββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββ
β 6. Component receives data β
β TypeScript type-safe β
β
βββββββββββββββββββββββββββββββββββββ
User clicks button
β
βΌ
βββββββββββββββββββββββββββββββββββββ
β 1. useScaffoldWriteContract β
β writeContractAsync called β
βββββββββββββ¬ββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββ
β 2. useTransactor wraps call β
β Shows loading toast π β
βββββββββββββ¬ββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββ
β 3. User signs transaction β
β in wallet β
βββββββββββββ¬ββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββ
β 4. Transaction sent to network β
β Hash returned β
βββββββββββββ¬ββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββ
β 5. Wait for receipt β
β Block confirmations tracked β
βββββββββββββ¬ββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββ
β 6. Success toast shown β
β
β Contract state updated β
βββββββββββββ¬ββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββ
β 7. useScaffoldReadContract β
β auto-refetches new state β
βββββββββββββββββββββββββββββββββββββ
- Via:
deployedContracts.ts(generated) - Type Safety: Full TypeScript inference
- Hot Reload: Automatic on deployment
- Via: RainbowKit + wagmi + viem
- Protocols: EIP-1193, WalletConnect
- Networks: Mainnet, Sepolia, Localhost
- Via:
@bun-eth/sdk - Protocol: HTTP/REST
- Use Cases: Server-side operations
- Dev: Anvil (localhost:3002)
- Test: Sepolia
- Prod: Mainnet/L2s
- Library: viem (publicClient)
Each package has clear responsibilities:
- Presentation:
apps/web - Business Logic:
packages/hooks - UI:
packages/components - Data:
packages/contracts - Infrastructure:
packages/foundry-deployer
High-level modules don't depend on low-level modules:
apps/web β packages/components β packages/hooks β wagmi
Hooks compose:
useScaffoldReadContract() {
const info = useDeployedContractInfo();
return useReadContract({ ...info });
}Each package has one reason to change:
hooks: Change when interaction patterns changecomponents: Change when UI requirements changefoundry-deployer: Change when deployment format changes
Easy to extend without modifying:
- Add new hooks without changing existing ones
- Add new components without breaking others
- Add new networks in config
- React Query caching
- Auto-refetch on blocks (configurable)
- Component lazy loading
- Bun's fast refresh
- Foundry's fast compilation
- Optimized Solidity
- Gas-efficient patterns
- Incremental TypeScript generation
- Selective network deployment
- Cached Docker layers
- Never commit private keys
- Use
.envfiles (gitignored) - Encrypted keystores for production
- Verify on Etherscan
- Publish source code
- Use reproducible builds
- No server-side key storage
- User signs all transactions
- Rate limiting on API
- Write Solidity in
packages/contracts/contracts/ - Deploy with
task contracts:deploy - TypeScript auto-generates
- Use in frontend immediately
- Create in
packages/hooks/src/ - Export from
index.ts - Use in any app
- Update
wagmi.tsconfig - Add to
foundry-deployernetworks - Deploy contracts
- Done
- Hooks: React Testing Library
- Components: Jest + React Testing Library
- Utils: Bun test
- Contract interactions: Foundry tests
- API endpoints: Bun test
- E2E: Playwright (future)
- Solidity unit tests (Foundry)
- Fuzz testing
- Invariant testing
- Gas profiling
Built with clean architecture principles and β‘ Bun speed.