This repository demonstrates the backend-heavy architecture described in the project brief. It follows a simple split:
marketplace_indexer.pyhandles Web3 connectivity, optional live-chain indexing, and a SQLite-backed order book.app_factory.py/main.pyexpose the API via FastAPI for local dev and deployment (e.g. Railway).index.htmlis a Tailwind + ethers.js UI that speaks to/api/listingsand can trigger a realbuyItemcall through MetaMask.
python -m venv .venv
.venv\Scripts\activate # Windows
pip install -r requirements.txt
uvicorn main:app --reloadOpen index.html in a browser. When developing locally the page defaults to http://localhost:8000 for API calls. You can override the backend origin by appending ?api=https://your-api-url to the page URL.
Configure these locally (e.g. via .env) or inside your hosting provider’s environment variable settings.
| Variable | Description | Default |
|---|---|---|
MARKETPLACE_RPC_URL |
HTTPS RPC endpoint (Infura, Alchemy, etc.) | Sepolia placeholder (mock-only) |
MARKETPLACE_CONTRACT_ADDRESS |
Deployed marketplace address | Dead address placeholder (mock-only) |
USE_MOCK_EVENTS |
true keeps using the static dataset (no RPC needed), false pulls real events via web3.py |
true |
BLOCK_LOOKBACK |
Number of blocks to scan when indexing | 10000 |
To enable real chain support you must:
- Set
USE_MOCK_EVENTS=false - Provide a non-placeholder
MARKETPLACE_RPC_URL(e.g. Infura/Alchemy with a real project key) - Provide a non-placeholder
MARKETPLACE_CONTRACT_ADDRESS(0x-prefixed, 40-hex-character address)
If any of these are missing or left on their placeholders, the indexer will raise a clear runtime error explaining what needs to be fixed instead of failing deep inside the Web3 stack.
- Install the Railway CLI and run
railway login. - From the project root run
railway init(first time) and connect the repo to a Railway service. - Deploy with
railway up. Railway will detect theDockerfile, build the image, and launchuvicorn main:app --host 0.0.0.0 --port $PORT. - Inside the Railway dashboard, set the environment variables from the table above (plus anything contract-specific).
Troubleshooting tips:
- If you see
ModuleNotFoundError: No module named 'encodings', double-check that the Docker builder is selected. That error shows up when Railway tries to boot a partial Python runtime instead of the container defined here. - Use
railway logsto tail output. The FastAPI server binds to the injectedPORT.
The frontend loads ethers.js@6 and integrates with MetaMask (or any EIP‑1193 wallet):
- Click Connect Wallet to trigger
eth_requestAccounts. - Listings are fetched from
/api/listings. - Press Buy NFT to call
buyItem(nftAddress, tokenId)on the configured marketplace contract. The value field uses the price (in wei) supplied by the backend. - The UI waits for the transaction receipt before marking the NFT as sold.
- Listings live in
IN_MEMORY_LISTINGS. Swap for SQLite/Postgres once persistence is required. marketplace_indexer.run_indexer()can be scheduled (e.g. cron) or invoked on FastAPI startup/serverless request depending on the deployment target.- Replace the placeholder ABI/address with your real contracts. The minimal ABI bundled here only includes the events and
buyItemfunction needed for the MVP.