Skip to content
Draft
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
46 changes: 37 additions & 9 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,20 @@ This is a SvelteKit-based dApp (decentralized application) for participating in
## Working Effectively

### Bootstrap and Dependencies

- Install dependencies: `npm install` -- takes 45 seconds
- Node.js and npm are available (Node v20.19.4, npm 10.8.2)

### Environment Setup (CRITICAL)
**ALWAYS** create a `.env` file before building or running the application. The app requires both VITE_ and PUBLIC_ prefixed environment variables:

**ALWAYS** create a `.env` file before building or running the application. The app requires both VITE* and PUBLIC* prefixed environment variables:

```bash
# Create .env file with required variables for mock mode
cat > .env << 'EOF'
# Mock mode (do not set VITE_API_BASE to enable mock mode)
VITE_CHAIN_ID="11155111"
VITE_RPC_URL="https://rpc.sepolia.org"
VITE_RPC_URL="https://rpc.sepolia.org"
VITE_TOKEN_ADDR="0x1234567890123456789012345678901234567890"
VITE_CAMPAIGN="0x1234567890123456789012345678901234567890123456789012345678901234"
VITE_FLOOR_SCORE="600000"
Expand All @@ -40,27 +42,33 @@ EOF
```

### Build and Development

- Build for production: `npm run build` -- takes 30 seconds. **NEVER CANCEL** - Set timeout to 60+ minutes for complex builds.
- Start development server: `npm run dev` -- starts in 1-2 seconds on http://localhost:5173
- Preview production build: `npm run preview` -- serves on http://localhost:4173

### Testing

- Run unit tests: `npm run test:unit` -- takes 2 seconds with Vitest
- **NOTE**: Some unit tests may fail when .env file is present due to test design expecting missing environment variables
- Run e2e tests: `npm run test:e2e` -- **REQUIRES Playwright browser installation first**
- Install browsers: `npx playwright install` -- takes 5-10 minutes. **NEVER CANCEL** - Set timeout to 15+ minutes.
- Note: Playwright downloads may fail in some environments due to network restrictions
- Run all tests: `npm test` (alias for unit tests)

### Code Quality
- Check linting/formatting: `npm run lint` -- takes 8 seconds
- Auto-format code: `npm run format` -- takes 9 seconds

- Check linting/formatting: `npm run lint` -- takes 1-2 seconds
- Auto-format code: `npm run format` -- takes 1-2 seconds
- **ALWAYS run `npm run format` and `npm run lint` before committing** to avoid CI failures
- **NOTE**: ESLint configuration (`eslint.config.js`) is required for linting to work

## Validation Scenarios

**ALWAYS manually validate changes by running the application and testing key user flows:**

### Basic Application Flow

1. Start the dev server: `npm run dev`
2. Navigate to http://localhost:5173
3. Verify the homepage loads with "Claim Your Reputation-Based Airdrop" heading
Expand All @@ -69,18 +77,21 @@ EOF
6. Check the footer shows "Powered by Shadowgraph"

### Mock Mode Testing

- When `VITE_API_BASE` is **not set**, the app runs in mock mode
- Mock mode simulates API responses without requiring a live backend
- This is ideal for development and testing UI changes
- Scores are generated deterministically based on wallet addresses

### Production Mode Testing
### Production Mode Testing

- Set `VITE_API_BASE` to your backend URL to test with live services
- Requires valid contract addresses for ECDSA and/or ZK claim paths

## Repository Structure

### Key Directories

- `src/lib/` - Core application logic and utilities
- `src/lib/components/` - Svelte components
- `src/lib/stores/` - Svelte stores for state management
Expand All @@ -91,6 +102,7 @@ EOF
- `tests/e2e/` - Playwright end-to-end tests

### Important Files

- `src/lib/config.ts` - Environment configuration parsing with Zod validation
- `src/lib/web3/onboard.ts` - Web3-Onboard wallet connection setup
- `src/lib/chain/client.ts` - Viem blockchain client configuration
Expand All @@ -101,52 +113,68 @@ EOF
## Technology Stack

### Core Framework

