diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..5b6e3c7 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,96 @@ +name: CI + +on: + push: + branches: [main, develop] + pull_request: + branches: [main, develop] + +jobs: + rust-checks: + name: Rust Quality Checks + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt, clippy + targets: wasm32-unknown-unknown + + - name: Cache Cargo + uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Check formatting + run: cargo fmt --all -- --check + + - name: Run Clippy + run: cargo clippy --all-targets --all-features -- -D warnings + + - name: Run tests + run: cargo test --all-features + + - name: Build WASM + run: cargo build --target wasm32-unknown-unknown --release + + frontend-checks: + name: Frontend Quality Checks + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./frontend + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: frontend/package-lock.json + + - name: Install dependencies + run: npm ci + + - name: Check formatting + run: npm run format:check + + - name: Run linter + run: npm run lint + + - name: Type check + run: npx tsc --noEmit + + - name: Build + run: npm run build + + security-audit: + name: Security Audit + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Rust Security Audit + uses: rustsec/audit-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: frontend/package-lock.json + + - name: Frontend Security Audit + working-directory: ./frontend + run: npm audit --audit-level=moderate diff --git a/.gitignore b/.gitignore index bafdb8d..387f0d6 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,7 @@ out/ # OS Thumbs.db .kiro/ + +# Demo accounts (sensitive) +demo/demo-accounts.json +demo/*-secret.txt diff --git a/README.md b/README.md index 652c401..73ec436 100644 --- a/README.md +++ b/README.md @@ -193,12 +193,29 @@ cargo watch -x test ## CI/CD -GitHub Actions automatically: -- Runs tests on push/PR -- Checks code formatting -- Runs clippy linting -- Builds optimized WASM -- Uploads build artifacts +GitHub Actions automatically runs quality checks on all pushes and pull requests: + +### Rust Checks +- Code formatting (`cargo fmt`) +- Linting with Clippy (`cargo clippy`) +- Unit and integration tests +- WASM build verification +- Security audit with RustSec + +### Frontend Checks +- Code formatting with Prettier +- ESLint linting (max 0 warnings) +- TypeScript type checking +- Production build verification +- npm security audit + +### Branch Protection +Pull requests must pass all CI checks before merging. Configure branch protection rules: +1. Go to Settings > Branches +2. Add rule for `main` branch +3. Enable "Require status checks to pass before merging" +4. Select: `Rust Quality Checks`, `Frontend Quality Checks`, `Security Audit` +5. Enable "Require branches to be up to date before merging" ## License diff --git a/demo/README.md b/demo/README.md new file mode 100644 index 0000000..50d4cb4 --- /dev/null +++ b/demo/README.md @@ -0,0 +1,33 @@ +# Demo Resources + +This directory contains resources for demonstrating the Scavngr platform. + +## Files + +- **demo-script.md**: Complete step-by-step interactive demo guide with expected outputs +- **demo-accounts.json**: Template for storing demo account information (git-ignored) + +## Quick Start + +1. Follow the account setup in `demo-script.md` +2. Deploy contract to testnet +3. Configure frontend with contract ID +4. Execute demo flow (25-30 minutes) + +## Demo Highlights + +- Participant registration (3 roles) +- Incentive creation and management +- Waste submission and tracking +- Supply chain transfers +- Reward distribution +- Real-time statistics + +## Tips + +- Pre-fund all accounts before demo +- Keep block explorer open for transparency +- Allow time for transaction confirmations +- Prepare backup accounts in case of issues + +See `demo-script.md` for complete instructions. diff --git a/demo/demo-accounts.json.example b/demo/demo-accounts.json.example new file mode 100644 index 0000000..8f41249 --- /dev/null +++ b/demo/demo-accounts.json.example @@ -0,0 +1,32 @@ +{ + "accounts": [ + { + "name": "Alice", + "role": "Recycler", + "address": "G...", + "note": "Generate with: soroban keys generate alice" + }, + { + "name": "Bob", + "role": "Collector", + "address": "G...", + "note": "Generate with: soroban keys generate bob" + }, + { + "name": "Carol", + "role": "Manufacturer", + "address": "G...", + "note": "Generate with: soroban keys generate carol" + } + ], + "contract": { + "id": "C...", + "network": "testnet", + "deployed_at": "2024-01-01T00:00:00Z" + }, + "notes": [ + "Copy this file to demo-accounts.json and fill in actual values", + "Never commit demo-accounts.json (it's git-ignored)", + "Fund accounts via: curl https://friendbot.stellar.org?addr=ADDRESS" + ] +} diff --git a/demo/demo-script.md b/demo/demo-script.md new file mode 100644 index 0000000..73ad329 --- /dev/null +++ b/demo/demo-script.md @@ -0,0 +1,283 @@ +# Scavngr Interactive Demo Script + +This guide provides a step-by-step walkthrough for demonstrating the Scavngr platform's key features. + +## Prerequisites + +- Stellar testnet account with XLM +- Freighter wallet installed +- Contract deployed on testnet +- Frontend running locally or deployed + +## Demo Accounts Setup + +Create three demo accounts representing different roles: + +### Account 1: Recycler (Alice) +```bash +# Generate keypair +soroban keys generate alice + +# Get address +soroban keys address alice + +# Fund account +curl "https://friendbot.stellar.org?addr=$(soroban keys address alice)" +``` + +### Account 2: Collector (Bob) +```bash +soroban keys generate bob +soroban keys address bob +curl "https://friendbot.stellar.org?addr=$(soroban keys address bob)" +``` + +### Account 3: Manufacturer (Carol) +```bash +soroban keys generate carol +soroban keys address carol +curl "https://friendbot.stellar.org?addr=$(soroban keys address carol)" +``` + +## Demo Flow + +### Part 1: Participant Registration (5 minutes) + +#### Step 1.1: Register Recycler (Alice) +1. Open the frontend application +2. Connect Freighter wallet with Alice's account +3. Navigate to "Register" or landing page +4. Fill in registration form: + - Role: Recycler + - Name: "Alice's Recycling Center" + - Location: Use map or enter coordinates (e.g., 40.7128, -74.0060) +5. Click "Register" +6. Approve transaction in Freighter +7. **Expected Output**: Success message, redirected to Recycler Dashboard + +#### Step 1.2: Register Collector (Bob) +1. Disconnect Alice's wallet +2. Connect with Bob's account +3. Register as Collector: + - Name: "Bob's Collection Service" + - Location: 34.0522, -118.2437 +4. **Expected Output**: Success, redirected to Collector Dashboard + +#### Step 1.3: Register Manufacturer (Carol) +1. Switch to Carol's account +2. Register as Manufacturer: + - Name: "Carol's Manufacturing Co" + - Location: 41.8781, -87.6298 +4. **Expected Output**: Success, redirected to Manufacturer Dashboard + +### Part 2: Create Incentive (3 minutes) + +#### Step 2.1: Carol Creates Incentive +1. Logged in as Carol (Manufacturer) +2. Navigate to "Incentives" page +3. Click "Create Incentive" button +4. Fill in the form: + - Waste Type: PET Plastic + - Reward per gram: 10 points + - Total budget: 50000 points +5. Review the estimated coverage (5 kg) +6. Click "Create Incentive" +7. Approve transaction +8. **Expected Output**: + - Success notification + - New incentive card appears + - Shows: PET Plastic, 10 pts/g, 50000 pts budget, Active status + +### Part 3: Submit Waste Material (4 minutes) + +#### Step 3.1: Alice Submits Waste +1. Switch to Alice's account (Recycler) +2. Navigate to "Submit Material" or Dashboard +3. Click "Register Waste" button +4. Fill in the form: + - Waste Type: PET Plastic + - Weight: 500 grams + - Location: Use current or enter coordinates +5. Submit transaction +6. **Expected Output**: + - Success message + - New waste card appears in "My Materials" + - Status: Pending + - Waste ID assigned (e.g., #1) + +#### Step 3.2: Verify Material Status +1. Click on the waste card to view details +2. **Expected Output**: + - Waste ID, Type, Weight + - Current Owner: Alice's address + - Status: Pending (not yet confirmed) + - Transfer history: empty + +### Part 4: Transfer Waste (5 minutes) + +#### Step 4.1: Alice Transfers to Bob +1. Still logged in as Alice +2. On the waste card, click "Transfer" button +3. Fill in transfer form: + - Recipient: Bob's address (paste from clipboard) + - Location: Current location + - Note: "Collected from recycling center" +4. Submit transaction +5. **Expected Output**: + - Success notification + - Waste card shows "Current Owner: Bob's address" + - Transfer history updated + +#### Step 4.2: Bob Confirms Receipt +1. Switch to Bob's account (Collector) +2. Navigate to "My Materials" +3. Find the transferred waste (Status: Pending) +4. Click "Confirm Details" button +5. Approve transaction +6. **Expected Output**: + - Status changes to "Confirmed" + - Green checkmark badge appears + +#### Step 4.3: Bob Transfers to Carol +1. Still as Bob +2. Click "Transfer" on the confirmed waste +3. Transfer to Carol's address +4. Note: "Delivering to manufacturer" +5. **Expected Output**: Transfer successful, owner updated + +### Part 5: Distribute Rewards (4 minutes) + +#### Step 5.1: Carol Distributes Rewards +1. Switch to Carol's account (Manufacturer) +2. Navigate to "My Materials" or Dashboard +3. Find the received waste (Status: Pending) +4. Click "Confirm Details" first +5. Then click "Distribute Rewards" button +6. Select the incentive created earlier +7. Review reward distribution: + - Alice (Recycler): X points + - Bob (Collector): Y points + - Carol (Owner): Z points +8. Approve transaction +9. **Expected Output**: + - Success message + - Rewards distributed to all participants + - Incentive budget reduced by total reward amount + +### Part 6: View Statistics (3 minutes) + +#### Step 6.1: Check Individual Stats +1. As any participant, navigate to Dashboard +2. View personal statistics: + - Total materials submitted + - Total rewards earned + - Transfer count +3. **Expected Output**: Updated stats reflecting demo activities + +#### Step 6.2: Check Global Metrics +1. Navigate to "Supply Chain Tracker" or Stats page +2. View global statistics: + - Total waste items: 1 + - Total tokens distributed: (sum of rewards) + - Active participants: 3 +3. **Expected Output**: Aggregated platform metrics + +### Part 7: Incentive Management (2 minutes) + +#### Step 7.1: Update Incentive +1. As Carol, go to Incentives page +2. Click "Edit" on the created incentive +3. Update: + - Reward per gram: 15 points + - Add more budget: 25000 points +4. Submit transaction +5. **Expected Output**: Incentive updated, new values displayed + +#### Step 7.2: Deactivate Incentive +1. Click "Deactivate" on the incentive +2. Confirm action +3. **Expected Output**: + - Incentive status: Inactive + - No longer appears in active incentives list + +## Expected Outcomes Summary + +### Successful Demo Indicators +- ✅ 3 participants registered with different roles +- ✅ 1 incentive created and managed +- ✅ 1 waste item submitted, transferred twice, and confirmed +- ✅ Rewards distributed to supply chain participants +- ✅ Statistics updated across all dashboards +- ✅ All transactions confirmed on Stellar testnet + +### Key Metrics After Demo +- Total Participants: 3 +- Total Waste Items: 1 +- Total Transfers: 2 +- Total Incentives: 1 (deactivated) +- Total Rewards Distributed: ~5000-7500 points (depending on percentages) + +## Troubleshooting + +### Transaction Fails +- **Issue**: "Insufficient XLM balance" +- **Solution**: Fund account via friendbot again + +### Wallet Not Connected +- **Issue**: "Please connect wallet" +- **Solution**: Ensure Freighter is unlocked and connected to testnet + +### Contract Error +- **Issue**: "Participant not registered" +- **Solution**: Complete registration step first + +### Transfer Fails +- **Issue**: "Not the current owner" +- **Solution**: Verify you're logged in with the correct account + +## Demo Tips + +1. **Preparation**: Pre-fund all demo accounts before starting +2. **Timing**: Allow 30 seconds between transactions for blockchain confirmation +3. **Visuals**: Keep the block explorer open to show real-time transactions +4. **Narrative**: Explain the circular economy concept as you demo +5. **Questions**: Pause after each major section for audience questions + +## Advanced Demo Scenarios + +### Scenario A: Multiple Waste Types +- Submit different waste types (Paper, Metal, Glass) +- Create incentives for each type +- Show filtering and sorting capabilities + +### Scenario B: Batch Operations +- Submit multiple waste items at once +- Demonstrate bulk transfer capabilities +- Show aggregated statistics + +### Scenario C: Supply Chain Tracking +- Follow a single waste item through multiple transfers +- Visualize the complete journey on the tracker +- Highlight transparency and traceability + +## Demo Data Cleanup + +After the demo, you can: +1. Keep the contract for future demos +2. Deploy a fresh contract for clean slate +3. Deactivate all test incentives +4. Document final state for reference + +## Next Steps + +After the demo, guide participants to: +1. Review the documentation +2. Explore the GitHub repository +3. Try the testnet deployment themselves +4. Provide feedback and suggestions + +--- + +**Demo Duration**: ~25-30 minutes +**Audience Level**: Technical and non-technical +**Prerequisites**: Basic blockchain knowledge helpful but not required diff --git a/docs/COMPONENT_IMPLEMENTATION.md b/docs/COMPONENT_IMPLEMENTATION.md new file mode 100644 index 0000000..833ad24 --- /dev/null +++ b/docs/COMPONENT_IMPLEMENTATION.md @@ -0,0 +1,234 @@ +# Component Implementation Guide + +This document describes the implementation of key UI components in the Scavngr frontend. + +## WasteCard Component + +**Location**: `frontend/src/components/ui/WasteCard.tsx` + +### Features Implemented + +✅ **Waste Type Icon and Label** +- Dynamic icons for each waste type (Paper, PET Plastic, Plastic, Metal, Glass) +- Color-coded backgrounds with dark mode support +- Accessible icon presentation with `aria-hidden` + +✅ **Weight Display** +- Automatic unit conversion (grams to kilograms) +- Formatted display: "500 g" or "1.50 kg" +- Responsive layout + +✅ **Status Badge** +- Three states: Confirmed (green), Pending (yellow), Inactive (gray) +- Icon indicators (CheckCircle, Clock, XCircle) +- Accessible color contrast + +✅ **Waste ID** +- Monospace font for readability +- Displayed as "#123" format +- Supports BigInt IDs + +✅ **Current Owner** +- Truncated address display +- Link to block explorer +- Responsive text wrapping + +✅ **Action Buttons Slot** +- Flexible `actions` prop for custom buttons +- Rendered in card footer +- Supports multiple buttons with proper spacing + +✅ **Responsive Layout** +- Mobile-first design +- Flexbox layout for optimal spacing +- Card component with proper padding + +### Usage Example + +```tsx +import { WasteCard } from '@/components/ui/WasteCard' +import { Button } from '@/components/ui/Button' + + + + + + } +/> +``` + +### Props + +```typescript +interface WasteCardProps { + waste: Waste // Waste item data + actions?: React.ReactNode // Optional action buttons + className?: string // Additional CSS classes +} +``` + +## CreateIncentiveModal Component + +**Location**: `frontend/src/components/modals/CreateIncentiveModal.tsx` + +### Features Implemented + +✅ **Waste Type Selector** +- Dropdown with all waste types +- Labeled options (Paper, PET Plastic, etc.) +- Keyboard navigation support +- Accessible with proper ARIA labels + +✅ **Reward Per Gram Input** +- Number input with validation +- Minimum value: 1 +- Step: 1 (integer values) +- Placeholder text for guidance + +✅ **Total Budget Input** +- Number input with validation +- Minimum value: 1 +- Step: 1 (integer values) +- Clear labeling + +✅ **Preview of Estimated Rewards** +- Real-time calculation: `budget / reward_per_gram` +- Automatic unit conversion (grams to kg) +- Formatted display with context +- Updates as user types +- Accessible with `role="status"` and `aria-live="polite"` + +✅ **Submit Integration** +- Calls `createIncentive` from `useIncentives` hook +- Transaction confirmation dialog +- Loading states during submission +- Error handling with user feedback +- Success callback with created incentive data + +✅ **Form Validation** +- Required fields +- Positive number validation +- Submit button disabled when invalid +- Clear error messages + +✅ **Responsive Design** +- Mobile-friendly modal +- Proper spacing and typography +- Accessible focus management + +### Usage Example + +```tsx +import { CreateIncentiveModal } from '@/components/modals/CreateIncentiveModal' + +const [isOpen, setIsOpen] = useState(false) + + setIsOpen(false)} + onSuccess={(incentive) => { + console.log('Created:', incentive) + // Refresh incentives list + }} +/> +``` + +### Props + +```typescript +interface Props { + open: boolean // Modal visibility + onClose: () => void // Close handler + onSuccess?: (incentive: Incentive) => void // Success callback +} +``` + +### Transaction Flow + +1. User fills form (waste type, reward, budget) +2. Preview shows estimated coverage +3. User clicks "Create incentive" +4. Transaction confirmation dialog appears +5. User confirms in dialog +6. Transaction submitted to blockchain +7. Loading state shown during processing +8. On success: modal closes, callback fired +9. On error: error message displayed, modal stays open + +## Design Patterns + +### Accessibility +- Semantic HTML elements +- ARIA labels and roles +- Keyboard navigation +- Focus management +- Screen reader announcements + +### Responsive Design +- Mobile-first approach +- Flexible layouts +- Proper touch targets +- Readable typography + +### Error Handling +- User-friendly error messages +- Non-blocking errors +- Clear recovery paths +- Loading states + +### Performance +- Memoized components +- Optimized re-renders +- Efficient calculations +- Lazy loading where appropriate + +## Testing Recommendations + +### WasteCard +- [ ] Renders all waste types correctly +- [ ] Shows correct status badges +- [ ] Formats weight properly (g/kg) +- [ ] Truncates long addresses +- [ ] Renders action buttons in footer +- [ ] Responsive on mobile/desktop + +### CreateIncentiveModal +- [ ] Validates required fields +- [ ] Calculates preview correctly +- [ ] Handles form submission +- [ ] Shows loading states +- [ ] Displays errors appropriately +- [ ] Calls success callback +- [ ] Resets form on close + +## Future Enhancements + +### WasteCard +- Add waste image/photo support +- Show transfer count badge +- Add quick actions menu +- Implement card animations + +### CreateIncentiveModal +- Add incentive templates +- Support recurring incentives +- Add budget recommendations +- Implement draft saving + +## Related Components + +- `Badge` - Status indicators +- `Card` - Layout container +- `AddressDisplay` - Address formatting +- `TransactionConfirmDialog` - Transaction confirmation +- `Select` - Dropdown selector +- `Input` - Form inputs +- `Button` - Action buttons +- `Dialog` - Modal container