Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,76 @@ jobs:
if [ "$BUILD_RAN" = "false" ]; then
echo "No build script found. Skipping build step."
fi

e2e-tests:
name: E2E Tests
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: gasguard_test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
redis:
image: redis:7-alpine
ports:
- 6379:6379
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install pnpm
uses: pnpm/action-setup@v2
with:
version: 8

- name: Install dependencies
run: |
if [ -f "pnpm-lock.yaml" ]; then
pnpm install --frozen-lockfile
else
echo "No pnpm-lock.yaml found."
exit 1
fi

- name: Check for E2E test directory
id: check-e2e
run: |
if [ -d "apps/api-service/test/e2e" ]; then
echo "exists=true" >> $GITHUB_OUTPUT
echo "E2E test directory found"
else
echo "exists=false" >> $GITHUB_OUTPUT
echo "E2E test directory not found"
fi

- name: Run E2E tests
if: steps.check-e2e.outputs.exists == 'true'
run: |
cd apps/api-service
pnpm run test:e2e
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/gasguard_test
REDIS_URL: redis://localhost:6379
NODE_ENV: test

- name: Upload test results
if: always() && steps.check-e2e.outputs.exists == 'true'
uses: actions/upload-artifact@v4
with:
name: e2e-test-results
path: apps/api-service/test-results/
if-no-files-found: ignore
95 changes: 89 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@ As Web3 scales, transaction costs remain a significant barrier to entry.
```text
GasGuard/
├── apps/
│ └── api/ # Nest.js backend handling remote scan requests
│ ├── api/ # Nest.js backend handling remote scan requests
│ └── api-service/ # Enhanced API service with database and E2E testing
├── libs/
│ └── engine/ # Core logic for parsing Rust, Solidity, and Vyper
│ └── engine/ # Core logic for parsing Rust, Solidity, and Vyper
├── packages/
│ └── rules/ # Library of optimization rules and logic
├── .gitignore # Optimized for Node.js and Rust
└── LICENSE # MIT Licensed
│ └── rules/ # Library of optimization rules and logic
├── .gitignore # Optimized for Node.js and Rust
└── LICENSE # MIT Licensed
```

---
Expand All @@ -71,7 +72,7 @@ npm run start
```

The API will be available at `http://localhost:3000`.
=======

## 🔌 API Versioning