- **SvelteKit** - Full-stack framework with TypeScript
- **Vite** - Build tool and dev server
- **TailwindCSS** - Utility-first CSS framework

### Blockchain Integration

- **Viem** - TypeScript Ethereum library for contract interactions
- **Web3-Onboard** - Multi-wallet connection support (MetaMask, WalletConnect, Coinbase)
- **Zod** - Runtime validation for environment variables and API responses

### Testing

- **Vitest** - Unit testing framework
- **Playwright** - End-to-end testing
- **@testing-library/svelte** - Testing utilities

## Common Issues and Solutions

### Build Failures
- **Missing environment variables**: Ensure both VITE_ and PUBLIC_ prefixed versions are set

- **Missing environment variables**: Ensure both VITE* and PUBLIC* prefixed versions are set
- **Module resolution errors**: Run `npm install` to ensure dependencies are installed
- **TypeScript errors**: Check that `.svelte-kit/tsconfig.json` extends are properly configured

### Test Failures

- **Unit test module resolution**: Ensure `vitest.config.ts` includes the SvelteKit plugin
- **Unit test failures with .env present**: Some tests expect missing environment variables and may fail when .env is configured
- **E2E test browser errors**: Run `npx playwright install` to download browsers
- **Network-related test failures**: Some tests may fail due to network restrictions in CI environments

### Linting Issues

- **ESLint configuration**: Ensure `eslint.config.js` exists in the root directory
- **Existing linting errors**: The codebase has existing TypeScript and accessibility linting errors that are unrelated to new changes
- **Focus on new code**: Only fix linting issues in code you're modifying, ignore existing issues

### Development Server Issues

- **Port conflicts**: Default ports are 5173 (dev) and 4173 (preview)
- **Environment variable changes**: Restart the dev server after modifying `.env`
- **Build artifacts**: Clean `.svelte-kit/` directory if experiencing cache issues

## Specific Recommendations

### When Making Changes

1. **ALWAYS** ensure `.env` file exists with required variables
2. **ALWAYS** run `npm run build` to verify changes don't break production builds
3. **ALWAYS** test the application manually in browser after changes
4. **ALWAYS** run `npm run format && npm run lint` before committing
5. For blockchain/Web3 changes, test both mock mode and with test networks

### Performance Considerations

- Build generates large chunks (500kB+) due to Web3 libraries - this is expected
- Use `npm run preview` to test production build performance
- Monitor console for Web3 connection errors in development

### Security Notes

- Never commit real private keys or mainnet configuration to `.env`
- Use test networks (Sepolia) for development
- Validate all user inputs through Zod schemas
Expand All @@ -162,7 +190,7 @@ EOF
- Unit tests: 2 seconds (timeout: 30+ seconds)
- E2E tests: Variable (timeout: 10+ minutes including browser installation)
- Playwright browser installation: 5-10 minutes (timeout: 15+ minutes)
- Code formatting: 9 seconds
- Linting: 8 seconds
- Code formatting: 1-2 seconds
- Linting: 1-2 seconds

