Modern web interface for interacting with the EqualFi protocol built with Next.js 15, React 19, and wagmi v2.
- Node.js 18.x or higher
- pnpm 8.x or higher (recommended) or npm
- PostgreSQL 14.x or higher
- Git
- Foundry (for local blockchain testing)
cd website
pnpm installCreate a PostgreSQL database:
createdb equalfiOr using psql:
CREATE DATABASE equalfi;Initialize the database schema:
psql equalfi < indexer/sql/schema.sqlOr manually:
CREATE TABLE IF NOT EXISTS auctions (
chain_id INTEGER NOT NULL,
auction_id BIGINT NOT NULL,
type TEXT NOT NULL,
maker_position_id BIGINT,
pool_id_a INTEGER,
pool_id_b INTEGER,
token_a TEXT,
token_b TEXT,
reserve_a NUMERIC,
reserve_b NUMERIC,
start_time BIGINT,
end_time BIGINT,
fee_bps INTEGER,
fee_asset INTEGER,
active BOOLEAN,
finalized BOOLEAN,
raw JSONB,
block_number BIGINT,
tx_hash TEXT,
updated_at TIMESTAMPTZ DEFAULT NOW(),
PRIMARY KEY (chain_id, auction_id)
);
CREATE TABLE IF NOT EXISTS indexer_state (
chain_id INTEGER PRIMARY KEY,
last_block BIGINT NOT NULL,
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS auctions_active_idx ON auctions (active, finalized);
CREATE INDEX IF NOT EXISTS auctions_pair_idx ON auctions (token_a, token_b);
CREATE INDEX IF NOT EXISTS auctions_updated_idx ON auctions (updated_at DESC);Create a .env.local file in the website/ directory:
# Database Connection
DATABASE_URL=postgresql://username:password@localhost:5432/equalfi
# WalletConnect Project ID (get from https://cloud.walletconnect.com)
NEXT_PUBLIC_WC_PROJECT_ID=your_project_id_here
# Indexer Configuration (optional - for running the indexer)
# Select networks: arbitrum-sepolia,base-sepolia,ethereum-sepolia,anvil
INDEXER_NETWORKS=anvil
# Anvil (Local Foundry)
RPC_URL_ANVIL=http://127.0.0.1:8545
DIAMOND_ADDRESS_ANVIL=0xbcdc0d1555c4875fd3cd08d1227530c9b8e698c3
START_BLOCK_ANVIL=0
# Arbitrum Sepolia
RPC_URL_ARBITRUM_SEPOLIA=https://sepolia-rollup.arbitrum.io/rpc
DIAMOND_ADDRESS_ARBITRUM_SEPOLIA=0x027c9ba58be0af69c990da55630d9042d067652b
START_BLOCK_ARBITRUM_SEPOLIA=0
# Base Sepolia
RPC_URL_BASE_SEPOLIA=https://sepolia.base.org
DIAMOND_ADDRESS_BASE_SEPOLIA=0x027c9ba58be0af69c990da55630d9042d067652b
START_BLOCK_BASE_SEPOLIA=0
# Ethereum Sepolia
RPC_URL_ETHEREUM_SEPOLIA=https://rpc.sepolia.org
DIAMOND_ADDRESS_ETHEREUM_SEPOLIA=0x027c9ba58be0af69c990da55630d9042d067652b
START_BLOCK_ETHEREUM_SEPOLIA=0Note: Contract addresses are configured in src/lib/pools.json and support multi-chain deployments.
The application uses src/lib/pools.json for multi-chain contract addresses. This file is already configured with:
- Foundry (31337): Local development addresses
- Testnets (421614, 84532, 11155111): Shared addresses for Arbitrum Sepolia, Base Sepolia, and Ethereum Sepolia
After deploying to new networks, update the appropriate section in pools.json:
{
"31337": {
"diamondAddress": "0xbcdc0d1555c4875fd3cd08d1227530c9b8e698c3",
"positionNFTAddress": "0x82c098efe320a6226dda913e286bd309994e310c",
"faucetAddress": "0x88d90fDA745Da2487974879D400A5eCe434D811c",
"pools": [...]
},
"testnets": {
"diamondAddress": "0x027c9ba58be0af69c990da55630d9042d067652b",
"positionNFTAddress": "0x560beed75ba42f99602f8786abc4700c8b4cb1c5",
"faucetAddress": "0x88d90fDA745Da2487974879D400A5eCe434D811c",
"pools": [...]
}
}In the root project directory:
anvilIn a separate terminal:
forge script script/DeployDiamond.s.sol --rpc-url http://127.0.0.1:8545 --broadcastAfter deployment, update addresses in src/lib/pools.json for the appropriate network section.
pnpm devThe application will be available at http://localhost:3000.
pnpm buildpnpm startFor production deployments, set the following environment variables:
NEXT_PUBLIC_RPC_URL: Production RPC endpoint (e.g., Alchemy, Infura)NEXT_PUBLIC_CHAIN_ID: Target chain ID (1 for Ethereum mainnet, 42161 for Arbitrum, etc.)DATABASE_URL: Production PostgreSQL connection string- All contract addresses from deployment
- Connect your GitHub repository to Vercel
- Set environment variables in Vercel dashboard
- Deploy
FROM node:18-alpine AS base
# Install dependencies
FROM base AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable pnpm && pnpm install --frozen-lockfile
# Build
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN corepack enable pnpm && pnpm build
# Production
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]Build and run:
docker build -t equalfi-web .
docker run -p 3000:3000 --env-file .env.local equalfi-web- Framework: Next.js 15 (App Router)
- React: 19.x
- Styling: Tailwind CSS
- Web3: wagmi v2, viem
- Database: PostgreSQL with pg driver
- State Management: React hooks + Context API
website/
├── src/
│ ├── app/ # Next.js app router pages
│ │ ├── api/ # API routes
│ │ │ └── auctions/ # Auction data endpoint
│ │ ├── app/ # Main application pages
│ │ │ ├── auctions/ # Auction management
│ │ │ ├── credit/ # P2P lending
│ │ │ ├── faucet/ # Token faucet
│ │ │ ├── index/ # Index tokens
│ │ │ ├── position/ # Position management
│ │ │ └── swap/ # Token swaps
│ │ └── blog/ # Blog/documentation
│ ├── components/ # React components
│ │ ├── common/ # Shared components
│ │ ├── create/ # Creation forms
│ │ └── pool/ # Pool/auction components
│ ├── lib/ # Utilities and configuration
│ │ ├── abis/ # Contract ABIs
│ │ ├── hooks/ # Custom React hooks
│ │ ├── db.ts # Database client
│ │ ├── pools.json # Pool configuration
│ │ └── tokens.js # Token utilities
│ └── styles/ # Global styles
├── public/ # Static assets
├── .env.local # Environment variables
└── package.json
- Position Management: Create and manage Position NFTs
- Lending & Borrowing: Self-secured credit and P2P lending
- AMM Auctions: Solo and community liquidity pools
- Token Swaps: Swap tokens through auction pools
- Index Tokens: Create and manage basket tokens
- Derivatives: Options and futures trading
- Agent Wallets: ERC-6551 token-bound accounts with ERC-6900 modules
The indexer automatically tracks auction events across all configured networks.
# Index all configured networks
node indexer/index.mjs
# Index specific networks
node indexer/index.mjs --networks anvil
node indexer/index.mjs --networks arbitrum-sepolia,base-sepolia,ethereum-sepolia
# Or use environment variable
INDEXER_NETWORKS=anvil node indexer/index.mjsNetworks are configured in indexer/config.mjs. Each network requires:
RPC_URL_*- RPC endpointDIAMOND_ADDRESS_*- Deployed Diamond contract addressSTART_BLOCK_*(optional) - Block to start indexing from
The indexer will:
- Automatically create database tables on first run
- Track last indexed block per chain in
indexer_statetable - Resume from last block on restart
- Skip networks with missing configuration
See indexer/README.md for more details.
# Backup
pg_dump equalfi > equalfi_backup.sql
# Restore
psql equalfi < equalfi_backup.sqlIssue: "Cannot connect to database"
- Verify PostgreSQL is running:
pg_isready - Check
DATABASE_URLin.env.local - Ensure database exists:
psql -l | grep equalfi
Issue: "Contract call reverted"
- Verify you're connected to the correct network in your wallet
- Check contract addresses in
pools.jsonmatch your connected network - Ensure wallet has sufficient gas
Issue: "Auctions not displaying"
- Ensure the indexer is running:
node indexer/index.mjs - Check database has auction records:
psql equalfi -c "SELECT * FROM auctions;" - Verify indexer is configured for the correct network
- Hard refresh browser (Ctrl+Shift+R)
Issue: "Expected Share (%) shows 0"
- This was fixed in recent updates
- Ensure you're on the latest code
- Check browser console for calculation logs
Issue: "Indexer not finding events"
- Verify
DIAMOND_ADDRESS_*matches deployed contract - Check
START_BLOCK_*is set to deployment block or earlier - Ensure RPC endpoint is accessible and not rate-limited
Enable verbose logging:
NEXT_PUBLIC_DEBUG=true pnpm devThe application supports multiple networks:
- Foundry Local (chainId: 31337)
- Arbitrum Sepolia (chainId: 421614)
- Base Sepolia (chainId: 84532)
- Ethereum Sepolia (chainId: 11155111)
Network switching is handled automatically by the UI based on the connected wallet's network.
- Add network configuration to
indexer/config.mjs - Add corresponding env vars for RPC URL, Diamond address, and start block
- Deploy contracts to the new network
- Update
src/lib/pools.jsonwith new network section (or add to "testnets" if addresses match)
Fetch auction data from database.
Query Parameters:
chainId(optional): Filter by chain IDscope(optional):active(default) orallpage(optional): Page number (default: 1)limit(optional): Results per page (default: 50, max: 100)
Response:
{
"auctions": [
{
"id": 1,
"type": "solo",
"token_a": "0x...",
"token_b": "0x...",
"reserve_a": "5000000000000000000",
"reserve_b": "15000000000",
"active": true,
"finalized": false
}
],
"page": 1,
"limit": 50
}See the main project README for contribution guidelines.
BUSL-1.1 - See LICENSE file in root directory.