Welcome to the MB project which is a sample project written in Python with FastAPI!
This project was created to demonstrate my knowledge of Python, FastAPI, and Clean Architecture.
This document will help you understand the project structure and get started quickly.
# First time setup
make setup
# Copy .env.example to .env and edit it with your configuration
cp .env.example .env
# Start the application environment with Docker Compose
make up/buildOpen a new browser tab and navigate to http://localhost:8000/docs or http://localhost:8000/redoc to see the API documentation.
.
βββ app/ # Source code directory
β βββ data/ # Data layer
β βββ domain/ # Domain layer
β βββ presentation/ # Presentation layer
β βββ utils/ # Utility functions
β βββ main.py # Application entry point
βββ test/ # Test files
β βββ integration/ # Integration tests
β βββ unit/ # Unit tests
β βββ conftest.py # Test configuration file
βββ .dockerignore # Docker ignore file
βββ .env.example # Environment variables example to be copied as .env locally
βββ Dockerfile # Dockerfile for building the Docker image
βββ main.py # Application entry point
βββ Makefile # Makefile with multiple useful commands
βββ README.md # This file
βββ requirements-dev.in # Development dependencies input file for pip-tools
βββ requirements-dev.txt # Development dependencies output file for pip-tools
βββ requirements.in # Production dependencies input file for pip-tools
βββ requirements.txt # Production dependencies output file for pip-tools
- Python 3.8 or later
- pip3 (Python package installer)
- Docker and Docker Compose
- Make (for using Makefile commands)
- Clone the repository:
git clone [email protected]:0xfbravo/mb.git
cd mb- Set up the development environment:
make setup- Set up environment variables:
cp .env.example .env
# Edit .env with your configuration- Install the package in development mode:
make install- Run the development server:
make runThis application is configured to work with any EVM compatible blockchain.
By default, the application is configured to work with the TEST network.
So if you want to use, for example, the ETHEREUM_SEPOLIA network, you need to change the selected network in the config.yaml file to ETHEREUM_SEPOLIA.
Also you can configure the assets and networks in the config.yaml file, you just need to add the asset and network you want to use.
assets:
USDT:
native: false
ETHEREUM: "0xdac17f958d2ee523a2206206994597c13d831ec7"
ARBITRUM: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9"
BASE: "0xfde4c96c8593536e31f229ea8f37b2ada2699bb2" # Bridged USDT
# ETHEREUM_SEPOLIA: "0x0000000000000000000000000000000000000000" # Unable to find official contract address
# ARBITRUM_SEPOLIA: "0x0000000000000000000000000000000000000000" # Unable to find official contract address
# BASE_SEPOLIA: "0x0000000000000000000000000000000000000000" # Unable to find official contract addressThe project follows Clean Architecture principles with clear separation of concerns:
-
Presentation (
app/presentation)- Implements REST API endpoints (e.g.
app/presentation/api/) - Handles request/response transformation
- Calls domain layers to perform business logic
- Can interact with user's input and output in multiple ways (e.g. CLI, HTTP, etc.)
- Implements REST API endpoints (e.g.
-
Data (
app/data/)- Handles external dependencies like database, cache, and external service integrations (e.g.
app/data/evm/) - Implements data access interfaces
- Handles external dependencies like database, cache, and external service integrations (e.g.
-
Domain (
app/domain/)- Defines data models and entities split into sub-folders (e.g.
app/domain/wallet/) - Contains domain-specific logic
- Independent of infrastructure concerns, exclusively responsible for business logic
- Defines data models and entities split into sub-folders (e.g.
The application uses PostgreSQL with Tortoise ORM for database operations and connection pooling.
The database connection pool is managed by Tortoise ORM and can be configured using environment variables:
# Database connection settings
POSTGRES_DB=your_database_name
POSTGRES_USER=your_username
POSTGRES_PASSWORD=your_password
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
# Connection pool settings (optional)
DB_POOL_MIN_SIZE=1 # Minimum number of connections in the pool
DB_POOL_MAX_SIZE=10 # Maximum number of connections in the pool
DB_POOL_MAX_IDLE=300 # Maximum time (seconds) a connection can be idle
DB_POOL_TIMEOUT=30 # Timeout (seconds) for getting a connection from the poolRun all tests:
make testRun unit tests only:
make test/unitRun integration tests:
make test/integrationRun tests with coverage:
make test/allGenerate coverage report:
make coverage-
Creating a New Feature
- Create a new branch from
main - Follow the domain-driven structure
- Add tests for new functionality
- Submit a pull request
- Create a new branch from
-
Code Style
- Follow PEP 8 guidelines
- Use
blackandisortfor code formatting - Use
flake8andmypyfor code quality
-
Documentation
- Document all public APIs
- Update README when adding new features
- Add docstrings for functions and classes
make setup # Setup development environment (venv, tools, dependencies)
make build # Build the Python package
make install # Install the package in development mode
make clean # Clean build artifacts and cache files
make test # Run all tests (unit and integration)
make test/unit # Run unit tests only
make test/integration # Run integration tests
make test/all # Run all tests with coverage
make coverage # Generate test coverage report
make lint # Run linter (flake8 and mypy)
make fmt # Format code with black and isort
make deps # Install dependencies
make deps/update # Update dependencies
make deps/compile # Compile requirements files
make security # Run security checks
make run # Run the application
make run/dev # Run with auto-reload
make mocks # Mock generation infoAdd production dependencies to requirements.txt:
pip3 install package_name
pip3 freeze > requirements.txtAdd development dependencies to requirements-dev.txt:
pip3 install package_name
pip3 freeze > requirements-dev.txtFor better dependency management, use pip-tools:
make deps/compileEach service follows this pattern:
class ServiceImpl:
def __init__(self, repository: Repository, logger: Logger):
self.repository = repository
self.logger = logger
def execute(self, request: Request) -> Response:
# Business logic here
pass- Use custom exception classes
- Handle errors at appropriate layers
- Return meaningful error messages
- Use structured logging
- Include relevant context in logs
- Log at appropriate levels
- Test individual functions and methods
- Mock external dependencies
- Focus on business logic
- Test component interactions
- Use test databases
- Test API endpoints
- Aim for >80% coverage
- Focus on critical business logic
- Use
pytest-covfor coverage reporting
Run security checks:
make securityThis will:
- Check for known vulnerabilities in dependencies
- Scan for security issues in your code
- Provide recommendations for fixes
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Set up the development environment (
make setup) - Make your changes
- Run tests (
make test) - Format your code (
make fmt) - Run linting (
make lint) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Create a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
For support, please:
- Check the documentation
- Search existing issues
- Create a new issue if needed
The project uses GitHub Actions for:
- Running tests
- Linting and formatting checks
- Security scanning
- Building Docker images
- Deploying to environments
-
Code Organization
- Keep files focused and small
- Use meaningful names
- Follow Python idioms and PEP 8
-
Testing
- Write unit tests for business logic
- Include integration tests
- Maintain good test coverage
-
Documentation
- Keep documentation up to date
- Document complex algorithms
- Include examples in docstrings
-
Dependencies
- Pin dependency versions
- Use virtual environments
- Regularly update dependencies
-
Code Quality
- Use type hints
- Follow linting rules
- Format code consistently