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
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ jobs:
- name: Lint
run: npm run lint

- name: Type check
run: npm run type-check

- name: Test application
run: npm test

Expand All @@ -41,5 +44,8 @@ jobs:
- name: Test smart contracts
run: npm run test:contracts

- name: Smart contract coverage
run: npm run test:coverage

- name: Build application
run: npm run build
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

# testing
/coverage
coverage.json

# next.js
/.next/
Expand Down
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20
62 changes: 49 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ An educational math game for children aged 2–9 with an on-chain reward system

---

## Tech Stack
## Tech Stack & Runtime Requirements

| Layer | Tech |
|---|---|
| Runtime | Node.js `>=20.9.0` (pinned via `.nvmrc` `20`), npm `>=10.0.0` |
| Frontend | Next.js 16, React 19, Tailwind CSS |
| State | Zustand (persisted to localStorage) |
| Smart Contract | Solidity 0.8.24, Hardhat 2 |
Expand All @@ -27,25 +28,53 @@ An educational math game for children aged 2–9 with an on-chain reward system

## Getting Started

### 1. Install dependencies
### 1. Prerequisites
Ensure you are using the supported Node.js and npm versions:
```bash
npm install
nvm use
# Node >= 20.9.0, npm >= 10.0.0
```

### 2. Set up environment
### 2. Install dependencies
```bash
npm ci
```

### 3. Set up environment
```bash
cp .env.example .env.local
# Fill in your DEPLOYER_PRIVATE_KEY
```

### 3. Run locally
### 4. Run locally
```bash
npm run dev
# Open http://localhost:3000
```

---

## Local Validation (Matches CI)

Run the full local validation sequence matching the CI workflow:

```bash
npm ci && npm run lint && npm run type-check && npm test && npm run test:network && npm run compile && npm run test:contracts && npm run test:coverage && npm run build
```

### Individual Test Commands

- **Frontend unit & component tests**: `npm test`
- **TypeScript type checking**: `npm run type-check`
- **ESLint**: `npm run lint`
- **Network configuration tests**: `npm run test:network`
- **Compile smart contracts**: `npm run compile`
- **Smart contract tests**: `npm run test:contracts`
- **Smart contract coverage**: `npm run test:coverage`
- **Production build**: `npm run build`

---

## Smart Contract

### Contract: `MathBlocGame.sol`
Expand Down Expand Up @@ -75,6 +104,12 @@ Deployed on **Celo Alfajores Testnet**.
npm run compile
```

### Test & Coverage
```bash
npm run test:contracts
npm run test:coverage
```

### Deploy to Alfajores (testnet)
```bash
npm run deploy:alfajores
Expand Down Expand Up @@ -132,14 +167,15 @@ mathbloc/
│ ├── data.ts # Story chapters, badges, TTS
│ ├── useContract.ts # ethers.js contract hook
│ └── contract.json # Auto-generated after deploy
└── contracts/
├── contracts/
│ └── MathBlocGame.sol
├── scripts/
│ ├── deploy.ts
│ └── daily-activity.ts
└── test/
└── MathBlocGame.test.ts
├── contracts/
│ ├── contracts/
│ │ └── MathBlocGame.sol
│ ├── scripts/
│ │ ├── deploy.ts
│ │ └── daily-activity.ts
│ └── test/
│ └── MathBlocGame.test.ts
└── tests/ # Frontend unit & regression tests
```

---
Expand Down
4 changes: 4 additions & 0 deletions contracts/contracts/MathBlocGame.sol
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,10 @@ contract MathBlocGame is Ownable, ReentrancyGuard, Pausable, EIP712 {
*/
function getLeaderboard(uint256 topN) external view returns (LeaderboardEntry[] memory) {
uint256 total = registeredPlayers.length;
if (total == 0 || topN == 0) {
return new LeaderboardEntry[](0);
}
if (topN > total) topN = total;

// Edge cases: nothing to return
if (total == 0 || topN == 0) {
Expand Down
Loading