This project is a decentralized cryptocurrency exchange (DEX) built on the Ethereum blockchain. It allows users to trade ERC-20 tokens, create and fill orders, and manage token balances.
- Node.js and npm
- MetaMask browser extension
- Basic understanding of Ethereum and smart contracts
- installation of Hardhat and other development tools
- edit package.json with project name and dependencies
- run
npm install
to install dependencies - run
npx hardhat compile
to compile the contracts - run
npx hardhat node
to start a local blockchain node - run
npx hardhat run scripts/1_deploy.js --network localhost
to deploy the contracts - run
npx hardhat run scripts/2_seed_exchange.js --network localhost
to seed the exchange with test data
-
Create a .env file: Copy the
.env.example
file to.env
and fill in your API keys and private keys:cp .env.example .env
Then edit the
.env
file with your:- Private keys for deployment accounts
- Infura API key
- Alchemy API key (recommended for better rate limits)
-
Install dependencies:
npm install --save-dev @nomiclabs/hardhat-waffle
-
Start a local Hardhat blockchain node:
npx hardhat node
-
Deploy the contracts to the local blockchain:
npx hardhat run scripts/1_deploy.js --network localhost
-
Seed the exchange with test data:
npx hardhat run scripts/2_seed_exchange.js --network localhost
-
Update the contract addresses in
src/config.json
with the addresses from step 2:{ "31337": { "exchange": { "address": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9" }, "DApp": { "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3" }, "mETH": { "address": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" }, "mDAI": { "address": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" } } }
-
Configure MetaMask to connect to your local Hardhat network:
- Network Name: Hardhat Local
- RPC URL: http://127.0.0.1:8545
- Chain ID: 31337
- Currency Symbol: ETH
-
Import Hardhat test accounts into MetaMask:
- Account #0: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
- Private Key: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
- Account #1: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8
- Private Key: 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
- Account #0: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
-
Start the React app:
npm start
For deploying to a public testnet like Sepolia:
-
Configure environment variables: Make sure your
.env
file is set up properly with your:PRIVATE_KEYS
for deployment accountsINFURA_API_KEY
for Infura accessALCHEMY_API_KEY
for Alchemy access (recommended for higher rate limits)
These keys will be used both for contract deployment and by the React app.
-
Configure MetaMask for Sepolia testnet:
- Network Name: Sepolia Test Network
- RPC URL: https://eth-sepolia.g.alchemy.com/v2/YOUR-ALCHEMY-KEY or https://sepolia.infura.io/v3/YOUR-INFURA-KEY
- Chain ID: 11155111
- Currency Symbol: ETH
- Block Explorer URL: https://sepolia.etherscan.io
-
Get testnet ETH from a Sepolia faucet
-
Deploy contracts to Sepolia with auto-config:
npx hardhat run scripts/1_deploy_sepolia.js --network sepolia
This script will automatically update your config.json with the new contract addresses.
-
Seed the exchange with limited test data (optimized for testnets):
npx hardhat run scripts/2_seed_sepolia.js --network sepolia
This script uses longer delays between transactions to avoid rate limiting.
In the project directory, you can run:
Runs the React app in development mode at http://localhost:3000.
Starts a local Ethereum blockchain for development and testing.
Deploys the smart contracts to the local blockchain.
Seeds the exchange with test data (transfers tokens, creates orders, etc.).
Runs the contract tests.
Builds the app for production to the build
folder.
-
/contracts
: Solidity smart contractsToken.sol
: ERC-20 token implementationExchange.sol
: DEX contract for trading tokens
-
/scripts
: Deployment and setup scripts1_deploy.js
: Deploys the contracts2_seed_exchange.js
: Seeds the exchange with test data
-
/src
: Frontend React application/components
: React components/store
: Redux state management/abis
: Contract ABIs (Application Binary Interfaces)
If you encounter issues connecting MetaMask to your local Hardhat node:
- Ensure Hardhat is running with
npx hardhat node
- Verify MetaMask network settings (Chain ID: 31337)
- Reset your account in MetaMask (Settings > Advanced > Reset Account)
- Make sure you've imported the correct account private key
If you encounter errors when interacting with the contracts:
- Check that the contract addresses in
src/config.json
match the deployed addresses - Verify that you've properly seeded the exchange
- Ensure MetaMask is connected to the right network and has sufficient ETH
- Restart the Hardhat node and redeploy if necessary
When using public testnets like Sepolia, you might encounter API rate limiting:
-
Rate Limit Errors (429, 403):
- The application uses fallback providers with Alchemy as the primary provider (80% of requests)
- If you encounter rate limit errors, ensure your
.env
file has valid API keys for both Alchemy and Infura - Consider upgrading to a paid Alchemy plan if you need higher rate limits
-
Slow Loading of Events:
- The application fetches blockchain events in chunks to avoid hitting rate limits
- If data is loading slowly or partially, it may be due to rate limiting
- Check the browser console for event loading status and errors
-
Using Multiple RPC Providers:
- The app automatically falls back between Alchemy and Infura
- You can modify the provider preferences in
src/store/interactions.js
if needed
-
Optimizing for Testnets:
- We use network-specific chunk sizes (smaller for testnets, larger for local)
- Use the Sepolia-specific deployment and seeding scripts for testnet interactions
- The optimized scripts include:
- Longer delays between transactions
- Fewer test orders to reduce RPC calls
- Auto-updating config.json
- Network validation checks
-
Balance Loading Optimizations:
- Balance loading is now done in parallel using Promise.all
- There's a deliberate delay after transfers complete before refreshing balances
- These changes significantly reduce the number of concurrent RPC calls