| slug | /contributing/style-guide |
|---|---|
| title | Code Style Guidelines |
| description | Coding standards, formatting guidelines, and linting rules for SoroScan's backend, frontend, contracts, and SDKs. |
| sidebar_label | Style Guide |
| hide_title | false |
SoroScan is a multi-language project (Python, TypeScript, Rust, CSS, SQL). To keep our codebase clean, maintainable, and readable, all contributors must adhere to the style guidelines detailed below.
SoroScan's backend is built using Django and Python 3.12+.
- Formatter: We use black with default settings (88 characters line limit).
- Linter: We use ruff for linting and import sorting.
- Run checks before committing:
cd django-backend black --check . ruff check .
- All new code must contain explicit type hints for function signatures and class definitions.
- Use built-in types for collections (e.g.,
list[str],dict[str, int]) rather than imports fromtypingwhere possible. - Example:
def fetch_contract_events( contract_id: str, limit: int = 100, offset: int = 0 ) -> list[dict[str, any]]: """Fetches events for a given contract ID with pagination.""" ...
- Explicit Imports: Do not use wildcard imports (
from module import *). - Docstrings: Include Google-style docstrings for public classes, methods, and functions.
- Django ORM: Use
select_relatedandprefetch_relatedto avoid N+1 queries.
SoroScan's frontend is a Next.js application, and we maintain a TypeScript SDK.
- Formatter: We use Prettier for layout style.
- Linter: We use ESLint configured with Next.js standards.
- Run checks before committing:
cd soroscan-frontend pnpm lint
- Avoid
any: The use ofanyis strictly prohibited unless parsing raw blockchain payloads. Useunknownor define interface types/discriminated unions instead. - Strict Null Checks: Explicitly handle
nullorundefinedconditions using optional chaining (?.) or nullish coalescing (??). - Example:
interface EventRowProps { eventId: string; contractAddress: string; timestamp: number; payload?: string; // Optional field } export const EventRow = ({ eventId, contractAddress, timestamp, payload }: EventRowProps): JSX.Element => { const displayPayload = payload ?? 'No details provided'; return ( <div className="flex justify-between items-center py-2"> <span>{eventId}</span> <span>{displayPayload}</span> </div> ); };
SoroScan's blockchain components are written in Rust for Soroban event emission.
- Formatter: We use standard
rustfmt. Runcargo fmtto auto-format. - Linter: We use
clippy. All warnings must be resolved before merging. - Run checks before committing:
cd soroban-contracts/soroscan_core cargo fmt --check cargo clippy -- -D warnings
- Error Handling: Do not use
unwrap()orexpect()in library/contract code. Propagate errors viaResult<T, E>. - Panics: Smart contracts should fail safely and emit diagnostic events rather than panicking, which consumes gas.
- Safety: Mark unsafe operations explicitly and include comments explaining the invariant validation.
SoroScan utilizes Tailwind CSS for styling the React interface.
- Ordering: Organize classes logically by layout first, then sizing, spacing, typography, and finally effects/states.
- Layout:
position,display,flex/grid properties(e.g.,absolute top-0 flex items-center) - Box Model:
width,height,margin,padding(e.g.,w-full max-w-md mx-auto p-4) - Typography:
font-family,size,weight,color(e.g.,font-mono text-sm font-semibold text-emerald-400) - Visuals:
background,border,rounded(e.g.,bg-zinc-900 border border-zinc-800 rounded-lg) - States & Transitions:
hover,focus,transition(e.g.,hover:bg-zinc-800 transition duration-150)
- Layout:
// Correct
<button className="flex items-center w-full p-3 font-mono text-sm bg-zinc-900 border border-zinc-800 rounded hover:bg-zinc-800 transition duration-150">
Refresh Ledger
</button>- Avoid creating custom CSS files for simple layouts.
- If you need a complex animation or custom style that cannot be cleanly written in Tailwind, add it to
soroscan-docs/src/css/custom.css(orsoroscan-frontend/app/globals.css) using CSS variables.
SQL script templates and raw queries in Django (cursor.execute()) must follow these standards.
- Keywords: Write SQL keywords in UPPERCASE (e.g.,
SELECT,FROM,WHERE,JOIN,ON,GROUP BY,ORDER BY). - Identifiers: Write table names, column names, and schemas in lowercase snake_case (e.g.,
ingest_event,contract_id). - Indentation: Format multi-line queries for readability.
- Parameterized Queries: Never concatenate inputs directly into raw SQL. Always use query parameters to prevent SQL injection.
SELECT
event_type,
COUNT(id) AS event_count
FROM
ingest_event
WHERE
contract_id = %s
AND status = 'SUCCESS'
GROUP BY
event_type
ORDER BY
event_count DESC;