The GasGuard API uses **NestJS built-in versioning** with URI-based versioning strategy. All endpoints require a version prefix.
Expand Down Expand Up @@ -122,3 +123,85 @@ app.enableVersioning({
```

This ensures all API consumers explicitly specify the version, making the API future-proof for version migrations.

## 🧪 End-to-End Testing

GasGuard includes comprehensive end-to-end testing to ensure reliable gasless transaction flows across all services.

### E2E Test Framework

- **Framework:** Jest with Supertest for API testing
- **Blockchain:** Hardhat local network for contract interactions
- **Services:** Dockerized PostgreSQL, Redis, and mock RPC providers
- **Coverage:** Full gasless transaction workflows and failure scenarios

### Running E2E Tests

```bash
# Install dependencies
pnpm install

# Start test environment
docker-compose -f apps/api-service/docker-compose.e2e.yml up -d

# Run E2E tests
cd apps/api-service
pnpm run test:e2e

# Or run from root
pnpm run test:e2e
```

### Test Structure

```
apps/api-service/test/
├── e2e/ # E2E test suites
│ ├── basic-api.e2e-spec.ts
│ ├── gasless-transaction.e2e-spec.ts
│ ├── failure-scenarios.e2e-spec.ts
│ └── contract-interaction.e2e-spec.ts
├── utils/ # Test utilities
│ ├── test-helpers.ts
│ └── blockchain-setup.ts
└── fixtures/ # Test data fixtures
```

For detailed information, see:
- [E2E Testing Documentation](./docs/E2E_TESTING.md)
- [E2E Quick Start Guide](./docs/E2E_QUICKSTART.md)

## 🚀 Getting Started

### Prerequisites

- Node.js 18+
- Docker & Docker Compose
- pnpm package manager
- Rust toolchain (for core engine)

### Installation

```bash
# Clone the repository
git clone https://github.com/your-username/GasGuard.git
cd GasGuard

# Install dependencies
pnpm install

# Run tests
pnpm run test

# Start the API
cd apps/api
npm run start:dev
```

## 🤝 Contributing

We welcome contributions! Please see our [contributing guidelines](CONTRIBUTING.md) for more details.

## 📄 License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
22 changes: 22 additions & 0 deletions apps/api-service/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Database Configuration
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USERNAME=postgres
DATABASE_PASSWORD=postgres
DATABASE_NAME=gasguard
DATABASE_SYNCHRONIZE=false
DATABASE_LOGGING=false
DATABASE_SSL=false
DATABASE_MAX_QUERY_TIME=1000
DATABASE_MAX_CONNECTIONS=10
DATABASE_MIN_CONNECTIONS=1
DATABASE_CONNECTION_TIMEOUT=30000
DATABASE_IDLE_TIMEOUT=10000

# Application Configuration
PORT=3000
NODE_ENV=development

# Analytics Configuration
ANALYTICS_ENABLED=true
ANALYTICS_RETENTION_DAYS=90
23 changes: 23 additions & 0 deletions apps/api-service/Dockerfile.e2e
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM node:18-alpine

WORKDIR /app

# Copy package files
COPY package*.json ./
COPY tsconfig*.json ./

# Install dependencies
RUN npm ci --only=production

# Copy source code
COPY src/ ./src/
COPY test/ ./test/

# Build the application
RUN npm run build

# Expose port
EXPOSE 3000

# Start the application
CMD ["npm", "run", "start:prod"]
72 changes: 72 additions & 0 deletions apps/api-service/docker-compose.e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
version: '3.8'

services:
# PostgreSQL database for testing
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: gasguard_test
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- "5433:5432"
volumes:
- postgres_data_test:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5

# Redis for queue testing
redis:
image: redis:7-alpine
ports:
- "6380:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5

# Hardhat node for blockchain testing
hardhat:
image: node:18-alpine
working_dir: /app
volumes:
- .:/app
command: sh -c "npm install && npx hardhat node"
ports:
- "8546:8545"
depends_on:
- postgres
- redis

# GasGuard API service
gasguard-api:
build:
context: .
dockerfile: Dockerfile.e2e
environment:
- DATABASE_HOST=postgres
- DATABASE_PORT=5432
- DATABASE_USERNAME=postgres
- DATABASE_PASSWORD=postgres
- DATABASE_NAME=gasguard_test
- DATABASE_SYNCHRONIZE=true
- REDIS_HOST=redis
- REDIS_PORT=6379
- BLOCKCHAIN_RPC_URL=http://hardhat:8545
- NODE_ENV=test
ports:
- "3001:3000"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
hardhat:
condition: service_started

volumes:
postgres_data_test:
36 changes: 36 additions & 0 deletions apps/api-service/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";

const config: HardhatUserConfig = {
solidity: {
version: "0.8.20",
settings: {
optimizer: {
enabled: true,
runs: 1000,
},
},
},
networks: {
hardhat: {
chainId: 1337,
mining: {
auto: true,
interval: 1000
},
accounts: {
count: 20,
accountsBalance: "10000000000000000000000" // 10,000 ETH
}
},
localhost: {
url: "http://127.0.0.1:8545",
chainId: 1337
}
},
mocha: {
timeout: 40000
}
};

export default config;
15 changes: 15 additions & 0 deletions apps/api-service/ormconfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { DataSource } from 'typeorm';

export default new DataSource({
type: 'postgres',
host: process.env.DATABASE_HOST || 'localhost',
port: parseInt(process.env.DATABASE_PORT || '5432', 10),
username: process.env.DATABASE_USERNAME || 'postgres',
password: process.env.DATABASE_PASSWORD || 'postgres',
database: process.env.DATABASE_NAME || 'gasguard',
synchronize: false,
logging: process.env.DATABASE_LOGGING === 'true',
entities: ['src/database/entities/**/*.entity{.ts,.js}'],
migrations: ['src/database/migrations/**/*{.ts,.js}'],
subscribers: ['src/database/subscribers/**/*{.ts,.js}'],
});
Loading