First off, thank you for considering contributing to ApexChainx! It's people like you that make ApexChainx such a great tool for service operators managing SLA compliance and outage resolution.
ApexChainx is part of the Stellar Wave Program! If you're here from the Wave:
- Browse Issues: Look for issues tagged with
Stellar Wave - Apply to Work: Comment on the issue you want to work on
- Get Assigned: Wait for a maintainer to assign you
- Submit PR: Create a pull request when ready
Important: Only one contributor per issue. First to apply and get assigned gets the work.
There are many ways to contribute to ApexChainx:
- Report bugs and issues
- Suggest new features or enhancements
- Fix bugs and implement features
- Improve documentation
- Write tests to increase coverage
- Review pull requests
- Help answer questions in discussions
For Frontend (apexchainx-fe):
- Node.js 18.x or higher
- npm or yarn
- Git
- Freighter wallet (for Stellar features)
For Backend (apexchainx-be):
- Python 3.11 or higher
- pip and virtualenv
- Git
For Smart Contracts (apexchainx-contracts):
- Rust and Cargo
- Soroban CLI
- Stellar CLI
The fastest way to contribute is via GitHub Codespaces. A pre-configured dev container starts a Python 3.11 environment with PostgreSQL 15 and Redis 7 already running. You can be ready to run tests in under 60 seconds.
- Fork the repository on GitHub (click the Fork button on the repo page).
- On your fork, click Code → Codespaces → Create codespace on main.
GitHub will build the container using.devcontainer/devcontainer.json.
The postCreateCommand runs automatically:
pip install -e .
# waits for Postgres to be ready, then:
alembic upgrade headYou will see a ✅ in the terminal when it is done.
make welcomeThis installs all dev dependencies, verifies the app imports cleanly, and runs the full test suite. A clean run confirms your environment is working end-to-end.
# Sync with upstream first
git fetch upstream
git checkout -b fix/your-issue-description upstream/main| Task | Command |
|---|---|
| Install/refresh deps | pip install -e ".[dev]" |
| Run linter | make lint |
| Run type checker | make typecheck |
| Run tests | make test |
| Run all quality gates | make ci |
| Start the API | uvicorn app.main:app --reload |
| Apply migrations | make migrate |
Port 8000 is forwarded automatically — the Swagger UI is available at the Ports tab.
- Fork the repository on GitHub
- Clone your fork locally:
git clone https://github.com/YOUR_USERNAME/apexchainx-fe.git # or git clone https://github.com/YOUR_USERNAME/apexchainx-be.git # or git clone https://github.com/YOUR_USERNAME/apexchainx-contracts.git
- Add upstream remote:
git remote add upstream https://github.com/ApexChainx/ApexChainx-Backend.git
Frontend:
cd apexchainx-fe
npm install
cp .env.example .env.local
# Edit .env.local with your config
npm run devBackend:
cd apexchainx-be
python3 -m venv .venv
source .venv/bin/activate
# On Windows: .venv\Scripts\Activate.ps1
pip install -r requirements.txt
cp .env.example .env
# Edit .env — never commit it
# Edit .env with your config
alembic upgrade head
uvicorn app.main:app --reloadThis project uses ruff for fast linting and formatting.
pip install pre-commit
pre-commit installNow ruff check --fix and ruff format run automatically on every commit.
Smart Contracts:
cd apexchainx-contracts
# Install Soroban CLI if you haven't
cargo install --locked soroban-cli
# Build contracts
make build
# Run tests
make testAlways create a new branch for your work:
git checkout -b feature/wallet-integration
# or
git checkout -b fix/payment-bug
# or
git checkout -b docs/stellar-guideBranch naming convention:
feature/description- New featuresfix/description- Bug fixesdocs/description- Documentationtest/description- Adding testsrefactor/description- Code refactoring
- Write clean, readable code
- Follow the project's code style (see below)
- Add tests for new functionality
- Update documentation as needed
- Keep commits focused and atomic
Frontend:
npm run test
npm run lint
npm run type-checkBackend:
pytest
pytest -v
pytest --cov=app --cov-report=html
ruff check app/ # lint (replaces flake8)
ruff format app/ # format (replaces black)
mypy app/ # type-check
python scripts/lint_migrations.py # migration raw-SQL lintSmart Contracts:
cargo test
cargo clippy -- -D warningsWe follow Conventional Commits:
git commit -m "feat: add wallet balance display"
git commit -m "fix: resolve payment timeout issue"
git commit -m "docs: update stellar integration guide"
git commit -m "test: add unit tests for SLA calculator"Commit message format:
<type>: <description>
[optional body]
[optional footer]
Types:
Scope is optional but encouraged: feat(sla): add bulk recompute endpoint
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting, semicolons, etc.)refactor: Code refactoring without behaviour changetest: Adding or updating testschore: Maintenance tasksperf: Performance improvementsci: CI/CD configuration changes
git push origin feature/wallet-integrationThen open a pull request on GitHub with:
- Clear title following conventional commit format (keep under 70 characters)
- Description of what you changed and why
- Screenshots (for UI changes)
- Testing notes (how you tested the changes)
- Related issue:
Closes #123orFixes #456
- Use TypeScript for all new files
- Follow React hooks best practices
- Use functional components over class components
- Use Tailwind CSS for styling (no inline styles)
- Use shadcn/ui components when available
- Extract reusable logic into custom hooks
- PropTypes or TypeScript interfaces for all components
Example:
import { useState } from 'react';
import { Button } from '@/components/ui/button';
interface WalletConnectProps {
onConnect: (publicKey: string) => void;
}
export function WalletConnect({ onConnect }: WalletConnectProps) {
const [connected, setConnected] = useState(false);
// Component logic here
return (
<Button onClick={handleConnect}>
{connected ? 'Disconnect' : 'Connect Wallet'}
</Button>
);
}- Follow PEP 8 style guide
- Use type hints for all functions
- Write docstrings for all public functions
- Use async/await for I/O operations
- Pydantic models for request/response validation
- Dependency injection for services
- Environment variables for configuration
Example:
from fastapi import APIRouter, Depends, HTTPException
from app.models.payment import PaymentCreate, PaymentResponse
from app.services.stellar.payment_service import PaymentService
from app.api.deps import get_current_user
router = APIRouter()
@router.post("/payments", response_model=PaymentResponse)
async def create_payment(
payment: PaymentCreate,
current_user = Depends(get_current_user)
) -> PaymentResponse:
"""
Create a new payment transaction on Stellar network.
Args:
payment: Payment details including amount and destination
current_user: Currently authenticated user
Returns:
PaymentResponse with transaction hash and status
Raises:
HTTPException: If payment creation fails
"""
service = PaymentService()
result = await service.create_payment(payment)
return result- Follow Rust best practices
- Document all public functions
- Use proper error handling
- Test all functions thoroughly
- Keep gas costs in mind
- Use clippy for linting
Example:
#[contractimpl]
impl SLAContract {
/// Calculate SLA result for an outage
///
/// # Arguments
/// * `outage_id` - Unique identifier for the outage
/// * `severity` - Severity level (Critical, High, Medium, Low)
/// * `mttr_minutes` - Mean time to repair in minutes
///
/// # Returns
/// SLAResult containing status and payment information
pub fn calculate_sla(
env: Env,
outage_id: Symbol,
severity: Severity,
mttr_minutes: u32,
) -> SLAResult {
// Implementation here
}
}- Code follows the style guidelines
- Self-review completed
- Tests added/updated and passing
- Documentation updated
- No console.log or print statements
- Environment variables in .env.example
- Breaking changes clearly documented
## Description
Brief description of the changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Related Issue
Closes #123
## Testing
- [ ] Unit tests added/updated
- [ ] Integration tests added/updated
- [ ] Manual testing completed
## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Documentation updated
- [ ] Tests pass locally
## Screenshots (if applicable)
[Add screenshots here]
## Additional Notes
Any additional information for reviewersInclude in your PR description:
- Testnet transaction hashes (for blockchain features)
- Video/GIF of feature working (for UI changes)
- Performance metrics (if relevant)
- Time spent on the issue (optional)
# Run all tests
npm run test
# Run tests in watch mode
npm run test:watch
# Run with coverage
npm run test:coverageTest structure:
import { render, screen, fireEvent } from '@testing-library/react';
import { WalletConnect } from './WalletConnect';
describe('WalletConnect', () => {
it('should connect to Freighter wallet', async () => {
render(<WalletConnect onConnect={jest.fn()} />);
const button = screen.getByText('Connect Wallet');
fireEvent.click(button);
// Assertions here
});
});# Run all tests
pytest
# Run specific test file
pytest tests/test_payment_service.py
# Run with coverage
pytest --cov=app --cov-report=htmlTest structure:
import pytest
from app.services.stellar.payment_service import PaymentService
@pytest.mark.asyncio
async def test_create_payment():
"""Test payment creation on Stellar network"""
service = PaymentService(network="testnet")
result = await service.create_payment(
source_secret="S...",
destination="G...",
amount="10.00"
)
assert result["status"] == "success"
assert "tx_hash" in result# Run tests
cargo test
# Run with output
cargo test -- --nocapture- Use clear, concise language
- Include code examples
- Add screenshots for UI features
- Keep up-to-date with code changes
- Link to related docs where helpful
- Use Markdown for formatting
CRITICAL: Security is everyone's responsibility. Follow these guidelines strictly.
- Never commit secrets (API keys, private keys, passwords, tokens) to version control
- Use environment variables or a secrets manager (AWS Secrets Manager, HashiCorp Vault) for sensitive data
- Never log secrets or include them in error messages, stack traces, or documentation
- Use separate secrets for each environment (dev/staging/prod)
- Rotate secrets regularly and immediately after any suspected compromise
- Always use bcrypt for password hashing (never plaintext or weak hashes)
- Implement rate limiting on auth endpoints to prevent brute force attacks
- Use token rotation for refresh tokens to detect replay attacks
- Follow the principle of least privilege for all API endpoints
- Validate role-based access on every protected endpoint
- Validate all inputs using Pydantic models with strict type checking
- Enforce payload size limits to prevent abuse (see MAX_REQUEST_BODY_SIZE_BYTES)
- Sanitize user inputs before storage or processing
- Use parameterized queries for database operations (SQLAlchemy handles this)
- Implement CORS policies that restrict allowed origins
- NEVER expose Stellar secret keys (starting with 'S') in code, logs, or docs
- Only use public keys (starting with 'G') for wallet linking and balance queries
- Separate testnet and mainnet keys - never reuse across environments
- Use hardware security modules (HSM) or secure enclaves for production key storage
- Implement transaction validation before submission (amount, destination, asset type)
- Always verify webhook signatures using HMAC-SHA256 before processing
- Implement idempotency to prevent duplicate webhook processing
- Use HTTPS for all webhook endpoints
- Validate webhook payload structure before acting on events
- Never log sensitive data (passwords, tokens, secret keys)
- Include actor attribution (user ID/email) in all audit events
- Add correlation IDs to track requests across services
- Audit logs are immutable - never modify or delete audit entries
- Redact sensitive fields automatically using the audit service's sanitization logic
Before approving any PR, verify:
- No secrets or credentials in code or comments
- All user inputs are validated and sanitized
- Auth checks are present on protected endpoints
- Error messages don't leak sensitive information
- Dependencies are up-to-date and free of known vulnerabilities
- Audit logging captures security-relevant events
Use the GitHub issue template and include:
- Clear title describing the bug
- Steps to reproduce the issue
- Expected behavior
- Actual behavior
- Screenshots (if applicable)
- Environment details (OS, browser, versions)
- Error messages (full stack trace if possible)
- For Stellar issues: Include network (testnet/mainnet) and transaction hash
Use the GitHub issue template and include:
- Clear title describing the feature
- Problem statement (what problem does this solve?)
- Proposed solution
- Alternative solutions considered
- Additional context (mockups, examples, etc.)
- GitHub Issues: For bugs and feature requests
- Discord: [Join our server] (link TBD)
- Stellar Discord: For Stellar-specific questions
By contributing to ApexChainx, you agree that your contributions will be licensed under the MIT License.
Your contributions make ApexChainx better for everyone. We appreciate your time and effort!
Happy coding! 🚀
- Do not push directly to
main— all changes must go through a PR - Do not commit
.envfiles — use.env.examplefor documentation - Do not add floating version ranges to
requirements.txt— pin exact versions - Do not put business logic in route handlers — it belongs in services
- Do not expose private keys via API responses or logs
- Do not skip tests — all PRs require passing test suite
When filing a bug report, include:
- Steps to reproduce — the exact sequence of actions
- Expected behaviour — what should have happened
- Actual behaviour — what actually happened
- Environment — Python version, OS, database version
- Logs — relevant error output (redact any secrets)
Before opening a feature request:
- Check existing issues to avoid duplicates
- Describe the problem the feature solves — not just the solution
- Consider the scope: does this belong in the backend, frontend, or contracts?
- Outline acceptance criteria — what does "done" look like?
- PRs are reviewed within 48 hours on business days
- Address all reviewer comments before requesting re-review
- Use
Resolve conversationonly after the concern is addressed, not to dismiss it - Breaking changes require explicit sign-off from a maintainer
PRs that only modify .md files do not require test coverage but must:
- Be factually accurate and consistent with the routed runtime
- Not introduce references to legacy module paths or old names
- Follow the same commit convention as code PRs
- New service functions must have at least one unit test
- New route handlers must have at least one integration test
- Bug fixes must include a regression test that would have caught the bug
- Tests must pass locally before opening a PR (
pytest tests/)
This project uses pyproject.toml for declaring dependencies with pip-tools for lock file generation.
make bootstrappip-compile pyproject.toml --generate-hashes > requirements.lockpip install -r requirements.lockWhen your PR requires a database change:
- Create a new migration file under
alembic/versions/with the next sequential number - Name the file descriptively:
NNNN_short_description.py - Include both
upgrade()anddowngrade()functions - Test the migration with
alembic upgrade headandalembic downgrade -1 - Include the migration in the same PR as the code that depends on it
Before submitting a PR, verify:
- No secrets, keys, or credentials in any committed file
- No private keys exposed via API responses or logs
- Input validation present on all new endpoints (Pydantic schemas)
- Authentication required on all protected routes
- No new floating dependency version ranges
-
.env.exampleupdated if new environment variables were added