A full-stack, real-time gas fee monitoring and analytics platform for Ethereum Layer 2 networks (Base, Optimism, Arbitrum). Monitor gas prices across multiple chains, track trends, and get intelligent recommendations for when and where to execute your transactions.
- Multi-Chain Monitoring: Real-time gas price tracking for Base, Optimism, and Arbitrum
- Smart Recommendations: Intelligent algorithm recommends the cheapest chain for your transactions
- Historical Analytics: 24h, 7d, and 30d gas price trends with statistical analysis
- REST API: Comprehensive API endpoints for programmatic access
- Real-time Dashboard: Beautiful React frontend with live price updates
- Persistent Storage: SQLite database for historical data and analytics
- Webhook Integration: Optional webhook notifications when prices drop below thresholds
- Automated Scheduling: GitHub Actions workflow for continuous monitoring
- Gas prices (base fees)
- Priority fees (tips)
- Statistical aggregates (min, max, average)
- Recommendation history
- Timestamp-based snapshots
gas-fee-optimizer/
βββ src/
β βββ gas-optimizer.js # Core gas fee fetcher & report generator
β βββ server.js # Express API server
β βββ database.js # SQLite operations
β βββ scheduler.js # Job scheduling
βββ client/ # React frontend dashboard
β βββ public/
β βββ src/
β β βββ App.js # Main dashboard component
β β βββ components/ # Reusable UI components
β βββ package.json
βββ config/
β βββ gas.config.json # Configuration & thresholds
βββ reports/ # JSON reports (auto-generated)
βββ data/ # SQLite database location
βββ .env.example # Environment template
βββ package.json # Dependencies
- Node.js 14+
- npm or yarn
- Ethereum RPC endpoints (free tier available from Alchemy, Infura, or Quicknode)
# Clone the repository
git clone https://github.com/yourusername/gas-fee-optimizer.git
cd gas-fee-optimizer
# Install root dependencies
npm install
# Install client dependencies
cd client && npm install && cd ..Copy .env.example to .env and fill in your RPC endpoints:
cp .env.example .envEdit .env:
# Required: Ethereum L2 RPC Endpoints
RPC_BASE=https://mainnet.base.org
RPC_OPTIMISM=https://mainnet.optimism.io
RPC_ARBITRUM=https://arb1.arbitrum.io/rpc
# Optional: Webhook URL for alerts
WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
# Server Configuration
API_PORT=5000
API_HOST=localhost
# Database
DATABASE_PATH=./data/gas-optimizer.db
# Polling
POLL_INTERVAL=5
HISTORY_RETENTION_DAYS=90npm startOutput:
{
"timestamp": "2025-09-28T12:00:00Z",
"best_chain": "optimism",
"recommendation": "Send your transactions on Optimism now for lowest fees.",
"chains": {
"base": {"gas_price_gwei": 12, "priority_fee_gwei": 1.2},
"optimism": {"gas_price_gwei": 6, "priority_fee_gwei": 0.8},
"arbitrum": {"gas_price_gwei": 9, "priority_fee_gwei": 1.0}
}
}# Terminal 1: Start API server
npm run server
# Terminal 2: Start React dashboard
npm run dev:clientOr run both together (requires concurrently):
npm run devAccess the dashboard at: http://localhost:3000
GET /api/currentResponse:
{
"base": {
"gas_price_gwei": 12.5,
"priority_fee_gwei": 1.2,
"timestamp": "2025-09-28T12:00:00Z"
},
"optimism": {
"gas_price_gwei": 6.3,
"priority_fee_gwei": 0.8,
"timestamp": "2025-09-28T12:00:00Z"
},
"arbitrum": {
"gas_price_gwei": 9.1,
"priority_fee_gwei": 1.0,
"timestamp": "2025-09-28T12:00:00Z"
}
}GET /api/chain/:name?limit=100Parameters:
:name- Chain name:base,optimism, orarbitrumlimit- Number of records (default: 100, max: 1000)
Response:
{
"chain": "optimism",
"data": [
{
"timestamp": "2025-09-28T12:00:00Z",
"gas_price_gwei": 6.3,
"priority_fee_gwei": 0.8
}
],
"count": 1
}GET /api/stats?hours=24Parameters:
hours- Time period for aggregation (default: 24)
Response:
{
"time_period_hours": 24,
"stats": {
"base": {
"avg_gas_price": 11.8,
"avg_priority_fee": 1.15,
"min_gas_price": 8.2,
"max_gas_price": 15.4,
"data_points": 288
},
"optimism": {...},
"arbitrum": {...}
}
}GET /api/recommendations?limit=50Response:
{
"recommendations": [
{
"timestamp": "2025-09-28T12:00:00Z",
"best_chain": "optimism",
"recommendation": "Send your transactions on Optimism now for lowest fees."
}
],
"count": 1
}GET /api/healthResponse:
{
"status": "healthy",
"server": {
"uptime": 1234.56,
"memory": {...}
},
"database": {
"total_gas_records": 1440,
"total_recommendations": 288,
"oldest_record": "2025-09-27T12:00:00Z"
}
}{
"chains": {
"base": {
"threshold_gwei": 15
},
"optimism": {
"threshold_gwei": 7
},
"arbitrum": {
"threshold_gwei": 10
}
},
"alert": {
"enabled": true,
"webhook": "${WEBHOOK_URL}"
}
}| Variable | Description | Default |
|---|---|---|
RPC_BASE |
Base RPC endpoint | Required |
RPC_OPTIMISM |
Optimism RPC endpoint | Required |
RPC_ARBITRUM |
Arbitrum RPC endpoint | Required |
WEBHOOK_URL |
Slack/Discord webhook URL | Optional |
API_PORT |
Server port | 5000 |
DATABASE_PATH |
SQLite database path | ./data/gas-optimizer.db |
POLL_INTERVAL |
Check interval (minutes) | 5 |
HISTORY_RETENTION_DAYS |
Data retention period | 90 |
- Current gas prices for all chains
- Priority fee estimates
- Last update timestamp
- 24-hour average prices
- Min/max price tracking
- Statistical data points
- Best chain for transactions
- Action recommendations
- Recommendation history table
- Configurable refresh intervals (10s, 30s, 1m, 5m)
- Manual refresh button
- Error handling and notifications
Create .github/workflows/gas-optimizer.yml:
name: Gas Fee Optimizer
on:
schedule:
- cron: '*/5 * * * *' # Every 5 minutes
workflow_dispatch:
jobs:
check-gas:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Run gas optimizer
env:
RPC_BASE: ${{ secrets.RPC_BASE }}
RPC_OPTIMISM: ${{ secrets.RPC_OPTIMISM }}
RPC_ARBITRUM: ${{ secrets.RPC_ARBITRUM }}
WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }}
run: npm start
- name: Commit reports
run: |
git add reports/
git commit -m "Add gas fee reports" || true
git push# Start core optimizer (single run)
npm start
# Start API server (watch mode)
npm run dev:server
# Start React frontend (development)
npm run dev:client
# Run both server & client
npm run dev
# Build React app for production
npm run build
# Schedule monitoring via node-schedule
npm run schedule
# Run tests
npm run testsrc/
βββ gas-optimizer.js # Main script - fetches gas data
βββ server.js # Express API server
βββ database.js # SQLite database module
βββ scheduler.js # Job scheduling
client/
βββ public/ # Static assets
βββ src/
β βββ App.js # Main React component
β βββ index.js # React entry point
β βββ index.css # Tailwind CSS
β βββ components/
β βββ GasPriceCard.js
β βββ AnalyticsChart.js
β βββ RecommendationPanel.js
βββ package.json
const axios = require('axios');
// Get current prices
async function getCurrentPrices() {
const response = await axios.get('http://localhost:5000/api/current');
console.log(response.data);
}
// Get 24h statistics
async function getStats() {
const response = await axios.get('http://localhost:5000/api/stats?hours=24');
console.log(response.data);
}
// Find best chain for transactions
async function findBestChain() {
const response = await axios.get('http://localhost:5000/api/recommendations?limit=1');
const latest = response.data.recommendations[0];
console.log(`Best chain: ${latest.best_chain}`);
}import requests
# Get current prices
response = requests.get('http://localhost:5000/api/current')
data = response.json()
for chain, prices in data.items():
print(f"{chain}: {prices['gas_price_gwei']} Gwei")# Get current prices
curl http://localhost:5000/api/current
# Get chain history (last 50 records)
curl "http://localhost:5000/api/chain/optimism?limit=50"
# Get stats
curl "http://localhost:5000/api/stats?hours=24"WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URLWEBHOOK_URL=https://discord.com/api/webhooks/YOUR/WEBHOOK/URL- ethers.js - Ethereum interaction
- express - Web server
- axios - HTTP client
- better-sqlite3 - Database
- node-schedule - Job scheduling
- cors - Cross-origin support
- dotenv - Environment variables
- React 18 - UI framework
- Tailwind CSS - Styling
- Axios - API calls
- Chart.js - Data visualization
# Run test suite
npm run test
# Run with coverage
npm run test:coverage
# Watch mode
npm run test:watchSolution: Run the core optimizer first to populate the database:
npm startSolution: Check if another instance is running:
ps aux | grep node
# Kill processes if needed: kill -9 <PID>Solution: Verify endpoints in .env:
curl https://mainnet.base.org -X POST -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":1}'Solution: Change port in .env:
API_PORT=5001FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY src ./src
COPY config ./config
ENV NODE_ENV=production
EXPOSE 5000
CMD ["npm", "run", "server"]cd client
npm run build
# Deploy the build/ folder to Vercel# Create Heroku app
heroku create gas-fee-optimizer
# Set environment variables
heroku config:set RPC_BASE="..." RPC_OPTIMISM="..." RPC_ARBITRUM="..."
# Deploy
git push heroku maingas_history table:
- id (INTEGER PRIMARY KEY)
- timestamp (TEXT)
- chain (TEXT)
- gas_price_gwei (REAL)
- priority_fee_gwei (REAL)
- created_at (DATETIME)recommendations table:
- id (INTEGER PRIMARY KEY)
- timestamp (TEXT UNIQUE)
- best_chain (TEXT)
- recommendation (TEXT)
- created_at (DATETIME)- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open a Pull Request
MIT License - see LICENSE file for details
If this project helps you, please star β it!
For questions or suggestions, open an issue on GitHub.
Last Updated: September 2025
Version: 1.0.0
Status: Active Development β