diff --git a/.github/workflows/ci-contracts.yml b/.github/workflows/ci-contracts.yml index 5f4110e0..19aa45a2 100644 --- a/.github/workflows/ci-contracts.yml +++ b/.github/workflows/ci-contracts.yml @@ -22,7 +22,7 @@ env: jobs: cairofmt: - runs-on: ubuntu-24-04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v3 - uses: software-mansion/setup-scarb@v1 diff --git a/README.md b/README.md index 6f7dd7bc..6fc75b6c 100644 --- a/README.md +++ b/README.md @@ -1,324 +1,613 @@ +# PixeLAW Core + +
+ ![PixeLAW](https://pixelaw.github.io/book/images/PixeLAW.jpeg) -[![ci-contracts](https://github.com/pixelaw/core/actions/workflows/ci-contracts.yml/badge.svg)](https://github.com/pixelaw/core/actions/workflows/ci-contracts.yml) - - - - - - -[![discord](https://img.shields.io/badge/join-PixeLAW-green?logo=discord&logoColor=white)](https://t.co/jKDjNbFdZ5) - - -A game built on top of Dojo. See live example at . - -This repository includes core components and systems. For more details, please check [PixeLAW Book](https://pixelaw.github.io/book/index.html). - -## Concepts -- World : A Cartesian plane (2d grid), where every position represents a "Pixel" -- Pixel : One x/y Position, that has 6 primitive properties and one behavior template (App) -- App : A Pixel can have only one App that defines its behavior -- App2App : Interactions between Apps, where allowed -- Action : A specific behavior in the context of an App -- Queued Action : Action to be executed in the future, can be scheduled during an Action - -## App Core Behavior (for owner) -- register : Register the App in the World -- unregister : Remove the App from the World -- allow_app -- disallow_app - -## App Properties -- name -- permissions (bool hashmap of appname+property) - - -## Core Pixel Behavior -- **update_all** -- update_app -- update_color -- update_owner -- update_text -- update_alert -- update_timestamp - -## Pixel Properties (every Pixel has these) -- position (cannot be changed) -- app -- color -- owner -- text -- alert -- timestamp - - -## Default App -- paint (put_color , remove_color) - -## Checking Permissions -- Is calling Player the owner of the pixel -> they can do anything -- Is calling App allowed to update the Property? -- Problem - - If scheduled, the calling App is CoreActions - - How can we reliably check - -## Scheduling Actions -- Can schedule anything through the Core.ScheduleAction function (?) -- This stores a hash onchain that will be removed once executed -- Core.ProcessScheduleAction takes the calldata and - - checks if the hash exists - - checks if it's not too early -- Upside - - Onchain storage is minimized -- Problem - - - - - -## Snake -- properties - - direction - - head_position - - length? -- behavior - - spawn - - position - - color - - text - - direction - - - - move - - - - handle_next_pixel - - normal: - - head moves to next - - rollback last - - die - - iterate all pixels and rollback - - longer - - head moves to next - - shorter - - head moves to next - - rollback last 2 - - change_direction -## What if.. -### Future actions are 1 per Pixel? - -## Todo -- handle unregistered apps -- research feasibility of "hooks" -- Properly hook up process_queue so it is allowed to do player_id, but normal calls are not. - - - -## Snake moves onto a non-owned Paint Pixel -- action: snake_move -- check pixel that will be occupied - - call update_color on that pixel - - is PaintApp allowing update_color from Snake? - - - - -## Prerequisites - -- Rust - install [here](https://www.rust-lang.org/tools/install) -- Cairo language server - install [here](https://book.dojoengine.org/development/setup.html#3-setup-cairo-vscode-extension) -- Dojo - install [here](https://book.dojoengine.org/getting-started/quick-start.html) -- Scarb - install [here](https://docs.swmansion.com/scarb/download) -- NodeJS - install [here](https://nodejs.org/en/download) - -## Developing Locally - -### Step 1: Build the contracts - -```shell -make build +[![ci-contracts](https://github.com/pixelaw/core/actions/workflows/ci-contracts.yml/badge.svg)](https://github.com/pixelaw/core/actions/workflows/ci-contracts.yml) +[![Discord](https://img.shields.io/badge/join-PixeLAW-green?logo=discord&logoColor=white)](https://t.co/jKDjNbFdZ5) +[![Twitter Follow](https://img.shields.io/twitter/follow/0xpixelaw?style=social)](https://x.com/0xpixelaw) +[![GitHub Stars](https://img.shields.io/github/stars/pixelaw/core?style=social)](https://github.com/pixelaw/core) + +**The foundational smart contract framework for building interactive, composable pixel-based games on Starknet** + +[Documentation](https://pixelaw.github.io/book/index.html) โ€ข [Examples](../examples/) โ€ข [SDK](../pixelaw.js/) โ€ข [Frontend](../vanilla/) + +
+ +--- + +## What is PixeLAW Core? + +**PixeLAW Core** is the foundational smart contract layer of the PixeLAW ecosystem, built on **Starknet** using the **Dojo ECS framework**. It provides the primitives and infrastructure for creating interactive pixel-based autonomous worlds where multiple applications can coexist and interact on a shared 2D grid. + +Think of it as the "operating system" for pixel-based blockchain games. Core defines: +- **The Pixel World**: A 2D Cartesian plane where each position (x, y) represents a programmable pixel +- **App System**: Modular applications that define pixel behavior and game mechanics +- **Permission Framework**: Ownership rules and App2App interaction controls through hooks +- **Spatial Infrastructure**: Area management with R-Tree indexing for efficient queries +- **Temporal System**: Queue-based scheduling for time-delayed actions + +Whether you're building a simple painting app, a complex strategy game, or an emergent multi-app experience, PixeLAW Core provides the composable primitives to make it happenโ€”all on-chain, all verifiable, all interoperable. + +--- + +## Architecture + +PixeLAW Core sits at the heart of the ecosystem, providing the blockchain layer that everything else builds upon: + +```mermaid +graph TB + subgraph "Frontend Layer" + Vanilla[Vanilla Frontend
React Client] + end + + subgraph "SDK Layer" + SDK[pixelaw.js
TypeScript SDK] + end + + subgraph "Blockchain Layer - PixeLAW Core" + Core[Core Contracts
Actions & Models] + DefaultApps[Default Apps
Paint, Snake, Player, House] + Examples[Example Apps
Custom Games] + end + + subgraph "Infrastructure" + Katana[Katana
Starknet RPC Node] + Torii[Torii
Event Indexer] + end + + Vanilla --> SDK + SDK --> Core + DefaultApps -.implements.-> Core + Examples -.implements.-> Core + Core --> Katana + Katana --> Torii + Torii -.events.-> SDK + + style Core fill:#4a90e2,stroke:#2e5c8a,stroke-width:3px,color:#fff + style DefaultApps fill:#6aa84f,stroke:#45682f,stroke-width:2px,color:#fff +``` + +**Core provides**: +- Smart contract primitives (Pixel, Area, Queue, App Registry) +- Permission system with hooks for App2App interactions +- Default apps demonstrating core patterns +- Docker image with pre-initialized blockchain state + +**Everything else consumes**: +- Frontend (Vanilla) uses SDK to interact with Core +- SDK (pixelaw.js) abstracts Core interactions into TypeScript +- Example apps build on Core to create custom games + +--- + +## Key Concepts + +### ๐ŸŸฆ Pixel World +A 2D Cartesian plane (max 32,767 x 32,767) where every position is a **Pixel** with properties: +- **Position**: (x, y) coordinatesโ€”immutable and unique +- **App**: Contract address defining the pixel's behavior +- **Color**: RGBA value for visual representation +- **Owner**: Address with full control over the pixel +- **Text**: Arbitrary text data for labels or metadata +- **Alert**: Special notification flag +- **Timestamps**: Created, updated, and custom timestamps + +### ๐ŸŽฎ Apps +Smart contracts that define pixel behavior. Each pixel is managed by exactly one app. Apps can: +- Register with the Core registry +- Implement custom interaction logic +- Define permission rules via hooks +- Schedule future actions via the queue +- Interact with other apps through the permission system + +### ๐Ÿ”— App2App Interactions +The **Hook System** enables controlled interactions between apps: + +```cairo +fn on_pre_update( + pixel_update: PixelUpdate, + app_caller: ContractAddress, + player_caller: ContractAddress, +) -> Option +``` + +- **`on_pre_update`**: Called BEFORE a pixel updateโ€”can allow, deny, or modify +- **`on_post_update`**: Called AFTER a pixel updateโ€”for side effects and reactions + +This pattern allows complex emergent gameplay without modifying Core contracts. + +### ๐Ÿ“ Areas +Rectangular spatial regions with ownership and permissions, indexed by **R-Tree** for O(log n) queries: +- Define territories with custom rules +- Control access to pixel groups +- Efficiently query "what area contains this position?" + +### โฐ Queue System +Schedule actions for future execution with cryptographic integrity: +- Actions stored with timestamp and poseidon hash +- External bots/schedulers execute when ready +- Prevents tampering with queued data +- Enables time-based game mechanics (cooldowns, delayed effects) + +--- + +## Features + +### โœจ Default Apps Included + +PixeLAW Core ships with four default apps demonstrating core patterns: + +| App | Purpose | Key Functions | +|-----|---------|---------------| +| **Paint** | Basic pixel coloring and image rendering | `put_color`, `remove_color`, `put_fading_color` | +| **Snake** | Classic snake game with collision detection | `move`, `interact` (spawn) | +| **Player** | Player character representation | `interact` (move), `configure` (name/emoji) | +| **House** | Building and area management | `build`, `demolish` | + +### ๐Ÿงช Comprehensive Test Suite +- **33 passing tests** covering all core functionality +- Pixel CRUD operations and permission validation +- Area management and R-Tree spatial queries +- Queue scheduling and integrity checks +- Hook invocation and App2App interactions +- Testing utilities via `pixelaw_test_utils` package + +### ๐Ÿณ Production-Ready Docker Image +Multi-stage Docker build with: +- Pre-compiled contracts with Dojo 1.7.1 +- Katana RPC node (port 5050) +- Torii indexer (port 8080) +- Pre-initialized blockchain snapshot for instant startup +- PM2 process management for all services + +### ๐Ÿ”ง Developer-Friendly Tools +- `justfile` commands for common tasks +- `pixelaw_test_utils` package with testing helpers +- Comprehensive error messages with position tracking +- Modern Dojo 1.7.1 patterns and best practices + +--- + +## Version Compatibility + +| Component | Version | Notes | +|-----------|---------|-------| +| **PixeLAW Core** | `0.8.0-dev` | Current development version | +| **Dojo Framework** | `1.7.1` | ECS framework for blockchain games | +| **Cairo** | `2.12.2` | Smart contract language | +| **Scarb** | `2.12.2` | Package manager and build tool | +| **Starknet** | `2.12.2` | Layer 2 blockchain | + +> **โš ๏ธ Breaking Changes in Dojo 1.7.1**: If upgrading from earlier versions, see the migration guide in `examples/DOJO_1.7.1_UPGRADE_GUIDE.md` + +--- + +## Quick Start + +### Running PixeLAW Core with Docker + +The fastest way to get started is using the pre-built Docker image: + +```bash +# Pull the latest image +docker pull ghcr.io/pixelaw/core:latest + +# Or build locally +cd core +make docker_build + +# Run with docker-compose +docker compose up -d + +# Services now available: +# - Katana RPC: http://localhost:5050 +# - Torii Indexer: http://localhost:8080 +# - Dashboard: http://localhost:3000 ``` -This command compiles your project and prepares it for execution. +### Building from Source + +```bash +cd core + +# Build contracts +just build -### Step 2: Start Keiko -The Keiko is a container that has the [Katana RPC](https://book.dojoengine.org/framework/katana/overview.html), -the [Torii World Indexer](https://book.dojoengine.org/framework/torii/overview.html), and a Dashboard. Once the container starts, it starts running Katana, deploys the World Container from the repo -via the contracts volume (See the docker-compose.yml for more details), runs the post_deploy script from -the repo's Scarb.toml, and starts up Torii. Keiko Dashboard is accesible via http://localhost:3000/fork. +# Run tests +just test -```shell -make start_keiko +# Run filtered tests +just test_filtered "snake" + +# Start development environment (Katana + Torii) +docker compose up -d + +# Deploy contracts to local Katana +cd contracts +sozo migrate apply + +# Initialize contracts +scarb run init ``` -### Step 3: Get the React frontend ready +### Creating Your First App + +See the [Examples repository](../examples/) for complete app templates. Basic structure: -```shell -make prep_web -cd web -yarn +```cairo +#[dojo::contract] +mod my_app { + use pixelaw::core::actions::{IActionsDispatcher, IActionsDispatcherTrait}; + + #[abi(embed_v0)] + impl MyAppImpl of IMyApp { + fn interact(ref self: ContractState, position: Position) { + let core = get_core_actions(ref self.world()); + + // Your game logic here + + core.update_pixel( + for_player: player, + for_system: system, + pixel_update: pixel_update, + area_hint: Option::None, + allow_modify: true + ); + } + } +} ``` -### Step 4: Run the frontend locally +--- + +## Core Architecture -```shell -cd web -yarn dev +### Models (ECS Components) + +| Model | Purpose | Key Fields | +|-------|---------|------------| +| **Pixel** | Core pixel entity | position, app, color, owner, text, alert, timestamps | +| **Area** | Spatial region | id, position, width, height, owner, app, color | +| **QueueItem** | Scheduled action | id, timestamp, system, selector, calldata, hash | +| **App** | App registry entry | system, name, icon, action | +| **RTree** | Spatial index | Root node with hierarchical bounding boxes | + +### Actions (Core Systems) + +The `IActions` interface in `core/contracts/src/core/actions.cairo` provides all primitives: + +#### Pixel Actions +```cairo +fn update_pixel( + for_player: ContractAddress, + for_system: ContractAddress, + pixel_update: PixelUpdate, + area_hint: Option, + allow_modify: bool +) ``` -### Step 5: Run the queue bot -````shell -cd bots -yarn install -yarn dev -```` -- to run here, you can check this page: https://www.npmjs.com/package/canvas -- the following command might fix your issue. -````shell -brew install pkg-config cairo pango libpng jpeg giflib librsvg pixman -```` - -#### NOTE -To change accounts, add an account query to the frontend url. For example: http://localhost:3000/?account=1. Add -as many accounts as desired by following the pattern set in the env.example. - -The following would be example players: -````console -# for player 1 -http://localhost:5173/?account=1 -# for player 2 -http://localhost:5173/?account=2 -```` - -## Project Structure -This is an overview of the most important folders/files: -- `Makefile` : A collection of helpful commands, mainly for Dojo -- `contracts` : The Dojo Cairo smart contract code - - `src/components.cairo` : Dojo component definitions - - `src/systems.cairo` : Dojo component definitions - - `src/Scarb.toml` : The scarb config file used for katana -- `web` : A [Vite](https://vitejs.dev/) React project - - `.env` : (copied from env.example) Contains the hardcoded developer addresses used for Dojo - - `src/dojo/contractComponents.ts` : Client-side definitions of the components - - `src/dojo/createClientComponents.ts` : Client-side setup of the components - - `src/dojo/createSystemCalls.ts` : Client-side definitions of the systems - -## Typical development activities -### Add a DOJO system -- Edit `src/systems.cairo` -- Edit `src/dojo/createSystemCalls.ts` -### Add a DOJO component -- Edit `src/components.cairo` -- Edit `src/dojo/contractComponents.ts` -- Edit `src/dojo/createClientComponents.ts` -### Redeploy to Katana -- Restart Katana -- Redeploy the contracts with `cd contracts && scarb run deploy` - -## Troubleshooting / Tricks -### When using vscode, the cairo language server panics with `thread 'main' panicked at 'internal error: entered unreachable code: ` -Resolution: None, this is a know issue, can ignore - -### When deploying/migrating, consistent exceptions even though the contract compiles. -Resolution: Delete the `contracts/target` dir - -### How do I use different accounts while testing? -Register 2 accounts (example from https://github.com/coostendorp/dojo-rps): +#### Queue Actions +```cairo +fn schedule_queue( + timestamp: u64, + called_system: ContractAddress, + selector: felt252, + calldata: Span +) -> u64 + +fn process_queue( + id: u64, + timestamp: u64, + called_system: ContractAddress, + selector: felt252, + calldata: Span +) ``` -let player1 = starknet::contract_address_const::<0x1337>(); -let player2 = starknet::contract_address_const::<0x1338>(); + +#### Area Actions +```cairo +fn add_area(area: Area) -> u32 +fn remove_area(id: u32) +fn find_area_by_position(position: Position) -> Option ``` -And then switch accounts like this: + +#### App Actions +```cairo +fn new_app( + for_player: ContractAddress, + name: felt252, + icon: felt252 +) ``` -starknet::testing::set_contract_address(player1); + +### Permission System + +When `update_pixel()` is called, Core checks permissions in this order: + +1. **Is caller the pixel owner?** โ†’ Allow immediately +2. **Is caller the owner of an area containing the pixel?** โ†’ Allow immediately +3. **Is pixel unowned AND no area contains it?** โ†’ Allow immediately +4. **Otherwise** โ†’ Call pixel app's `on_pre_update` hook: + - Hook returns `None` โ†’ **DENY** update + - Hook returns `Some(pixel_update)` โ†’ **ALLOW** (with optional modifications) + +After successful update, call pixel app's `on_post_update` hook for side effects. + +### R-Tree Spatial Indexing + +Areas are indexed using a hierarchical R-Tree data structure for efficient spatial queries: + +- **Performance**: O(log n) area lookup vs O(n) iteration +- **Implementation**: Bit-packed felt252 nodes (4 child IDs per node) +- **Root Node**: ID `4294967292` spanning entire world bounds +- **Operations**: Insert, remove, find by position, find in bounds + +--- + +## Development Guide + +### Project Structure + ``` +core/ +โ”œโ”€โ”€ contracts/ # Cairo smart contracts +โ”‚ โ”œโ”€โ”€ src/ +โ”‚ โ”‚ โ”œโ”€โ”€ lib.cairo # Module declarations +โ”‚ โ”‚ โ”œโ”€โ”€ apps/ # Default apps (paint, snake, player, house) +โ”‚ โ”‚ โ”œโ”€โ”€ core/ +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ models/ # ECS models (pixel, area, queue, registry) +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ actions/ # Core systems (pixel, queue, area, app) +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ utils.cairo # Helper functions +โ”‚ โ”‚ โ””โ”€โ”€ tests/ # Comprehensive test suite +โ”‚ โ”œโ”€โ”€ Scarb.toml # Package configuration +โ”‚ โ””โ”€โ”€ README.md +โ”œโ”€โ”€ pixelaw_test_utils/ # Testing helper package +โ”œโ”€โ”€ dojo_init/ # Initialization scripts +โ”œโ”€โ”€ scripts/ # Release and upgrade scripts +โ”œโ”€โ”€ docker/ # Docker configuration +โ”œโ”€โ”€ docker-compose.yml # Development environment +โ”œโ”€โ”€ Dockerfile # Production build +โ”œโ”€โ”€ justfile # Development commands +โ””โ”€โ”€ Makefile # Docker build commands +``` + +### Building Contracts -## Deploying Contracts Remotely -### Step 1 Follow slot deployment -Replace the rpc_url in Scarb.toml, as well as the account_address, and private_key with the slot katana url, -account_address, and private_key. Read [this](https://book.dojoengine.org/tutorial/deploy-using-slot/main.html) to -familiarize yourself with slot deployments. NOTE: set the invoke-max-steps to a sufficiently high number to allow -ml-based games (4_000_000_000 is a good amount). Also, take note of copying the SEED, TOTAL_ACCOUNTS, and WORLD_ADDRESS - -Deploying Katana -````console -slot deployments create katana --invoke-max-steps 4000000000 -```` - -Get the account information and seed using the logs -````console -slot deployments logs katana > output.txt -```` - -Replace the account_address, private_key, and rpc_url, then deploy your world -````console +```bash +# Build contracts with Dojo +just build + +# Or directly with sozo cd contracts -sozo migrate --name -```` +sozo build + +# โš ๏ธ IMPORTANT: Always use `sozo build`, not `scarb build` +# sozo properly compiles Dojo contracts +``` + +### Running Tests -Deploy Torii -````console -slot deployments create torii --rpc --world --start-block 0 -```` +```bash +# Run all 33 tests +just test -### Step 2 Run post slot deployment -This will initialize the deployed world -````console +# Run specific test pattern +just test_filtered "snake" +just test_filtered "pixel" +just test_filtered "area" + +# Run tests directly cd contracts -scarb run slot_post_deploy -```` - -### Step 3 Set environment variables -Set the following environment variables in the Docker Container that holds the PixeLAW Core image: -1. PUBLIC_NODE_URL - the slot katana url provided -2. PUBLIC_TORII - the slot torii url provided -3. SLOT_KATANA - same value as the PUBLIC_NODE_URL -4. SLOT_TORII - same value as the PUBLIC_TORII -5. SEED - the seed provided when first deploying with Slot -6. TOTAL_ACCOUNTS - number of accounts prefunded -7. WORLD_ADDRESS - the address of the deployed world - -### Step 4 Upload the manifest -Wait till the Docker Container is up and running, then execute this command: -````console +sozo test +``` + +### Docker Development + +```bash +# Build Docker image +make docker_build + +# Or with specific tag +docker build -t pixelaw/core:latest . + +# Run with docker-compose +docker compose up -d + +# View logs +docker compose logs -f katana +docker compose logs -f torii + +# Access container shell +just shell + +# Stop services +docker compose down + +# Clean up volumes +docker compose down -v +``` + +### Deployment + +```bash +# Deploy to local Katana cd contracts -scarb run upload_manifest -```` - -## Deployed Worlds - -| ID | Address | Core Version | Dojo | Branch | -|--------------|-------------------------------------------------------------------|--------------|---------|--------| -| pixelaw | 0x47864d08a1b86cf0dd52ea2785f8bc93b5f48edca8380bbb3057d158521e12d | v0.0.45 | v0.4.1 | main | -| pixelaw1 | 0x662b50ea51bf4b9b4a72e48d189d11d4224456c06256f0d57d1756d2d909c47 | v0.0.30 | v0.3.15 | demo1 | -| pixelaw-test | 0x2d409910fb90d701633d9e09139a2b37a13e1cbf1288fc4a9ae6ac09a59ff16 | v0.0.45 | v0.4.1 | test | -| pixelaw-demo | 0x51ee3a738cbe090c95eb8102427ffb31b796be7395968cdda70cbfdd675e65a | v0.0.61 | v0.4.1 | main | - - -### How to create new Demo -- Create a new demo branch -- Add new workflow `.github/workflows/demo{x}.yaml` -- Copy the content of demo1.yaml and only change below lines - ``` - name: Deploy Application Dry Run - env: - ARGOCD_SERVER: ${{ secrets.ARGOCD_SERVER }} - ARGOCD_AUTH_TOKEN: ${{ secrets.ARGOCD_AUTH_TOKEN }} - run: | - argocd app create $PROJECTNAME-{demo1} \ <-- Change demo1 to preferred demo number - --repo https://github.com/pixelaw/core.git \ - --path chart/pixelaw-core \ - --revision {demo1} \ <--- Revision = BranchName, change it - --dest-namespace $PROJECTNAME-{demo1} \ <-- Change demo1 to preferred demo number - --dest-server https://kubernetes.default.svc \ - --helm-set-string dockerImage=$REGISTRY/$PROJECTNAME:${VERSION} \ - --upsert \ - --server $ARGOCD_SERVER \ - --auth-token $ARGOCD_AUTH_TOKEN - - -- Edit `chart/pixelaw-core/values.yaml` -- ``` appType: - frontend: webapp-demo1 <-- Change demo1 to preferred demo number - - subDomainName: <-- Change subdomains to preferred ones - pixelaw: demo - katana: katana.demo - torii: torii.demo - grpcTorii: grpc.demo +sozo migrate apply + +# Initialize contracts (runs dojo_init) +scarb run init + +# Deploy to remote (configure Scarb.toml first) +sozo migrate --name + +# Upload manifest +scarb run upload_manifest /manifests +``` + +### Testing Utilities + +The `pixelaw_test_utils` package provides helpers for writing tests: + +```cairo +use pixelaw_test_utils::{setup_core, setup_apps, set_caller}; + +#[test] +fn test_my_app() { + let (world, core_actions, _) = setup_core(); + + // Set caller for permission checks + set_caller(player_address); + + // Your test logic here + core_actions.update_pixel(...); + + // Assertions + let pixel = get!(world, position, Pixel); + assert(pixel.color == expected_color, 'wrong color'); +} +``` + +--- + +## Contributing + +We welcome contributions! PixeLAW Core is the foundation of the ecosystem, so we maintain high standards for code quality, testing, and backward compatibility. + +### Code Style + +#### Cairo Conventions +- **Functions**: `snake_case` (e.g., `update_pixel`, `schedule_queue`) +- **Types/Structs**: `PascalCase` (e.g., `Pixel`, `QueueItem`) +- **Constants**: `SCREAMING_SNAKE_CASE` (e.g., `APP_KEY`, `APP_ICON`) +- **Traits**: `PascalCase` with `Trait` suffix (e.g., `PixelTrait`) + +#### Modern Dojo Patterns +- Use `WorldStorage` and `ModelStorage` for reading/writing models +- Enums in models MUST derive `Default` trait with `#[default]` attribute +- Use `.try_into().unwrap()` for `ContractAddress` conversion (NOT deprecated `contract_address_const`) +- Always include `allow-prebuilt-plugins = ["dojo_cairo_macros"]` in `Scarb.toml` + +#### Error Handling +```cairo +// Use descriptive error messages +assert(condition, 'pixel not owned by caller'); + +// Use panic_at_position for position-related errors +panic_at_position(position, 'invalid pixel state'); +``` + +### Testing Requirements + +All contributions must include comprehensive tests: + +1. **Unit tests** for new functions/logic +2. **Integration tests** for full workflows +3. **Permission tests** validating access control +4. **Hook tests** if modifying the hook system + +Tests should cover both success and failure scenarios: + +```cairo +#[test] +fn test_update_pixel_success() { + // Test successful pixel update +} + +#[test] +#[should_panic(expected: ('pixel not owned',))] +fn test_update_pixel_unauthorized() { + // Test permission denial +} +``` + +### Pull Request Process + +1. **Fork the repository** and create your branch from `main` +2. **Write tests** covering your changes +3. **Run the test suite**: `just test` (all 33 tests must pass) +4. **Format your code**: Follow Cairo style conventions +5. **Update documentation** if adding new features +6. **Create a PR** with: + - Clear description of changes + - Link to any related issues + - Test results showing all tests pass + +### Development Workflow + +```bash +# 1. Fork and clone +git clone https://github.com/YOUR_USERNAME/core +cd core + +# 2. Create feature branch +git checkout -b feature/my-new-feature + +# 3. Make changes and test iteratively +just build +just test + +# 4. Run full test suite +just test + +# 5. Commit and push +git add . +git commit -m "feat: add my new feature" +git push origin feature/my-new-feature + +# 6. Open PR on GitHub +``` + +### What to Contribute + +We're especially interested in: + +- **Bug fixes**: Issues labeled `bug` in GitHub +- **Performance optimizations**: Gas reduction, query optimization +- **Documentation improvements**: Code comments, README updates +- **New default apps**: Well-tested apps demonstrating new patterns +- **Testing improvements**: New test cases, better coverage + +### Core Stability Guidelines + +โš ๏ธ **Breaking changes require careful consideration**: +- Core contracts are used by multiple apps +- Changes must maintain backward compatibility when possible +- Coordinate with the core team for major architectural changes + +--- + +## Resources + +### Documentation +- **PixeLAW Book**: [pixelaw.github.io/book](https://pixelaw.github.io/book/index.html) +- **Dojo Framework**: [book.dojoengine.org](https://book.dojoengine.org) +- **Cairo Language**: [book.cairo-lang.org](https://book.cairo-lang.org) + +### Related Repositories +- **Examples**: [../examples/](../examples/) - 7 example apps demonstrating different game mechanics +- **SDK (pixelaw.js)**: [../pixelaw.js/](../pixelaw.js/) - TypeScript SDK for frontend integration +- **Frontend (Vanilla)**: [../vanilla/](../vanilla/) - React client for PixeLAW + +### Community +- **Discord**: [Join PixeLAW Discord](https://t.co/jKDjNbFdZ5) +- **Twitter**: [@0xpixelaw](https://x.com/0xpixelaw) +- **GitHub Issues**: [Report bugs or request features](https://github.com/pixelaw/core/issues) + +--- + +## License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. + +--- + +
+ +**Built with โค๏ธ by the PixeLAW community** + +[๐ŸŽฎ Try PixeLAW](https://demo.pixelaw.xyz) โ€ข [๐Ÿ“– Read the Docs](https://pixelaw.github.io/book) โ€ข [๐Ÿ’ฌ Join Discord](https://t.co/jKDjNbFdZ5) + +