**Always wait for completion of builds and tests to ensure accuracy of validation.**
**Always wait for completion of builds and tests to ensure accuracy of validation.**
2 changes: 1 addition & 1 deletion .github/description.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
A novel airdrop mechanism that leverages peer-to-peer attestations with EBSL (Ethereum Booster Sampling Layer) and EZKL (Easy Zero-Knowledge Learning) to create verifiable reputation-based token distributions. This system implements ZKML (Zero-Knowledge Machine Learning) proofs to ensure fair and sybil-resistant token allocations based on genuine user reputation.
A novel airdrop mechanism that leverages peer-to-peer attestations with EBSL (Ethereum Booster Sampling Layer) and EZKL (Easy Zero-Knowledge Learning) to create verifiable reputation-based token distributions. This system implements ZKML (Zero-Knowledge Machine Learning) proofs to ensure fair and sybil-resistant token allocations based on genuine user reputation.
12 changes: 10 additions & 2 deletions .svelte-kit/ambient.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ declare module '$env/static/private' {
export const SYSTEMD_EXEC_PID: string;
export const DBUS_SESSION_BUS_ADDRESS: string;
export const GITHUB_GRAPHQL_URL: string;
export const GITHUB_DOWNLOADS_URL: string;
export const COLOR: string;
export const NVM_DIR: string;
export const DOTNET_SKIP_FIRST_TIME_EXPERIENCE: string;
Expand Down Expand Up @@ -134,12 +135,14 @@ declare module '$env/static/private' {
export const RUNNER_TRACKING_ID: string;
export const INVOCATION_ID: string;
export const RUNNER_TOOL_CACHE: string;
export const GITHUB_UPLOADS_URL: string;
export const REQUESTS_CA_BUNDLE: string;
export const NODE: string;
export const npm_package_name: string;
export const GITHUB_ACTION: string;
export const GITHUB_RUN_NUMBER: string;
export const GITHUB_TRIGGERING_ACTOR: string;
export const COPILOT_EXPERIMENTS: string;
export const RUNNER_ARCH: string;
export const XDG_RUNTIME_DIR: string;
export const AGENT_TOOLSDIRECTORY: string;
Expand Down Expand Up @@ -196,6 +199,7 @@ declare module '$env/static/private' {
export const GITHUB_OUTPUT: string;
export const npm_config_global_prefix: string;
export const EDGEWEBDRIVER: string;
export const COPILOT_EXPERIMENT_ASSIGNMENT_CONTEXT: string;
export const npm_command: string;
export const ANDROID_NDK: string;
export const SGX_AESM_ADDR: string;
Expand Down Expand Up @@ -225,11 +229,11 @@ declare module '$env/static/private' {
* ```
*/
declare module '$env/static/public' {
export const PUBLIC_WALLETCONNECT_PROJECT_ID: string;
export const PUBLIC_CHAIN_ID: string;
export const PUBLIC_RPC_URL: string;
export const PUBLIC_TOKEN_ADDR: string;
export const PUBLIC_CAMPAIGN: string;
export const PUBLIC_WALLETCONNECT_PROJECT_ID: string;
}

/**
Expand Down Expand Up @@ -303,6 +307,7 @@ declare module '$env/dynamic/private' {
SYSTEMD_EXEC_PID: string;
DBUS_SESSION_BUS_ADDRESS: string;
GITHUB_GRAPHQL_URL: string;
GITHUB_DOWNLOADS_URL: string;
COLOR: string;
NVM_DIR: string;
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: string;
Expand Down Expand Up @@ -354,12 +359,14 @@ declare module '$env/dynamic/private' {
RUNNER_TRACKING_ID: string;
INVOCATION_ID: string;
RUNNER_TOOL_CACHE: string;
GITHUB_UPLOADS_URL: string;
REQUESTS_CA_BUNDLE: string;
NODE: string;
npm_package_name: string;
GITHUB_ACTION: string;
GITHUB_RUN_NUMBER: string;
GITHUB_TRIGGERING_ACTOR: string;
COPILOT_EXPERIMENTS: string;
RUNNER_ARCH: string;
XDG_RUNTIME_DIR: string;
AGENT_TOOLSDIRECTORY: string;
Expand Down Expand Up @@ -416,6 +423,7 @@ declare module '$env/dynamic/private' {
GITHUB_OUTPUT: string;
npm_config_global_prefix: string;
EDGEWEBDRIVER: string;
COPILOT_EXPERIMENT_ASSIGNMENT_CONTEXT: string;
npm_command: string;
ANDROID_NDK: string;
SGX_AESM_ADDR: string;
Expand Down Expand Up @@ -450,11 +458,11 @@ declare module '$env/dynamic/private' {
*/
declare module '$env/dynamic/public' {
export const env: {
PUBLIC_WALLETCONNECT_PROJECT_ID: string;
PUBLIC_CHAIN_ID: string;
PUBLIC_RPC_URL: string;
PUBLIC_TOKEN_ADDR: string;
PUBLIC_CAMPAIGN: string;
PUBLIC_WALLETCONNECT_PROJECT_ID: string;
[key: `PUBLIC_${string}`]: string | undefined;
}
}
2 changes: 1 addition & 1 deletion .svelte-kit/generated/server/internal.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const options = {
app: ({ head, body, assets, nonce, env }) => "<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <link rel=\"icon\" href=\"" + assets + "/favicon.png\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <script>\n // Prevent Flash Of Unstyled Content (FOUC) by applying the user's theme\n // preference before the app hydrates. Uses localStorage when available,\n // otherwise falls back to the system preference.\n (function () {\n try {\n var theme = localStorage.getItem(\"theme\");\n if (theme === \"dark\") {\n document.documentElement.classList.add(\"dark\");\n } else if (theme === \"light\") {\n document.documentElement.classList.remove(\"dark\");\n } else if (\n window.matchMedia &&\n window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n ) {\n document.documentElement.classList.add(\"dark\");\n }\n } catch (e) {\n // ignore errors (e.g. blocked storage)\n }\n })();\n </script>\n " + head + "\n </head>\n <body data-sveltekit-preload-data=\"hover\" class=\"antialiased\">\n <div class=\"min-h-screen site-container\">" + body + "</div>\n </body>\n</html>\n",
error: ({ status, message }) => "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<title>" + message + "</title>\n\n\t\t<style>\n\t\t\tbody {\n\t\t\t\t--bg: white;\n\t\t\t\t--fg: #222;\n\t\t\t\t--divider: #ccc;\n\t\t\t\tbackground: var(--bg);\n\t\t\t\tcolor: var(--fg);\n\t\t\t\tfont-family:\n\t\t\t\t\tsystem-ui,\n\t\t\t\t\t-apple-system,\n\t\t\t\t\tBlinkMacSystemFont,\n\t\t\t\t\t'Segoe UI',\n\t\t\t\t\tRoboto,\n\t\t\t\t\tOxygen,\n\t\t\t\t\tUbuntu,\n\t\t\t\t\tCantarell,\n\t\t\t\t\t'Open Sans',\n\t\t\t\t\t'Helvetica Neue',\n\t\t\t\t\tsans-serif;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tjustify-content: center;\n\t\t\t\theight: 100vh;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t.error {\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tmax-width: 32rem;\n\t\t\t\tmargin: 0 1rem;\n\t\t\t}\n\n\t\t\t.status {\n\t\t\t\tfont-weight: 200;\n\t\t\t\tfont-size: 3rem;\n\t\t\t\tline-height: 1;\n\t\t\t\tposition: relative;\n\t\t\t\ttop: -0.05rem;\n\t\t\t}\n\n\t\t\t.message {\n\t\t\t\tborder-left: 1px solid var(--divider);\n\t\t\t\tpadding: 0 0 0 1rem;\n\t\t\t\tmargin: 0 0 0 1rem;\n\t\t\t\tmin-height: 2.5rem;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t}\n\n\t\t\t.message h1 {\n\t\t\t\tfont-weight: 400;\n\t\t\t\tfont-size: 1em;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t@media (prefers-color-scheme: dark) {\n\t\t\t\tbody {\n\t\t\t\t\t--bg: #222;\n\t\t\t\t\t--fg: #ddd;\n\t\t\t\t\t--divider: #666;\n\t\t\t\t}\n\t\t\t}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<div class=\"error\">\n\t\t\t<span class=\"status\">" + status + "</span>\n\t\t\t<div class=\"message\">\n\t\t\t\t<h1>" + message + "</h1>\n\t\t\t</div>\n\t\t</div>\n\t</body>\n</html>\n"
},
version_hash: "17gzzde"
version_hash: "6shq5s"
};

export async function get_hooks() {
Expand Down
33 changes: 33 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import js from "@eslint/js";
import ts from "typescript-eslint";
import svelte from "eslint-plugin-svelte";
import prettier from "eslint-config-prettier";
import globals from "globals";

/** @type {import('eslint').Linter.Config[]} */
export default [
js.configs.recommended,
...ts.configs.recommended,
...svelte.configs["flat/recommended"],
prettier,
...svelte.configs["flat/prettier"],
{
languageOptions: {
globals: {
...globals.browser,
...globals.node,
},
},
},
{
files: ["**/*.svelte"],
languageOptions: {
parserOptions: {
parser: ts.parser,
},
},
},
{
ignores: ["build/", ".svelte-kit/", "dist/"],
},
];