diff --git a/.claude/skills/audit/SKILL.md b/.claude/skills/audit/SKILL.md deleted file mode 100644 index 12d2246..0000000 --- a/.claude/skills/audit/SKILL.md +++ /dev/null @@ -1,741 +0,0 @@ ---- -name: audit -description: Perform a full-spectrum audit covering Claude Code config, security, code quality, architecture, dependencies, and DevOps hygiene. Run with /audit. -user-invocable: true ---- - -# Full-Spectrum Project & Claude Code Audit - -You are performing an exhaustive audit of this project. This covers SIX domains: -1. Claude Code configuration -2. Codebase security -3. Code quality & patterns -4. Architecture & structure -5. Dependency health -6. Git & DevOps hygiene - -Take your time. Be thorough. Read files when needed. Cost and tokens do not matter — completeness does. - ---- - -## Phase 1: Discovery - -Run ALL of the following scans. Store every output for Phase 2 evaluation. - -### 1.1 Project Identity & Tech Stack Detection - -```bash -bash -c ' -echo "=== PROJECT ROOT ===" -pwd -echo "" - -echo "=== TECH STACK ===" -# Node/JS/TS -if [ -f package.json ]; then - echo "Node.js project detected" - NAME=$(sed -n "s/.*\"name\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\".*/\1/p" package.json | head -1) - echo " Name: $NAME" - [ -f pnpm-workspace.yaml ] && echo " Monorepo: pnpm workspaces" - [ -f lerna.json ] && echo " Monorepo: lerna" - [ -f turbo.json ] && echo " Monorepo: turborepo" - [ -f nx.json ] && echo " Monorepo: nx" - [ -f yarn.lock ] && echo " Lockfile: yarn.lock" - [ -f pnpm-lock.yaml ] && echo " Lockfile: pnpm-lock.yaml" - [ -f package-lock.json ] && echo " Lockfile: package-lock.json" - [ -f bun.lockb ] && echo " Lockfile: bun.lockb" - [ -f tsconfig.json ] && echo " TypeScript: yes" - [ -f .babelrc ] || [ -f babel.config.js ] || [ -f babel.config.json ] && echo " Babel: yes" -fi - -# Python -[ -f pyproject.toml ] && echo "Python project (pyproject.toml)" -[ -f requirements.txt ] && echo "Python project (requirements.txt)" -[ -f Pipfile ] && echo "Python project (Pipfile)" -[ -f setup.py ] && echo "Python project (setup.py)" -[ -f poetry.lock ] && echo " Poetry lockfile detected" - -# Go -[ -f go.mod ] && echo "Go project: $(head -1 go.mod)" - -# Rust -[ -f Cargo.toml ] && echo "Rust project detected" - -# Solidity / Web3 -if ls foundry.toml hardhat.config.* 2>/dev/null | head -1 > /dev/null 2>&1; then - [ -f foundry.toml ] && echo "Solidity: Foundry" - ls hardhat.config.* 2>/dev/null && echo "Solidity: Hardhat" -fi - -# Daml -ls *.daml daml.yaml 2>/dev/null | head -1 > /dev/null 2>&1 && echo "Daml project detected" - -# Other -[ -f composer.json ] && echo "PHP (Composer)" -[ -f Gemfile ] && echo "Ruby (Bundler)" -[ -f build.gradle ] || [ -f pom.xml ] && echo "Java/Kotlin" -[ -f Dockerfile ] && echo "Docker: yes" -[ -f docker-compose.yml ] || [ -f docker-compose.yaml ] && echo "Docker Compose: yes" - -echo "" -echo "=== FRAMEWORK DETECTION ===" -if [ -f package.json ]; then - for fw in next react vue angular svelte express fastify nestjs nuxt gatsby remix vite astro; do - grep -q "\"$fw\"" package.json 2>/dev/null && echo " Framework/Lib: $fw" - done - grep -q "\"hardhat\"" package.json 2>/dev/null && echo " Framework/Lib: hardhat" - grep -q "\"ethers\"" package.json 2>/dev/null && echo " Framework/Lib: ethers" - grep -q "\"viem\"" package.json 2>/dev/null && echo " Framework/Lib: viem" - grep -q "\"wagmi\"" package.json 2>/dev/null && echo " Framework/Lib: wagmi" - grep -q "\"@rainbow-me/rainbowkit\"" package.json 2>/dev/null && echo " Framework/Lib: rainbowkit" - grep -q "\"@openzeppelin\"" package.json 2>/dev/null && echo " Framework/Lib: openzeppelin" -fi -' -``` - -### 1.2 Claude Code Configuration Scan - -```bash -bash -c ' -echo "=== GLOBAL CLAUDE CONFIG ===" -for f in ~/.claude/CLAUDE.md ~/.claude/settings.json; do - if [ -f "$f" ]; then - echo "✅ $(basename $f) ($(wc -l < "$f" | tr -d " ") lines)" - else - echo "❌ $(basename $f)" - fi -done -[ -f ~/.claude.json ] && echo "✅ ~/.claude.json (MCP config)" || echo "❌ ~/.claude.json" - -echo "" -echo "=== PROJECT CLAUDE CONFIG ===" -for f in ./CLAUDE.md ./.claude/CLAUDE.md ./.claude/settings.json ./.claude/settings.local.json; do - if [ -f "$f" ]; then - echo "✅ $f ($(wc -l < "$f" | tr -d " ") lines)" - else - echo "❌ $f" - fi -done - -echo "" -echo "=== CLAUDE EXTENSIONS ===" -for d in agents commands skills hooks rules; do - if [ -d "./.claude/$d" ]; then - count=$(find "./.claude/$d" -maxdepth 2 -type f 2>/dev/null | wc -l | tr -d " ") - echo "✅ $d/: $count files" - find "./.claude/$d" -maxdepth 2 -type f 2>/dev/null | while read f; do echo " $(basename $f)"; done - else - echo "❌ $d/" - fi -done - -echo "" -echo "=== SECURITY HOOKS ===" -if [ -d "./.claude/hooks" ]; then - grep -rl "PreToolUse" ./.claude/hooks/ 2>/dev/null | while read f; do echo "✅ PreToolUse hook: $f"; done - grep -rl "PostToolUse" ./.claude/hooks/ 2>/dev/null | while read f; do echo "✅ PostToolUse hook: $f"; done - grep -rl "UserPromptSubmit" ./.claude/hooks/ 2>/dev/null | while read f; do echo "✅ UserPromptSubmit hook: $f"; done - [ -z "$(grep -rl "PreToolUse" ./.claude/hooks/ 2>/dev/null)" ] && echo "❌ No PreToolUse hooks" -else - echo "❌ No hooks directory" -fi - -echo "" -echo "=== MCP SERVERS ===" -CURRENT_DIR=$(pwd) -MCP_FOUND="" - -if [ -f ~/.claude.json ] && command -v jq &>/dev/null; then - PROJ_MCP=$(jq -r --arg p "$CURRENT_DIR" "(.projects[\$p].mcpServers // {}) | keys[]" ~/.claude.json 2>/dev/null) - GLOBAL_MCP=$(jq -r "(.mcpServers // {}) | keys[]" ~/.claude.json 2>/dev/null) - if [ -n "$PROJ_MCP" ]; then - echo "Project MCP (from ~/.claude.json):" - echo "$PROJ_MCP" | while read s; do echo " ✅ $s"; done - MCP_FOUND="yes" - fi - if [ -n "$GLOBAL_MCP" ]; then - echo "Global MCP (from ~/.claude.json):" - echo "$GLOBAL_MCP" | while read s; do echo " ✅ $s"; done - MCP_FOUND="yes" - fi -fi - -if [ -f ./.claude/mcp.json ]; then - echo "Project MCP (from .claude/mcp.json):" - if command -v jq &>/dev/null; then - jq -r "(.mcpServers // {}) | keys[]" ./.claude/mcp.json 2>/dev/null | while read s; do echo " ✅ $s"; done - fi - MCP_FOUND="yes" -fi - -[ -z "$MCP_FOUND" ] && echo "❌ No MCP servers configured" - -echo "" -echo "=== PERMISSIONS CONFIG ===" -for f in ./.claude/settings.json ~/.claude/settings.json; do - if [ -f "$f" ]; then - echo "--- $f ---" - if command -v jq &>/dev/null; then - jq -r ".permissions // \"not set\"" "$f" 2>/dev/null - DENY=$(jq -r "(.permissions.deny // [])[]" "$f" 2>/dev/null) - if [ -n "$DENY" ]; then - echo "Denied patterns:" - echo "$DENY" | while read d; do echo " 🚫 $d"; done - else - echo "⚠️ No deny rules set" - fi - else - grep -i "deny\|allow\|permissions" "$f" 2>/dev/null || echo "⚠️ Could not parse (jq not available)" - fi - fi -done -' -``` - -### 1.3 CLAUDE.md Quality Deep Scan - -If a project CLAUDE.md exists, READ it fully. Evaluate: -- Is it concise or bloated? -- Does it contain actionable instructions or vague prose? -- Does it reference external docs with `@path` (SSOT pattern)? -- Does it include concrete code examples? -- Does it cover: project structure, conventions, tech stack, known issues, workflow rules? -- Are there contradictions or outdated info? - -Also check for a global `~/.claude/CLAUDE.md` and evaluate its quality. - -### 1.4 Codebase Security Scan - -```bash -bash -c ' -echo "=== HARDCODED SECRETS SCAN ===" -# Search for common secret patterns in source files (not node_modules, not .git, not lockfiles) -EXCLUDES="--include=*.ts --include=*.tsx --include=*.js --include=*.jsx --include=*.py --include=*.sol --include=*.json --include=*.yaml --include=*.yml --include=*.toml --include=*.env* --include=*.cfg --include=*.conf --include=*.md" - -echo "--- API Keys / Tokens ---" -grep -rn $EXCLUDES \ - -E "(api[_-]?key|api[_-]?secret|access[_-]?token|auth[_-]?token|bearer|secret[_-]?key)[[:space:]]*[:=][[:space:]]*[\"'\'']+[A-Za-z0-9+/=_-]{16,}" \ - --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist --exclude-dir=build --exclude-dir=.next --exclude-dir=out --exclude-dir=coverage \ - . 2>/dev/null | grep -v "package-lock\|pnpm-lock\|yarn.lock\|\.example\|EXAMPLE\|placeholder\|your_\|YOUR_\|xxx\|TODO" | head -20 || echo "✅ None found" - -echo "" -echo "--- Private Keys ---" -grep -rn $EXCLUDES \ - -E "(PRIVATE[_-]?KEY|-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----)" \ - --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist --exclude-dir=build \ - . 2>/dev/null | grep -v "\.example\|EXAMPLE\|placeholder" | head -10 || echo "✅ None found" - -echo "" -echo "--- Hardcoded Passwords ---" -grep -rn $EXCLUDES \ - -iE "(password|passwd|pwd)[[:space:]]*[:=][[:space:]]*[\"'\'']+[^\"'\'']{4,}" \ - --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist --exclude-dir=build \ - . 2>/dev/null | grep -v "\.example\|EXAMPLE\|placeholder\|your_\|YOUR_\|xxx\|TODO\|password.*:\|type.*password\|passwordSchema\|passwordRegex\|password_hash\|password_field\|getPassword\|setPassword\|resetPassword\|validatePassword" | head -20 || echo "✅ None found" - -echo "" -echo "--- .env files in repo ---" -find . -name ".env" -o -name ".env.local" -o -name ".env.production" -o -name ".env.staging" 2>/dev/null | grep -v node_modules | grep -v ".env.example" | head -10 -echo "(If any above, check if they are in .gitignore)" - -echo "" -echo "--- Wallet / Mnemonic Exposure ---" -grep -rn $EXCLUDES \ - -iE "(mnemonic|seed[_-]?phrase|private[_-]?key[[:space:]]*[:=]|0x[a-fA-F0-9]{64})" \ - --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist --exclude-dir=build \ - . 2>/dev/null | grep -v "\.example\|EXAMPLE\|placeholder\|process\.env\|getenv\|os\.environ\|test\|mock\|fixture" | head -15 || echo "✅ None found" -' -``` - -```bash -bash -c ' -echo "=== VULNERABILITY PATTERNS ===" - -echo "--- SQL Injection Risk ---" -grep -rn --include="*.ts" --include="*.js" --include="*.py" \ - -E "(query|exec|execute|raw)\s*\(.*(\\\$\{|\" ?\+|'\'' ?\+|f\"|\%s)" \ - --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist \ - . 2>/dev/null | head -10 || echo "✅ None found" - -echo "" -echo "--- Command Injection Risk ---" -grep -rn --include="*.ts" --include="*.js" --include="*.py" \ - -E "(exec|execSync|spawn|system|popen|subprocess)\s*\(.*(\\\$\{|\" ?\+|'\'' ?\+|f\")" \ - --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist \ - . 2>/dev/null | head -10 || echo "✅ None found" - -echo "" -echo "--- XSS Risk (dangerouslySetInnerHTML / innerHTML) ---" -grep -rn --include="*.tsx" --include="*.jsx" --include="*.ts" --include="*.js" \ - -E "(dangerouslySetInnerHTML|\.innerHTML\s*=)" \ - --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist \ - . 2>/dev/null | head -10 || echo "✅ None found" - -echo "" -echo "--- Eval Usage ---" -grep -rn --include="*.ts" --include="*.js" --include="*.py" \ - -E "\beval\s*\(" \ - --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist \ - . 2>/dev/null | head -10 || echo "✅ None found" - -echo "" -echo "--- Insecure Randomness ---" -grep -rn --include="*.ts" --include="*.js" --include="*.sol" \ - -E "Math\.random\(\)" \ - --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist \ - . 2>/dev/null | head -10 || echo "✅ None found (or only in non-security contexts)" - -echo "" -echo "--- Disabled Security (SSL/TLS verification, CORS wildcard) ---" -grep -rn --include="*.ts" --include="*.js" --include="*.py" --include="*.yaml" --include="*.yml" \ - -iE "(rejectUnauthorized\s*:\s*false|verify\s*=\s*False|NODE_TLS_REJECT_UNAUTHORIZED|cors\(\s*\)|\"\*\".*origin|origin.*\"\*\")" \ - --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist \ - . 2>/dev/null | head -10 || echo "✅ None found" - -echo "" -echo "--- Solidity-Specific: reentrancy, tx.origin, unchecked delegatecall ---" -grep -rn --include="*.sol" \ - -E "(tx\.origin|delegatecall|selfdestruct|suicide\(|\.call\{value)" \ - --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=lib \ - . 2>/dev/null | head -15 || echo "✅ None found" - -echo "" -echo "--- Solidity: Missing access control on public/external functions ---" -grep -rn --include="*.sol" \ - -E "function\s+\w+\s*\([^)]*\)\s+(external|public)\s+(payable\s+)?(returns|{)" \ - --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=lib \ - . 2>/dev/null | grep -v "onlyOwner\|onlyAdmin\|onlyRole\|require\|modifier\|view\|pure\|override" | head -15 || echo "✅ All public functions appear access-controlled" -' -``` - -### 1.5 Code Quality Scan - -```bash -bash -c ' -echo "=== CODE QUALITY ===" - -echo "--- Linting Config ---" -[ -f .eslintrc ] || [ -f .eslintrc.js ] || [ -f .eslintrc.json ] || [ -f .eslintrc.yml ] || [ -f eslint.config.js ] || [ -f eslint.config.mjs ] && echo "✅ ESLint configured" || echo "❌ No ESLint config" -[ -f .prettierrc ] || [ -f .prettierrc.js ] || [ -f .prettierrc.json ] || [ -f prettier.config.js ] || [ -f .prettierrc.yml ] && echo "✅ Prettier configured" || echo "❌ No Prettier config" -[ -f .stylelintrc ] || [ -f stylelint.config.js ] && echo "✅ Stylelint configured" || echo "⚪ No Stylelint (optional)" -[ -f .editorconfig ] && echo "✅ EditorConfig" || echo "⚠️ No .editorconfig" - -echo "" -echo "--- TypeScript Strictness ---" -if [ -f tsconfig.json ]; then - echo "tsconfig.json found:" - grep -E "(strict|noImplicit|strictNullChecks|noUnused|skipLibCheck)" tsconfig.json 2>/dev/null | head -10 -else - echo "❌ No tsconfig.json" -fi -# Check all tsconfig files in packages -find . -name "tsconfig.json" -not -path "*/node_modules/*" -maxdepth 4 2>/dev/null | while read f; do - STRICT=$(grep "\"strict\"" "$f" 2>/dev/null) - if [ -n "$STRICT" ]; then - echo " $f: $STRICT" - fi -done - -echo "" -echo "--- Test Infrastructure ---" -TESTS_FOUND="" -grep -q "jest\|vitest\|mocha\|ava\|tap" package.json 2>/dev/null && echo "✅ Test runner in package.json" && TESTS_FOUND="yes" -[ -f jest.config.js ] || [ -f jest.config.ts ] || [ -f vitest.config.ts ] || [ -f vitest.config.js ] && echo "✅ Test config file found" && TESTS_FOUND="yes" -find . -name "foundry.toml" -not -path "*/node_modules/*" 2>/dev/null | head -1 | while read f; do echo "✅ Foundry test framework ($f)"; done -TEST_FILES=$(find . \( -name "*.test.*" -o -name "*.spec.*" -o -name "test_*" -o -name "*_test.*" \) -not -path "*/node_modules/*" -not -path "*/.git/*" 2>/dev/null | wc -l | tr -d " ") -echo "Test files found: $TEST_FILES" -[ "$TEST_FILES" -eq 0 ] && echo "❌ No test files found" - -# Solidity tests -SOL_TESTS=$(find . -path "*/test/*.sol" -o -path "*/test/*.t.sol" 2>/dev/null | grep -v node_modules | wc -l | tr -d " ") -[ "$SOL_TESTS" -gt 0 ] && echo "Solidity test files: $SOL_TESTS" - -echo "" -echo "--- Error Handling Patterns ---" -echo "Unhandled promise patterns:" -grep -rn --include="*.ts" --include="*.js" \ - -E "\.catch\(\s*\(\s*\)\s*=>\s*\{\s*\}\s*\)|\.catch\(\(\) => \{\}\)" \ - --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist \ - . 2>/dev/null | wc -l | tr -d " " -echo "Empty catch blocks:" -grep -rn --include="*.ts" --include="*.js" \ - -E "catch\s*\([^)]*\)\s*\{\s*\}" \ - --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist \ - . 2>/dev/null | wc -l | tr -d " " - -echo "" -echo "--- Console.log/debug left in source ---" -CONSOLE_COUNT=$(grep -rn --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" \ - -E "console\.(log|debug|info|warn|error)" \ - --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist --exclude-dir=build --exclude-dir=.next \ - . 2>/dev/null | wc -l | tr -d " ") -echo "console.* calls in source: $CONSOLE_COUNT" -[ "$CONSOLE_COUNT" -gt 50 ] && echo "⚠️ Excessive console usage — consider a proper logger" - -echo "" -echo "--- TODO/FIXME/HACK markers ---" -for marker in TODO FIXME HACK XXX TEMP TEMPORARY; do - COUNT=$(grep -rn --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" --include="*.sol" --include="*.py" \ - "$marker" \ - --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist --exclude-dir=build \ - . 2>/dev/null | wc -l | tr -d " ") - [ "$COUNT" -gt 0 ] && echo "$marker: $COUNT occurrences" -done -' -``` - -### 1.6 Architecture & Structure Scan - -```bash -bash -c ' -echo "=== PROJECT STRUCTURE ===" - -echo "--- Top-Level Layout ---" -ls -la | grep -v "node_modules\|\.git$\|^total" - -echo "" -echo "--- Packages/Workspaces ---" -if [ -f pnpm-workspace.yaml ]; then - echo "pnpm-workspace.yaml:" - cat pnpm-workspace.yaml -fi -if [ -d packages ]; then - echo "" - echo "Packages:" - for d in packages/*/; do - [ -f "$d/package.json" ] && echo " ✅ $d (has package.json)" || echo " ⚠️ $d (no package.json)" - done -fi - -echo "" -echo "--- Environment Management ---" -[ -f .env.example ] && echo "✅ .env.example exists" || echo "❌ No .env.example" -[ -f .env ] && echo "⚠️ .env file exists (check .gitignore)" || echo "✅ No .env in root (good if using per-package envs)" -find . -name ".env" -not -path "*/node_modules/*" -not -path "*/.git/*" -maxdepth 3 2>/dev/null | while read f; do - echo " Found: $f" -done - -echo "" -echo "--- .gitignore Coverage ---" -if [ -f .gitignore ]; then - echo ".gitignore exists. Key patterns:" - for pattern in "node_modules" ".env" "dist" "build" ".next" "coverage" ".claude/settings.local" "*.pem" "*.key"; do - grep -q "$pattern" .gitignore 2>/dev/null && echo " ✅ $pattern" || echo " ❌ $pattern NOT in .gitignore" - done -else - echo "❌ No .gitignore!" -fi - -echo "" -echo "--- Documentation ---" -[ -f README.md ] && echo "✅ README.md ($(wc -l < README.md | tr -d " ") lines)" || echo "❌ No README.md" -[ -f CONTRIBUTING.md ] && echo "✅ CONTRIBUTING.md" || echo "⚪ No CONTRIBUTING.md" -[ -f LICENSE ] || [ -f LICENSE.md ] && echo "✅ LICENSE" || echo "⚠️ No LICENSE file" -[ -f CHANGELOG.md ] && echo "✅ CHANGELOG.md" || echo "⚪ No CHANGELOG.md" -[ -d docs ] && echo "✅ docs/ directory" || echo "⚪ No docs/ directory" -' -``` - -### 1.7 Dependency Health Scan - -```bash -bash -c ' -echo "=== DEPENDENCY HEALTH ===" - -# npm/pnpm audit -if [ -f package.json ]; then - echo "--- Package Manager Audit ---" - if command -v pnpm &>/dev/null && [ -f pnpm-lock.yaml ]; then - pnpm audit --no-fix 2>/dev/null | tail -20 || echo "⚠️ pnpm audit failed (may need install first)" - elif command -v npm &>/dev/null && [ -f package-lock.json ]; then - npm audit --omit=dev 2>/dev/null | tail -20 || echo "⚠️ npm audit failed" - elif command -v yarn &>/dev/null && [ -f yarn.lock ]; then - yarn audit 2>/dev/null | tail -20 || echo "⚠️ yarn audit failed" - else - echo "⚠️ No lockfile found — cannot run audit" - fi -fi - -# Python -if [ -f requirements.txt ] || [ -f pyproject.toml ]; then - echo "" - echo "--- Python Dependency Audit ---" - if command -v pip-audit &>/dev/null; then - pip-audit 2>/dev/null | tail -20 - elif command -v safety &>/dev/null; then - safety check 2>/dev/null | tail -20 - else - echo "⚠️ No pip-audit or safety installed" - fi -fi - -echo "" -echo "--- Lockfile Consistency ---" -LOCKFILES=0 -[ -f package-lock.json ] && LOCKFILES=$((LOCKFILES+1)) && echo "Found: package-lock.json" -[ -f pnpm-lock.yaml ] && LOCKFILES=$((LOCKFILES+1)) && echo "Found: pnpm-lock.yaml" -[ -f yarn.lock ] && LOCKFILES=$((LOCKFILES+1)) && echo "Found: yarn.lock" -[ -f bun.lockb ] && LOCKFILES=$((LOCKFILES+1)) && echo "Found: bun.lockb" -[ "$LOCKFILES" -gt 1 ] && echo "❌ MULTIPLE lockfiles detected — pick ONE package manager" -[ "$LOCKFILES" -eq 0 ] && [ -f package.json ] && echo "❌ No lockfile — dependencies are not pinned" -[ "$LOCKFILES" -eq 1 ] && echo "✅ Single lockfile (consistent)" - -echo "" -echo "--- Outdated Dependencies (top-level) ---" -if command -v pnpm &>/dev/null && [ -f pnpm-lock.yaml ]; then - pnpm outdated 2>/dev/null | head -25 || echo "Could not check outdated packages" -elif command -v npm &>/dev/null && [ -f package-lock.json ]; then - npm outdated 2>/dev/null | head -25 || echo "Could not check outdated packages" -fi -' -``` - -### 1.8 Git & DevOps Scan - -```bash -bash -c ' -echo "=== GIT & DEVOPS ===" - -echo "--- Branch Info ---" -git branch --show-current 2>/dev/null -echo "Remote branches:" -git branch -r 2>/dev/null | head -15 - -echo "" -echo "--- CI/CD Configuration ---" -[ -d .github/workflows ] && echo "✅ GitHub Actions:" && ls .github/workflows/ 2>/dev/null || echo "❌ No GitHub Actions" -[ -f .gitlab-ci.yml ] && echo "✅ GitLab CI" || true -[ -f Jenkinsfile ] && echo "✅ Jenkinsfile" || true -[ -f .circleci/config.yml ] && echo "✅ CircleCI" || true -[ -f .travis.yml ] && echo "✅ Travis CI" || true -[ -f vercel.json ] && echo "✅ Vercel config" || true -[ -f netlify.toml ] && echo "✅ Netlify config" || true - -echo "" -echo "--- Git Hooks (husky/lefthook/etc) ---" -[ -d .husky ] && echo "✅ Husky hooks:" && ls .husky/ 2>/dev/null || echo "⚪ No Husky" -[ -f .lefthook.yml ] || [ -f lefthook.yml ] && echo "✅ Lefthook" || true -[ -f .pre-commit-config.yaml ] && echo "✅ pre-commit" || true -grep -q "pre-commit\|husky\|lint-staged" package.json 2>/dev/null && echo "✅ Git hooks referenced in package.json" || echo "⚠️ No git hooks in package.json" - -echo "" -echo "--- Commit Message Convention ---" -echo "Last 10 commits:" -git log --oneline -10 2>/dev/null -echo "" -CONVENTIONAL=$(git log --oneline -20 2>/dev/null | grep -cE "^[a-f0-9]+ (feat|fix|chore|docs|test|refactor|style|perf|ci|build|revert)(\(.*\))?:" || echo 0) -echo "Conventional commits (last 20): $CONVENTIONAL/20" - -echo "" -echo "--- Large Files in History ---" -git rev-list --objects --all 2>/dev/null | git cat-file --batch-check="%(objecttype) %(objectsize) %(rest)" 2>/dev/null | grep "^blob" | sort -t" " -k2 -n -r | head -10 | while read type size path; do - SIZE_MB=$((size / 1048576)) - [ "$SIZE_MB" -gt 1 ] && echo "⚠️ Large file ($SIZE_MB MB): $path" -done || echo "Could not scan git history" - -echo "" -echo "--- Files Tracked That Probably Should Not Be ---" -git ls-files 2>/dev/null | grep -iE "\.(env|pem|key|p12|pfx|jks|keystore)$" | grep -v "\.example\|\.sample\|\.template" | head -10 || echo "✅ No sensitive files tracked" -git ls-files 2>/dev/null | grep -iE "(credentials|secrets?|password)" | grep -v "\.example\|\.sample\|\.template\|\.md\|\.txt" | head -10 || true -' -``` - -### 1.9 Solidity-Specific Deep Scan (if applicable) - -Only run this if Solidity contracts were detected in Phase 1.1. - -```bash -bash -c ' -if find . -name "*.sol" -not -path "*/node_modules/*" -not -path "*/lib/*" 2>/dev/null | head -1 | grep -q .; then - echo "=== SOLIDITY DEEP SCAN ===" - - echo "--- Compiler Versions ---" - grep -rn "pragma solidity" --include="*.sol" --exclude-dir=node_modules --exclude-dir=lib . 2>/dev/null | sort -u - - echo "" - echo "--- License Identifiers ---" - grep -rn "SPDX-License-Identifier" --include="*.sol" --exclude-dir=node_modules --exclude-dir=lib . 2>/dev/null | sort -u - - echo "" - echo "--- Floating Pragmas (insecure) ---" - grep -rn "pragma solidity \^" --include="*.sol" --exclude-dir=node_modules --exclude-dir=lib . 2>/dev/null | head -10 - - echo "" - echo "--- Missing Zero-Address Checks ---" - echo "(Constructors and setters that take address params without require(addr != address(0))):" - grep -rn --include="*.sol" -A5 "constructor\|function set" --exclude-dir=node_modules --exclude-dir=lib . 2>/dev/null | grep "address " | grep -v "address(0)\|!= address\|require" | head -15 - - echo "" - echo "--- Unchecked External Calls ---" - grep -rn --include="*.sol" -E "\.(call|delegatecall|staticcall)\{" --exclude-dir=node_modules --exclude-dir=lib . 2>/dev/null | head -10 - - echo "" - echo "--- Reentrancy Patterns (state change after external call) ---" - echo "(Manual review recommended — grep cannot fully detect this)" - grep -rn --include="*.sol" -B2 -A5 "\.call\{" --exclude-dir=node_modules --exclude-dir=lib . 2>/dev/null | head -30 - - echo "" - echo "--- Missing Events on State Changes ---" - echo "Public/external functions without emit:" - grep -rn --include="*.sol" -A10 "function.*\(.*\).*external\|function.*\(.*\).*public" --exclude-dir=node_modules --exclude-dir=lib . 2>/dev/null | grep -B10 "}" | grep -v "view\|pure\|emit" | grep "function" | head -15 - - echo "" - echo "--- Contract Sizes ---" - find . -name "*.sol" -not -path "*/node_modules/*" -not -path "*/lib/*" -not -path "*/test/*" 2>/dev/null | while read f; do - LINES=$(wc -l < "$f" | tr -d " ") - [ "$LINES" -gt 200 ] && echo " $f: $LINES lines" - done - - echo "" - echo "--- Test Coverage Check ---" - for pkg in packages/contracts-*/; do - if [ -f "$pkg/foundry.toml" ]; then - echo " $pkg: Foundry project" - TEST_COUNT=$(find "$pkg" -name "*.t.sol" 2>/dev/null | wc -l | tr -d " ") - SRC_COUNT=$(find "$pkg/src" -name "*.sol" 2>/dev/null | wc -l | tr -d " ") - echo " Source contracts: $SRC_COUNT | Test files: $TEST_COUNT" - fi - done -else - echo "No Solidity files found — skipping Solidity scan." -fi -' -``` - ---- - -## Phase 2: Deep File Analysis - -After all bash scans complete, READ the following files (if they exist) to perform qualitative analysis. These cannot be evaluated by grep alone: - -1. **CLAUDE.md** (project root) — Evaluate structure, clarity, completeness, actionability -2. **Global ~/.claude/CLAUDE.md** — Evaluate personal conventions -3. **.claude/settings.json** — Check permission rules, deny patterns -4. **Any hook files** found in `.claude/hooks/` — Evaluate security coverage -5. **Any agent files** found in `.claude/agents/` — Evaluate descriptions (Tool SEO), model selection -6. **CI/CD config files** (.github/workflows/*.yml, etc.) — Evaluate pipeline completeness -7. **.gitignore** — Evaluate coverage for sensitive files -8. **tsconfig.json** (root + packages) — Check strictness settings -9. **Key source files** — Sample 2-3 core files per package to evaluate code patterns, error handling, typing, documentation - -For each file read, note specific issues with file path and line numbers. - ---- - -## Phase 3: Evaluation & Scoring - -### 3.1 Scoring Matrix - -Score each category on a 0-10 scale. Apply these weights: - -| Category | Weight | What 10/10 Looks Like | -|----------|--------|----------------------| -| **Security** | x4 | No secrets in code, deny rules for .env/.pem, security hooks, no OWASP patterns, access control on all Solidity functions | -| **Claude Code Config** | x3 | Complete CLAUDE.md (concise + actionable), hooks, agents, commands, MCP servers, proper permissions | -| **Code Quality** | x3 | Linting, strict TypeScript, tests exist, proper error handling, no console spam, clean TODO debt | -| **Architecture** | x2 | Clear structure, consistent patterns, proper env management, documentation | -| **Dependencies** | x2 | No vulnerabilities, single lockfile, reasonably up to date | -| **Git & DevOps** | x2 | CI/CD pipeline, conventional commits, git hooks, no sensitive files tracked | - -**Formula**: `Total = sum(category_score * weight) / sum(max_score * weight) * 100` - -### 3.2 Priority Classification - -For every finding: -- **CRITICAL**: Active security vulnerability, secrets in code, production risk -- **HIGH**: Missing fundamentals that significantly impact productivity or safety -- **MEDIUM**: Best practices that would meaningfully improve the workflow -- **LOW**: Polish, optimization, nice-to-have improvements - ---- - -## Phase 4: Report Generation - -Present the report in this exact structure: - -### 4.1 Executive Summary - -``` -Health Score: XX/100 [CRITICAL|POOR|FAIR|GOOD|EXCELLENT] - -Tech Stack: [detected stack summary] - -CRITICAL Issues: X -HIGH Issues: X -MEDIUM Issues: X -LOW Issues: X -``` - -### 4.2 Critical & High Priority Issues - -For each CRITICAL and HIGH issue: - -``` -### [NUMBER]. [Issue Title] -**Priority**: CRITICAL | HIGH -**Category**: Security | Claude Config | Code Quality | Architecture | Dependencies | DevOps -**Location**: file:line (or general if not file-specific) -**Current State**: [what is wrong] -**Risk**: [what can go wrong] -**Fix**: [specific actionable fix with code/config example] -``` - -### 4.3 Quick Wins - -List 5-10 high-impact actions under 5 minutes each: -``` -1. [action] -> [impact] (~X min) -``` - -### 4.4 Full Findings Table - -| # | Priority | Category | Element | Status | Action | -|---|----------|----------|---------|--------|--------| -| 1 | ... | ... | ... | ... | ... | - -### 4.5 Detailed Medium & Low Findings - -Same format as 4.2 but grouped together. - -### 4.6 Category Scorecards - -For each of the 6 categories, provide: -``` -### [Category Name]: X/10 -**Strengths**: [what's working] -**Gaps**: [what's missing] -**Next Steps**: [ordered action items] -``` - -### 4.7 Ready-to-Use Templates - -For every HIGH and MEDIUM priority gap that can be fixed with a file, provide: - -``` -### Template: [Element Name] -**File**: `exact/path/to/create/or/edit` -**Action**: Create | Edit - -[complete file content or edit instructions] -``` - -Templates MUST be specific to the detected tech stack. No generic placeholders. - ---- - -## Phase 5: Await Validation - -**CRITICAL**: Do NOT create or modify any files without explicit approval. - -After presenting the full report, ask: - -"Which of these would you like me to implement? - -- `all` — Implement everything -- `critical` — Only CRITICAL issues -- `high` — CRITICAL + HIGH priority -- `1, 4, 7` — Specific items by number -- `none` — Keep the report for reference - -Your choice:" - -Wait for explicit response. Do not proceed without it. diff --git a/.gitignore b/.gitignore index 07dcac3..7b7c3c0 100644 --- a/.gitignore +++ b/.gitignore @@ -46,4 +46,6 @@ lcov.info *.tgz .turbo/ -devA.md \ No newline at end of file +# Local tooling +.claude/ +.yarn/ diff --git a/.yarn/install-state.gz b/.yarn/install-state.gz deleted file mode 100644 index 35cf106..0000000 Binary files a/.yarn/install-state.gz and /dev/null differ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3e6a71d --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Sofiane Ben Taleb, Noé Wales and Armand Séchon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index adf4b85..4f4e5da 100644 --- a/README.md +++ b/README.md @@ -1,260 +1,262 @@ -# Metaphor +
+ +# 🗻 Metaphor + +**A confidential, automated RWA hub for institutions: bonds tokenized on ADI Chain, negotiated in Canton data rooms the rest of the market cannot see, paid on a Hedera schedule with no keeper, and reviewed by an AI on 0G that never signs.** + +[![ADI Chain](https://img.shields.io/badge/ADI%20Chain-Testnet%20(99999)-2563eb?style=flat-square)](https://explorer.ab.testnet.adifoundation.ai/address/0xab3cbc56d958245a2688b2171417679e743b1daf) +[![Hedera](https://img.shields.io/badge/Hedera-Schedule%20Service%20(0x16b)-7c3aed?style=flat-square)](https://hashscan.io/testnet/contract/0.0.7996912) +[![Canton](https://img.shields.io/badge/Canton-Daml%203.4-0f9d58?style=flat-square)](packages/contracts-canton) +[![0G](https://img.shields.io/badge/0G-Compute-1a1a1a?style=flat-square)](packages/ai-engine) +[![Solidity](https://img.shields.io/badge/Solidity-0.8.24%20%C2%B7%20Foundry-363636?style=flat-square)](packages/contracts-adi) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](LICENSE) + +🏅 **Finalist — ADI Foundation, Open Project Submission ($300) · ETHDenver 2026** + +**[Video demo](https://youtu.be/Dr8bLcU3o6A)** · **[Specification](./docs/SPEC.md)** · **[Bounty compliance](./docs/BOUNTY_COMPLIANCE.md)** · **[Demo guide](./docs/DEMO_GUIDE.md)** + +
+ +Institutions that tokenize bonds on a public chain show their positions to the whole market, pay +coupons from a cron job on a server, and run risk analysis in spreadsheets that never see the ledger. +Metaphor gives each of those jobs to the chain built for it, behind a single dashboard: issuance and +access control on ADI Chain, confidential negotiation on Canton, coupon payments scheduled by the +Hedera network itself, and risk analysis on 0G Compute with a human approving every recommendation. +Four chains, one interface. + +> 🏅 **Finalist on the ADI Foundation bounty at [ETHDenver 2026](https://ethdenver2026.devfolio.co/), Denver, February 2026.** +> One of the flagship Ethereum events of the year, with 186 projects submitted to its BUIDLathon. +> Three students from DeVinci Blockchain built Metaphor there for the New France Village track and +> four sponsor bounties at once (ADI Foundation, Canton Network, Hedera and 0G Labs), and it was named +> a finalist on ADI Foundation's $25,000 Open Project Submission bounty. + +## Table of contents + +- [How it works](#how-it-works) +- [Four chains, one interface](#four-chains-one-interface) +- [Architecture](#architecture) +- [Deployed contracts](#deployed-contracts) +- [What's live vs. simulated](#whats-live-vs-simulated) +- [Getting started](#getting-started) +- [Tests](#tests) +- [Tech stack](#tech-stack) +- [Repository structure](#repository-structure) +- [Team](#team) +- [License](#license) + +## How it works + +The life of a tokenized bond, from issuance to coupon: + +1. **Issue on ADI Chain.** An issuer mints an ERC-20 through `RWATokenFactory`, with the ISIN, coupon + rate, maturity and issuer written on chain. A transfer only settles when both wallets are + whitelisted, and a token can be fractionalized into sub-tokens. +2. **Hold it in a vault.** `VaultManager` groups tokens into vaults (create, deposit, withdraw, + allocate) behind four on-chain roles, Admin, Issuer, Investor and Auditor, and an emergency pause. +3. **Negotiate on Canton.** The data room is a Daml contract. The owner sees everything, + counterparties see the composition and propose trades, an auditor holds a separate `AuditRight` + with aggregate figures only, and for everyone else the contract does not exist. +4. **Pay the coupons on Hedera.** `CouponScheduler` registers the bond, derives its payment dates and + schedules each coupon from Solidity through the Schedule Service precompile at `0x16b`: the network + itself calls the payment on its date, with no keeper and no cron job. A payment is all or nothing: + without enough liquidity it is marked failed, never paid in part. The issuer then distributes the + coupon pro rata to holders through `YieldDistributor`, from a snapshot. +5. **Review the risk on 0G.** The AI engine sends the vault to 0G Compute and gets back a risk report + validated against a schema: a global score, an analysis per position, stress tests and + recommendations. Each recommendation waits for a human approval, and the AI has no signing + authority. + +Institutions come in as tenants: `InstitutionRegistry` gives each one its own isolated set of +contracts (access control, token factory, vault manager), and registering an institution takes two +admin approvals. Signing in is a wallet signature (EIP-191) exchanged for a 24-hour JWT whose roles are +read on chain. + +## Four chains, one interface + +| Layer | Where | What runs there | +|---|---|---| +| Issuance and access | **ADI Chain** (99999), also on Sepolia | `InstiVaultAccessControl` (four roles, whitelist) · `RWAToken` · `RWATokenFactory` · `VaultManager` · `InstitutionRegistry` (white-label tenants, two approvals) · `InstitutionDeployer` | +| Confidentiality | **Canton** (Daml) | nine templates in three modules: `ConfidentialVault` (vault, invitation, access right, trade request, settlement), `PrivateTrade` (multi-round offers, agreement), `AuditRight` (invitation, aggregate-only view) | +| Automation | **Hedera Testnet** | `CouponScheduler` (payment dates, scheduling through `IHRC755` and `IHRC1215`) · `YieldDistributor` (snapshot, pro-rata claims) | +| Intelligence | **0G Compute** | `ai-engine`: risk analyzer, strategy simulator and stress tests, reports validated with Zod, a deterministic mock as fallback | + +On Canton the visibility is enforced by the ledger, not hidden by the interface: -## Built for ETHDenver 2026 — New France Village Track - -Metaphor was developed for ETHDenver 2026, targeting 4 bounties: **ADI Foundation**, **Canton Network**, **Hedera**, and **0G Labs**, as well as the **New France Village** main track. The hackathon challenges developers to build real-world applications across multiple blockchain ecosystems. Metaphor addresses the fundamental complexity of institutional RWA (Real World Assets) management by unifying tokenization, confidential trading, automated yield payments, and AI-powered risk analysis into a single platform — 4 chains, 1 interface. - -## The problem Metaphor solves - -Institutions tokenizing real-world assets (bonds, invoices, real estate) face three obstacles that no single platform addresses today: - -1. **Confidentiality** — Investment strategies and portfolio compositions are exposed on public blockchains. Institutions cannot negotiate without revealing their hand to the entire market. -2. **Automation** — Coupon and yield payments depend on centralized off-chain servers (cron jobs), creating single points of failure and operational risk. -3. **Intelligence** — Risk analysis of RWA portfolios remains manual, fragmented across spreadsheets, and disconnected from on-chain data. - -Metaphor is intentionally integrated: issuers tokenize assets on ADI chain with on-chain metadata (ISIN, coupon rate, maturity), negotiate in Canton confidential data rooms where visibility is enforced at the protocol level, schedule coupon payments deterministically via Hedera's Schedule Service precompile, and analyze portfolio risk through 0G Compute with human-in-the-loop approval. No intermediaries, no manual settlements, no cron jobs. The entire lifecycle — from issuance to maturity — is trustless, automated, and confidential because each layer is built natively on the right chain for the job. - -## Challenges we ran into - -Building a full-stack institutional platform across 4 different blockchain ecosystems presented several learning curves: - -- **Hedera Address Format**: On Hedera, `msg.sender` resolves to the ECDSA-derived alias address, not the long-zero format from `AccountId.toSolidityAddress()`. Our deploy scripts passed the wrong format to `Ownable`, so `onlyOwner` checks always reverted. We had to derive the ECDSA alias via `PrivateKey.publicKey.toEvmAddress()` for all admin addresses. -- **Canton Visibility Model**: Implementing true privacy in Daml — where the auditor's transaction tree literally doesn't contain counterparty data (it's not hidden, it doesn't exist) — required rethinking how we structure templates and party roles. -- **Multi-Chain Orchestration**: Coordinating authentication, role-checking, and data fetching across ADI Chain (ethers.js), Hedera (SDK + EVM), Canton (Daml HTTP JSON API), and 0G Labs (Compute SDK) from a single Express backend. -- **EIP-170 Bytecode Limit**: `InstitutionRegistry` exceeded the contract size limit, requiring an external `InstitutionDeployer` pattern to separate deployment logic. -- **Schedule Service Precompile**: Calling Hedera's `0x16b` precompile (IHRC755 + IHRC1215) directly from Solidity for coupon scheduling — no documentation examples existed for this pattern. - -## Links - -- **GitHub Repository**: [github.com/DVB-ANS/ETH-DENVER](https://github.com/DVB-ANS/ETH-DENVER) -- **Youtube Presentation**: https://youtu.be/Dr8bLcU3o6A - -## What is Metaphor's unique value proposition? - -Metaphor turns institutional RWA management into a unified workflow across 4 specialized chains. Issuers tokenize once on ADI chain, negotiate confidentially on Canton, automate coupon payments on Hedera, and analyze risk via 0G Compute — all from one dashboard. Unlike platforms that force everything onto a single chain (sacrificing privacy or automation), Metaphor uses each chain for what it does best: +``` +Owner (signatory) full access: manage parties, trade, settle +Counterparty (observer) sees the vault composition, proposes trades +Auditor separate AuditRight contract, aggregate data only +Everyone else nothing: the contract does not exist for them +``` -- **ADI Chain**: ERC-20 tokens with on-chain RWA metadata (ISIN, rate, maturity) + RBAC + multi-tenant white-label with 2-of-N multisig governance -- **Canton/Daml**: Protocol-level privacy — the same vault shows different data to owners, counterparties, and auditors. Not UI hiding — ledger-enforced -- **Hedera**: Deterministic coupon payments via Schedule Service precompile `0x16b`, called directly from Solidity. No cron jobs, no off-chain servers -- **0G Labs**: Structured risk reports (Zod-validated) with stress tests and recommendations. AI never signs transactions — humans approve everything +Three things the build had to get right: -The product proves it end-to-end: tokenize an asset, create a vault, invite counterparties to a private data room, schedule automated coupon payments, run AI analysis, and approve or reject recommendations — all on-chain, all auditable, all from a single interface. +- **The Hedera sender.** Inside the EVM, `msg.sender` is the ECDSA alias of the account, not the + long-zero address returned by `AccountId.toSolidityAddress()`. Every script derives the owner from + the public key; with the long-zero form, `onlyOwner` always reverts. +- **Scheduling from Solidity.** The coupons are scheduled by calling the `0x16b` precompile directly + from the contract, a pattern with no example in the Hedera documentation at the time. +- **The contract size limit.** `InstitutionRegistry` outgrew the EIP-170 bytecode limit, so deploying a + tenant's contracts moved to the external `InstitutionDeployer`. -## Who is the target customer? +## Architecture -**Primary**: Asset managers, private banks, and family offices managing $50M-$500M in fixed income portfolios who need: -- **Confidential negotiation** without exposing strategies on public chains -- **Automated yield distribution** without operational overhead -- **On-chain compliance** with KYC-whitelisted transfers and role-based access +``` + Next.js dashboard (:3000) + RainbowKit · wagmi · viem · 10 pages + │ + │ EIP-191 sign-in, JWT bearer + ▼ + Express API (:3001) + on-chain roles · RBAC · aggregated v1 API + ┌────────────────┬───────┴───────┬────────────────┐ + ethers.js ethers.js JSON API 0G broker + │ │ │ │ + ADI Chain Hedera Canton 0G Compute + (99999) Testnet Daml inference + 6 contracts 2 contracts 9 templates risk reports +``` -**Secondary**: Corporate treasurers issuing $1M-$50M bonds where traditional underwriting fees (2-5%) are prohibitive, and regulators who benefit from on-chain audit trails with controlled visibility. +The backend is the only component that talks to the four networks: ethers.js for ADI Chain and for +Hedera's JSON-RPC relay, the JSON API for the Daml ledger, and the 0G serving broker for inference. Its +aggregated `v1` API feeds the dashboard and falls back to demo data when a network is unreachable. -## Who are the closest competitors and how is Metaphor different? +## Deployed contracts -Closest competitors include Securitize (Ethereum/Polygon tokenization), Ondo Finance (tokenized treasuries), and Centrifuge (real-world asset financing). These solutions either: -1. **Expose everything publicly**: Single-chain platforms can't enforce privacy at the protocol level -2. **Rely on off-chain servers**: Coupon payments triggered by cron jobs create single points of failure -3. **Lack AI integration**: Risk analysis is disconnected from on-chain portfolio data +**ADI Chain testnet** (chain 99999, [explorer](https://explorer.ab.testnet.adifoundation.ai/)) and +**Ethereum Sepolia** (chain 11155111): -Metaphor eliminates all three: -- **Protocol-level privacy**: Canton/Daml enforces visibility at the ledger — auditors can't see what they shouldn't, even with full database access -- **On-chain automation**: Hedera Schedule Service precompile executes payments deterministically from Solidity -- **Integrated intelligence**: 0G Compute analyzes actual portfolio composition with structured, actionable output — and the AI never has signing authority +| Contract | ADI Chain | Sepolia | +|---|---|---| +| `InstiVaultAccessControl` | [`0x8e7d4e14…dd656d`](https://explorer.ab.testnet.adifoundation.ai/address/0x8e7d4e14583a37770c743d33092bbcc4e3dd656d) | [`0x6ccfbc2c…f05043`](https://sepolia.etherscan.io/address/0x6ccfbc2c0d3a794938258d760cba69adbef05043) | +| `RWATokenFactory` | [`0x0ed29f8c…5d7d65`](https://explorer.ab.testnet.adifoundation.ai/address/0x0ed29f8c992bb10515296a301b27cd8f0a5d7d65) | [`0xe6c7cccc…36921b`](https://sepolia.etherscan.io/address/0xe6c7ccccf0ea80816cd4e8fad70270cf5836921b) | +| `VaultManager` | [`0x6b6449bd…c1534f`](https://explorer.ab.testnet.adifoundation.ai/address/0x6b6449bdec04dd8717ac71565c7c065680c1534f) | [`0xa162023b…6b8044`](https://sepolia.etherscan.io/address/0xa162023bd4267a5649025f616016a6ea4f6b8044) | +| `InstitutionRegistry` | [`0xab3cbc56…3b1daf`](https://explorer.ab.testnet.adifoundation.ai/address/0xab3cbc56d958245a2688b2171417679e743b1daf) | [`0x442ec1e3…031002`](https://sepolia.etherscan.io/address/0x442ec1e3079e6db66c24af692b43e7b756031002) | +| `InstitutionDeployer` | [`0x6804fc93…66179b`](https://explorer.ab.testnet.adifoundation.ai/address/0x6804fc931cc3db9543b07581c3aedcf1fa66179b) | [`0x531d24ca…1bb274`](https://sepolia.etherscan.io/address/0x531d24caee73fcabe1486036821d85b3111bb274) | -## Technology Stack +**Hedera Testnet:** -### Smart Contracts (ADI Chain — Solidity) -- **Foundry**: Build, test, and deploy framework -- **OpenZeppelin v5.5**: ERC-20, AccessControl, Pausable base contracts -- **Solidity 0.8.24**: 6 contracts, 111 tests passing +| Contract | Hedera ID | EVM address | +|---|---|---| +| `CouponScheduler` | [`0.0.7996912`](https://hashscan.io/testnet/contract/0.0.7996912) | `0x…007a05f0` | +| `YieldDistributor` | [`0.0.7996914`](https://hashscan.io/testnet/contract/0.0.7996914) | `0x…007a05f2` | -### Smart Contracts (Hedera — Solidity + SDK) -- **Hedera Smart Contract Service**: EVM-compatible execution -- **Schedule Service Precompile (0x16b)**: IHRC755 + IHRC1215 interfaces -- **Hedera SDK (TypeScript)**: Deployment and interaction scripts -- **Solidity 0.8.24**: 2 contracts, 74 tests passing +The twelve contracts were still deployed on 16 September 2026. The Daml package runs on a local Canton +sandbox, set up as described in [`packages/contracts-canton`](packages/contracts-canton/README.md). -### Smart Contracts (Canton — Daml) -- **Daml SDK 2.10.3**: Native Daml templates with party-scoped visibility -- **3 modules, 9 templates**: ConfidentialVault, PrivateTrade, AuditRight -- **28 tests passing**: Visibility separation verified +## What's live vs. simulated -### AI Engine (0G Labs) -- **0G Compute**: Decentralized inference for risk analysis -- **OpenAI SDK**: Compatible client for 0G broker -- **Zod**: Schema validation for structured AI output -- **TypeScript**: Risk analyzer + strategy simulator +- **On chain:** the ADI contracts on ADI Chain testnet and Sepolia, and `CouponScheduler` and + `YieldDistributor` on Hedera Testnet, where `CouponScheduler` holds five registered bonds with their + coupon dates computed on chain. +- **Canton:** the Daml contracts pass 28 Daml Script tests and run on a local sandbox. The deployment + on Canton's Devnet L1 asked for by the bounty was not done. +- **0G:** the engine calls 0G Compute when a provider is configured, and otherwise returns a + deterministic mock report (`ZG_USE_MOCK=true` in `.env.example`). +- **Dashboard:** the aggregated API reads the contracts and falls back to demo data when a network is + unreachable or empty, so parts of the dashboard can show demo figures. +- **No hosted deployment:** the product is shown in the [video demo](https://youtu.be/Dr8bLcU3o6A) and + runs locally with the steps below. -### Backend (Express) -- **Express.js**: RESTful API bridging all 4 chains -- **ethers.js 6**: ADI Chain + Hedera contract interaction -- **JWT (jsonwebtoken)**: Wallet-based authentication with on-chain role embedding -- **TypeScript (ESM)**: Strict mode, modern module system +## Getting started -### Frontend (Next.js) -- **Next.js 16.1**: App Router with 10 pages -- **TailwindCSS 4**: Utility-first styling -- **RainbowKit + wagmi 2.x + viem 2.x**: Wallet connection and Web3 integration -- **Recharts 3**: Portfolio and risk visualization charts -- **GSAP + Motion**: Scroll animations on landing page -- **shadcn/ui**: Component library +Prerequisites: Node 20+, pnpm 9+ and Foundry. The Canton package also needs Java 17+ and DPM with the +Daml SDK 3.4.11, see [`packages/contracts-canton`](packages/contracts-canton/README.md). -### Infrastructure -- **pnpm workspaces**: Monorepo with 6 packages -- **Node.js 20+**: Runtime requirement -- **Forge + Vitest**: Solidity and TypeScript testing +```bash +git clone --recurse-submodules https://github.com/DVB-ANS/Metaphor.git +cd Metaphor +pnpm install -## Architecture Overview +cp .env.example .env # RPC endpoints, keys and deployed addresses, for every package +set -a && source .env && set +a -``` - FRONTEND (Next.js :3000) - ├── 10 pages (App Router) - ├── RoleGate + route-access.ts - ├── auth-context (JWT + wagmi) - └── RainbowKit (wallet connect) - | - | fetch + JWT Bearer - v - BACKEND (Express :3001) - ├── middleware/auth.ts (JWT verify) - ├── middleware/rbac.ts (on-chain roles) - ├── routes/v1.ts (aggregated API) - └── services/ (ai-client, canton-client) - / | | \ - ethers.js ethers.js HTTP 0G SDK - | | | | - ADI Chain Hedera Canton 0G Labs - (99999) Testnet Devnet Compute - | | | | - 6 contracts 2 contracts 3 Daml risk-analyzer - 111 tests 74 tests 28 tests ~20 tests +pnpm dev:backend # Express API on http://localhost:3001 +pnpm dev:frontend # Next.js on http://localhost:3000 ``` -### Authentication Flow -1. User connects wallet (RainbowKit) -2. Frontend requests nonce → Backend generates nonce (5 min expiry) -3. User signs EIP-191 message → Frontend submits signature -4. Backend verifies signature + fetches roles on-chain via `hasRole()` -5. JWT returned with address + roles (24h expiry) -6. All API requests include JWT Bearer token +With `DEV_MODE=true`, `POST /api/auth/dev-login` returns a JWT holding the four roles, the quickest way +to open every page locally. -### Monorepo Structure +To deploy your own contracts, from the same shell: +```bash +# ADI Chain, or Sepolia with ADI_RPC_URL pointing at a Sepolia RPC +cd packages/contracts-adi +forge script script/Deploy.s.sol --rpc-url "$ADI_RPC_URL" --broadcast # signs with ADI_PRIVATE_KEY +cd ../.. + +# Hedera Testnet, with HEDERA_OPERATOR_ID and HEDERA_OPERATOR_KEY +pnpm --filter contracts-hedera run deploy +pnpm --filter contracts-hedera run register-bond +pnpm --filter contracts-hedera run schedule + +# Canton, on a local sandbox (ledger API on 6865, JSON API on 7575) +pnpm build:canton +pnpm --filter contracts-canton run sandbox ``` -packages/ -├── contracts-adi/ # Foundry — 6 Solidity contracts (ADI chain) -├── contracts-hedera/ # Solidity + Hedera SDK (coupon automation) -├── contracts-canton/ # Daml templates (confidential vaults) -├── ai-engine/ # TypeScript (0G Compute risk analysis) -├── backend/ # Express API (bridges all 4 chains) -└── frontend/ # Next.js dashboard (10 pages) -``` - -## Deployed Contracts - -### ADI Chain (Chain ID: 99999) - -| Contract | Address | Explorer | -|----------|---------|---------| -| InstiVaultAccessControl | `0x8E7D...656d` | [View](https://explorer.ab.testnet.adifoundation.ai/address/0x8E7D4E14583a37770C743D33092bbCC4E3Dd656d) | -| RWATokenFactory | `0x0eD2...7d65` | [View](https://explorer.ab.testnet.adifoundation.ai/address/0x0eD29f8c992bB10515296A301B27cd8F0a5d7d65) | -| VaultManager | `0x6b64...534f` | [View](https://explorer.ab.testnet.adifoundation.ai/address/0x6b6449bDEC04dd8717AC71565C7c065680C1534f) | -| InstitutionRegistry | `0xAB3C...1daF` | [View](https://explorer.ab.testnet.adifoundation.ai/address/0xAB3Cbc56D958245a2688b2171417679e743B1daF) | - -### Hedera Testnet - -| Contract | Account ID | Explorer | -|----------|------------|---------| -| CouponScheduler | `0.0.7996912` | [View](https://hashscan.io/testnet/contract/0.0.7996912) | -| YieldDistributor | `0.0.7996914` | [View](https://hashscan.io/testnet/contract/0.0.7996914) | -### Canton (Daml) +## Tests -| Module | Templates | -|--------|-----------| -| ConfidentialVault | ConfidentialVault, VaultInvitation, VaultAccessRight, TradeRequest, TradeSettlement | -| PrivateTrade | TradeProposal, TradeAgreement | -| AuditRight | AuditInvitation, AuditRight | - -## Setup - -### Prerequisites - -- Node.js 20+ -- pnpm 9+ -- Foundry (`curl -L https://foundry.paradigm.xyz | bash && foundryup`) -- A Hedera Testnet account ([portal.hedera.com](https://portal.hedera.com)) - -### Installation +| Package | Framework | Tests | +|---|---|---| +| `contracts-adi` | Forge | 111 | +| `contracts-hedera` | Forge | 74 | +| `contracts-canton` | Daml Script | 28 | +| `ai-engine` | Vitest | 21 | ```bash -# Clone and install -git clone https://github.com/DVB-ANS/ETH-DENVER.git -cd ETH-DENVER -pnpm install - -# Configure environment -cp .env.example .env -# Edit .env with your keys (see .env.example for all variables) +pnpm test # the four suites +pnpm test:adi # or one at a time: test:hedera, test:canton, test:ai ``` -### Run Locally - -```bash -# Terminal 1 — Backend API -pnpm dev:backend # Express on http://localhost:3001 - -# Terminal 2 — Frontend -pnpm dev:frontend # Next.js on http://localhost:3000 -``` +The Forge and Vitest suites were run again on 16 September 2026, 206 tests passing; the Daml suite +needs DPM. -Open [http://localhost:3000](http://localhost:3000) to see the app. +## Tech stack -### Run Tests +| Layer | Technology | +|---|---| +| ADI contracts | Solidity 0.8.24, Foundry, OpenZeppelin 5.5 | +| Hedera contracts | Solidity 0.8.24, Foundry, the Schedule Service system contract (`IHRC755`, `IHRC1215`), Hedera SDK | +| Canton contracts | Daml, SDK 3.4.11, DPM | +| AI engine | 0G Compute (`@0glabs/0g-serving-broker`), OpenAI-compatible client, Zod | +| Backend | Express 4, ethers 6, jsonwebtoken, TypeScript (ESM) | +| Frontend | Next.js 16, React 19, Tailwind CSS 4, shadcn/ui, RainbowKit, wagmi, viem, Recharts, GSAP, Motion | +| Tooling | pnpm workspaces, Forge, Vitest, Prettier | -```bash -pnpm test # All tests (ADI + Hedera + Canton + AI) +## Repository structure -# Or individually: -pnpm test:adi # 111 Solidity tests (Foundry) -pnpm test:hedera # 74 Solidity tests (Foundry) -pnpm test:canton # 28 Daml tests -pnpm test:ai # AI engine tests (Vitest) +``` +packages/ + contracts-adi/ Foundry: roles, RWA tokens, vaults, white-label registry (ADI Chain, Sepolia) + contracts-hedera/ Foundry and Hedera SDK: coupon scheduling, yield distribution, deploy scripts + contracts-canton/ Daml: confidential vaults, private trades, audit rights, sandbox scripts + ai-engine/ 0G Compute client, risk analyzer, strategy simulator, prompts, mock + backend/ Express API: wallet sign-in, RBAC, per-chain routes, aggregated v1 API + frontend/ Next.js dashboard, 10 pages +docs/ + SPEC.md specification: features, data flows, API endpoints, constraints + BOUNTY_COMPLIANCE.md every bounty requirement, with its evidence + DEMO_GUIDE.md the demo walkthrough, with the commands that check each step on chain ``` -## Test Results +## Team -| Package | Framework | Tests | Status | -|---------|-----------|-------|--------| -| contracts-adi | Forge | 111 | All passing | -| contracts-hedera | Forge | 74 | All passing | -| contracts-canton | Daml | 28 | All passing | -| ai-engine | Vitest | ~20 | All passing | -| **Total** | | **213+** | **All passing** | +Three students from **DeVinci Blockchain**, Paris, at ETHDenver 2026. -## Bounties +| | Role | | +|---|---|---| +| **Sofiane Ben Taleb** | frontend and backend | [GitHub](https://github.com/gamween) · [LinkedIn](https://www.linkedin.com/in/sofiane-ben-taleb/) | +| **Noé Wales** | Solidity contracts on ADI Chain and Hedera, backend integration | [GitHub](https://github.com/CHAAIISE) · [LinkedIn](https://www.linkedin.com/in/no%C3%A9-w/) | +| **Armand Séchon** | Daml contracts on Canton, AI engine on 0G | [GitHub](https://github.com/STOOOKEEE) · [LinkedIn](https://www.linkedin.com/in/armand-sechon/) | -| Sponsor | What We Built | Key Proof | -|---------|---------------|-----------| -| **ADI Foundation** | Multi-tenant tokenization platform with RBAC, 2-of-N multisig, and white-label support. 6 contracts deployed on ADI chain (99999) + Sepolia. | Live tokenization tx + vault creation tx + whitelist tx on chain 99999. InstitutionRegistry with isolated contracts per institution. | -| **Canton Network** | Native Daml confidential vaults with 9 templates across 3 modules. Party-scoped visibility enforced at the ledger protocol level. | 3-panel demo: same vault returns different data per role. Auditor's transaction tree doesn't contain counterparty data — it doesn't exist. | -| **Hedera** | On-chain coupon scheduling via Schedule Service precompile (`0x16b`). CouponScheduler + YieldDistributor deployed on Hedera Testnet. | `scheduleCoupon()` calls IHRC755 + IHRC1215 directly from Solidity. 2 bonds registered with automated payment dates. | -| **0G Labs** | Structured risk analysis via 0G Compute with Zod-validated reports, stress tests, and human-in-the-loop approval. | AI returns scored positions + macro stress scenarios. Every recommendation requires explicit user approval — AI never signs transactions. | +## License -## Team +[MIT](LICENSE) © 2026 Sofiane Ben Taleb, Noé Wales and Armand Séchon. The Hedera system-contract +interfaces vendored in `packages/contracts-hedera/contracts/hedera-deps/` keep their Apache-2.0 +license. -| Dev | Scope | -|-----|-------| -| Dev A | Solidity contracts (ADI + Hedera) | -| Dev B | Daml contracts (Canton) + AI engine (0G Labs) | -| Dev C | Frontend (Next.js) + Backend (Express) | - -## Documentation - -- **[SPEC.md](./markdown/SPEC.md)** — Full project specification (features, architecture, data flows, edge cases) -- **[DEPLOY.md](./markdown/DEPLOY.md)** — Step-by-step deployment guide -- **[DEMO_GUIDE.md](./markdown/DEMO_GUIDE.md)** — 20-minute demo walkthrough with terminal commands -- **[BOUNTY_COMPLIANCE.md](./markdown/BOUNTY_COMPLIANCE.md)** — Bounty requirement checklist with evidence -- **[PROJECT_OVERVIEW.md](./markdown/PROJECT_OVERVIEW.md)** — Detailed product overview -- **[DEPLOYED_CONTRACTS.md](./markdown/DEPLOYED_CONTRACTS.md)** — All contract addresses across chains -- **[TIMELINE.md](./markdown/TIMELINE.md)** — Development roadmap and phases +
+Built for ETHDenver 2026 · New France Village track · ADI Foundation, Canton Network, Hedera and 0G Labs bounties +
diff --git a/barque2.jpeg b/barque2.jpeg deleted file mode 100644 index e6f9918..0000000 Binary files a/barque2.jpeg and /dev/null differ diff --git a/carpe koi.jpeg b/carpe koi.jpeg deleted file mode 100644 index ac8802a..0000000 Binary files a/carpe koi.jpeg and /dev/null differ diff --git a/markdown/BOUNTY_COMPLIANCE.md b/docs/BOUNTY_COMPLIANCE.md similarity index 98% rename from markdown/BOUNTY_COMPLIANCE.md rename to docs/BOUNTY_COMPLIANCE.md index 2ced8d0..c675bdb 100644 --- a/markdown/BOUNTY_COMPLIANCE.md +++ b/docs/BOUNTY_COMPLIANCE.md @@ -1,4 +1,4 @@ -# Outward — Bounty Compliance +# Metaphor — Bounty Compliance ## ADI Foundation @@ -6,7 +6,7 @@ | Requirement | Status | Evidence | |---|---|---| -| MVP deployed on ADI chain | Done | Chain 99999 — 5 contracts deployed ([addresses](./DEPLOYED_CONTRACTS.md)) | +| MVP deployed on ADI chain | Done | Chain 99999 — 5 contracts deployed ([addresses](../README.md#deployed-contracts)) | | Also deployed on Sepolia | Done | Chain 11155111 — same 5 contracts | | Real economic utility | Done | Tokenization + vault management + fractional ownership + coupon lifecycle | | White-label ready | Done | `InstitutionRegistry` — multi-tenant, each institution gets isolated contracts | diff --git a/markdown/DEMO_GUIDE.md b/docs/DEMO_GUIDE.md similarity index 99% rename from markdown/DEMO_GUIDE.md rename to docs/DEMO_GUIDE.md index d225a71..a7169c7 100644 --- a/markdown/DEMO_GUIDE.md +++ b/docs/DEMO_GUIDE.md @@ -403,5 +403,5 @@ cd packages/contracts-canton && daml test | AI analysis slow | Set `ZG_USE_MOCK=true` in backend `.env` and restart | | Canton demo shows mock data | That's fine — the demo data shows the same privacy model. Canton sandbox is optional | | "Restricted Access" on a page | Wrong role — use dev-login for all roles | -| Hedera tx reverts | Admin address must be ECDSA alias, not long-zero format (see CLAUDE.md) | +| Hedera tx reverts | Admin address must be ECDSA alias, not long-zero format (see [SPEC.md §8](./SPEC.md#8-edge-cases-and-constraints)) | | Backend crashes on start | Check `pnpm install` was run, check `.env` exists | diff --git a/markdown/SPEC.md b/docs/SPEC.md similarity index 92% rename from markdown/SPEC.md rename to docs/SPEC.md index b97da82..ccc47f2 100644 --- a/markdown/SPEC.md +++ b/docs/SPEC.md @@ -143,7 +143,7 @@ A unified platform where institutions can: BACKEND (Express :3001) / | | \ ADI Chain Hedera Canton 0G Labs - (Testnet) (Testnet) (Devnet) (Compute) + (Testnet) (Testnet) (sandbox) (Compute) ``` ### Monorepo Structure @@ -185,7 +185,7 @@ packages/ | Layer | Technology | Language | |-------|-----------|----------| | ADI contracts | Foundry + OpenZeppelin v5.5 | Solidity 0.8.24 | -| Canton contracts | Daml SDK 2.10.3 | Daml | +| Canton contracts | Daml SDK 3.4.11 (DPM) | Daml | | Hedera contracts | Hedera Smart Contract Service + SDK | Solidity 0.8.24 + TypeScript | | AI engine | 0G Compute + OpenAI SDK | TypeScript | | Frontend | Next.js 16.1 + TailwindCSS 4 + RainbowKit | TypeScript (React 19) | @@ -369,10 +369,10 @@ packages/ | contracts-adi | Forge | 111 | All passing | | contracts-hedera | Forge | 74 | All passing | | contracts-canton | Daml sandbox | 28 | All passing | -| ai-engine | Vitest | ~20 | All passing | +| ai-engine | Vitest | 21 | All passing | | backend | — | 0 | No tests | | frontend | — | 0 | No tests | -| **Total** | | **213+** | | +| **Total** | | **234** | | --- @@ -402,15 +402,14 @@ packages/ - **Fonts**: Space Grotesk (display), Geist Sans (body), Geist Mono (code) - **SSR-safe wallet**: RainbowKit configured for server-side rendering compatibility -### Known Open Items +### Limits at Submission -- Canton contracts not yet deployed to Devnet L1 (code ready, sandbox tested) -- 0G Compute endpoint not configured (running in mock mode) -- Frontend pages built with demo/mock data integration — real API calls partially wired +- Canton contracts run on a local sandbox; the Devnet L1 deployment was not done (code ready, 28 tests) +- 0G Compute runs in mock mode unless a provider is configured (`ZG_USE_MOCK=true` by default) +- Frontend pages fall back to demo data when a service is unreachable; real API calls are partially wired - No CI/CD pipeline - No backend or frontend tests -- No live demo URL (Vercel deployment pending) -- No demo video recorded +- No hosted deployment: the demo is the [video](https://youtu.be/Dr8bLcU3o6A) --- @@ -423,29 +422,3 @@ packages/ - 9 dependency vulnerabilities (all transitive, from 0G SDK and Hedera SDK) - Open CORS policy (demo-only concern) - AI never has signing authority — human-in-the-loop enforced at API level - ---- - -## 10. Audit Summary - -### Health Score: 58/100 (FAIR) - -| Category | Score | Weight | Notes | -|----------|-------|--------|-------| -| Security | 7/10 | x4 | No secrets in code, proper env handling; open CORS, 9 transitive vulns | -| Code Quality | 5/10 | x3 | 213+ contract tests, but no backend/frontend tests; 111 console.log calls; no linting | -| Architecture | 8/10 | x2 | Clean monorepo, clear separation, proper fallbacks, good documentation | -| Dependencies | 6/10 | x2 | Single lockfile, 9 vulns (all transitive), reasonably current | -| Git & DevOps | 4/10 | x2 | No CI/CD, no git hooks, inconsistent commit messages | -| Claude Config | 6/10 | x3 | Good CLAUDE.md, but no hooks/agents/rules, no settings.json | - -### Key Gaps - -1. No CI/CD pipeline (GitHub Actions) -2. No backend or frontend tests -3. No ESLint configuration at root level -4. Open CORS policy -5. 111 console.log statements in source -6. Canton deployment pending -7. 0G Compute not configured (mock only) -8. Missing root README.md (being created) diff --git a/fuji.jpeg b/fuji.jpeg deleted file mode 100644 index 324a775..0000000 Binary files a/fuji.jpeg and /dev/null differ diff --git a/fuji_cerisier.png b/fuji_cerisier.png deleted file mode 100644 index ddc7f91..0000000 Binary files a/fuji_cerisier.png and /dev/null differ diff --git a/logo bandeau/0G Labs.svg b/logo bandeau/0G Labs.svg deleted file mode 100644 index c1bbab3..0000000 --- a/logo bandeau/0G Labs.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/logo bandeau/ADI Foundation.svg b/logo bandeau/ADI Foundation.svg deleted file mode 100644 index 44863d7..0000000 --- a/logo bandeau/ADI Foundation.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/logo bandeau/Canton Network.svg b/logo bandeau/Canton Network.svg deleted file mode 100644 index d13cb28..0000000 --- a/logo bandeau/Canton Network.svg +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/logo bandeau/Ethereum.png b/logo bandeau/Ethereum.png deleted file mode 100644 index c8ac5ec..0000000 Binary files a/logo bandeau/Ethereum.png and /dev/null differ diff --git a/logo bandeau/OpenZeppelin.png b/logo bandeau/OpenZeppelin.png deleted file mode 100644 index cb4f7aa..0000000 Binary files a/logo bandeau/OpenZeppelin.png and /dev/null differ diff --git a/logo.png b/logo.png deleted file mode 100644 index 975bf36..0000000 Binary files a/logo.png and /dev/null differ diff --git a/markdown/A-FAIRE-DANS-FRONT.md b/markdown/A-FAIRE-DANS-FRONT.md deleted file mode 100644 index 7d76dd6..0000000 --- a/markdown/A-FAIRE-DANS-FRONT.md +++ /dev/null @@ -1,11 +0,0 @@ -- Une page about us - - - - -- Landing page : - - enlever les deux images du milieu quand tu scrolles et mettre direct le truc d'après. - - liquid glass - - et enlever le rectaangle plus tot ou qui monte avec le texte en gros - - diff --git a/markdown/AUDIT.md b/markdown/AUDIT.md deleted file mode 100644 index abc98eb..0000000 --- a/markdown/AUDIT.md +++ /dev/null @@ -1,336 +0,0 @@ -# Metaphor — Full Project Audit - -> Date: February 21, 2026 | Branch: `develop` | Commit: `43f495c` - ---- - -## 1. Project Health Score: 52/100 - -| Category | Score | Weight | Details | -|----------|-------|--------|---------| -| Security | 4/10 | x4 | 3 CRITICAL (hardcoded keys, JWT secret fallback), 6 HIGH | -| Smart Contracts | 7/10 | x3 | 1 CRITICAL logic bug, 2 HIGH (DoS vectors), good test coverage | -| Code Quality | 5/10 | x3 | 77+ `any` types, 9 console.log (backend), alert() usage | -| Architecture | 8/10 | x2 | Clean monorepo, proper separation, good fallbacks | -| Testing | 5/10 | x2 | 213+ contract tests, 0 backend tests, 0 frontend tests | -| DevOps | 2/10 | x2 | No CI/CD, no linting pipeline, no pre-commit hooks | -| Documentation | 8/10 | x1 | SPEC.md, README.md, CLAUDE.md all consistent | - ---- - -## 2. Severity Summary - -| Severity | Count | Breakdown | -|----------|-------|-----------| -| **CRITICAL** | 5 | Backend: 3, Contracts: 1, AI: 1 | -| **HIGH** | 12 | Backend: 6, Contracts: 3, Frontend: 3 | -| **MEDIUM** | 18 | Across all packages | -| **LOW** | 12 | Across all packages | -| **TOTAL** | **47** | | - ---- - -## 3. CRITICAL Findings (fix before demo) - -### C1. Hardcoded Private Keys Committed to Git -**Severity:** CRITICAL | **Package:** Backend -**Files:** `packages/backend/.env` (committed), `packages/backend/src/config.ts:34` - -``` -ADI_PRIVATE_KEY=0x086770b56038738eb84b22c53ec2e368a702087ffc2fc77f28d34deb9caaef66 -ZG_PRIVATE_KEY=0xd0c53762ad996f7954a1dd44fb9f4a2fa8301d985cb2622290a666a61172e77d -HEDERA_PRIVATE_KEY fallback: 0x05a0252ccdfea79d6ba3b8a222e365108414f50b6edebc9a6d68dadc0f4d4cf2 -``` - -**Impact:** Complete compromise of ADI signer, 0G account, and Hedera signer. Keys are in git history forever. -**Fix:** Rotate ALL keys immediately. Remove `.env` from git history (BFG/filter-branch). Remove hardcoded fallbacks in `config.ts`. - ---- - -### C2. Hardcoded JWT Secret Fallback -**Severity:** CRITICAL | **Package:** Backend -**File:** `packages/backend/src/middleware/auth.ts:6` - -```typescript -const JWT_SECRET = process.env.JWT_SECRET || 'metaphor-dev-secret'; -``` - -**Impact:** If env var missing, anyone can forge valid JWTs with any role. -**Fix:** Remove fallback. Crash on startup if `JWT_SECRET` is not set. - ---- - -### C3. InstitutionRegistry Proposal ID 0 Bug -**Severity:** CRITICAL | **Package:** contracts-adi -**File:** `InstiVaultAccessControl.sol` — `approveProposal()`, `executeProposal()` - -```solidity -if (p.id == 0 && proposalId != 0) revert ProposalNotFound(proposalId); -``` - -Proposal IDs start at 0 (`_nextProposalId++`). The first proposal can never be approved or executed because `p.id == 0` is true for both uninitialized AND the first valid proposal. - -**Fix:** `if (proposalId >= _nextProposalId) revert ProposalNotFound(proposalId);` - ---- - -### C4. Canton Party Header Impersonation -**Severity:** CRITICAL | **Package:** Backend -**File:** `packages/backend/src/routes/canton.ts:24-25` - -```typescript -function getParty(req: Request): string { - return (req.headers['x-canton-party'] as string) || cantonClient.resolveParty('admin'); -} -``` - -**Impact:** Any user can set `x-canton-party: BNP_Paribas_Admin` header and execute Daml commands as ANY party. Complete authorization bypass on Canton. -**Fix:** Validate header value against authenticated user's wallet/role. - ---- - -### C5. AI Prompt Injection via Custom Scenarios -**Severity:** CRITICAL | **Package:** ai-engine -**File:** `packages/ai-engine/src/strategy-simulator.ts:30-38` - -```typescript -customScenarios.map((s, i) => `${i + 1}. ${s}`) // User input injected into LLM prompt -``` - -**Impact:** Attacker can inject instructions to manipulate risk scores. -**Fix:** Add Zod validation: `z.string().max(200).regex(/^[a-zA-Z0-9\s\+\-\%\.]+$/)`. - ---- - -## 4. HIGH Findings - -| # | Finding | Package | File | -|---|---------|---------|------| -| H1 | Unrestricted CORS (`cors()` with no config) | Backend | `index.ts:40` | -| H2 | Missing input validation on contract calls (addresses, amounts) | Backend | `routes/adi.ts:52,78,89` | -| H3 | No rate limiting on any endpoint | Backend | All routes | -| H4 | AI report file write race condition (concurrent `writeFileSync`) | Backend | `services/ai-client.ts:43` | -| H5 | DEV_MODE auto-provisions all roles on login | Backend | `routes/auth.ts:61-81` | -| H6 | Missing unvalidated vault ID parameter | Backend | `routes/adi.ts:78` | -| H7 | CouponScheduler bond ID 0 validation bug (same pattern as C3) | Contracts | `CouponScheduler.sol:204` | -| H8 | Unbounded loop in `getUnclaimedYield()` — gas DoS | Contracts | `YieldDistributor.sol:143` | -| H9 | Arithmetic underflow risk in `withdraw()` | Contracts | `VaultManager.sol:165` | -| H10 | JWT stored in localStorage (XSS vulnerable) | Frontend | `lib/api.ts:8-17` | -| H11 | No error boundaries in React app | Frontend | Entire app | -| H12 | `alert()`/`confirm()` for critical actions (8 instances) | Frontend | vaults, admin, data-room | - ---- - -## 5. MEDIUM Findings - -| # | Finding | Package | -|---|---------|---------| -| M1 | Error messages leak implementation details to clients | Backend | -| M2 | 24 instances of `any` type in backend | Backend | -| M3 | 9 console.log statements in backend | Backend | -| M4 | Canton JWT unsigned (acceptable for Devnet only) | Backend | -| M5 | Missing pagination on list endpoints | Backend | -| M6 | Missing request body size limit | Backend | -| M7 | Missing ReentrancyGuard on CouponScheduler + YieldDistributor | Contracts | -| M8 | Unbounded arrays: `getAllTokens()`, `getVaultTokens()` | Contracts | -| M9 | RWAToken allows silent burn via `transfer(address(0))` | Contracts | -| M10 | 53+ instances of `any` type in frontend | Frontend | -| M11 | No JWT expiry check on session restore | Frontend | -| M12 | Auth race condition (multiple signIn calls) | Frontend | -| M13 | Optimistic updates without rollback | Frontend | -| M14 | Missing form input validation (Issue page) | Frontend | -| M15 | No React.memo on heavy components | Frontend | -| M16 | 0G client: private key in memory without cleanup | AI Engine | -| M17 | No request timeout on 0G inference calls | AI Engine | -| M18 | GSAP + Motion.js redundancy (~500KB waste) | Frontend | - ---- - -## 6. Package-by-Package Status - -### contracts-adi (Solidity) -| Metric | Value | -|--------|-------| -| Contracts | 6 | -| Tests | 111 passing | -| Deployed | ADI Chain (99999) + Sepolia | -| Critical bugs | 1 (proposal ID 0) | -| Missing | Pagination on view functions, ReentrancyGuard | - -### contracts-hedera (Solidity) -| Metric | Value | -|--------|-------| -| Contracts | 2 (+5 deps) | -| Tests | 74 passing | -| Deployed | Hedera Testnet (live) | -| Critical bugs | 0 (but bond ID 0 HIGH) | -| Missing | Pagination on getUnclaimedYield, ReentrancyGuard | - -### contracts-canton (Daml) -| Metric | Value | -|--------|-------| -| Modules | 3 | -| Tests | 28 passing | -| Deployed | NOT DEPLOYED (sandbox only) | -| Critical bugs | 0 | -| Missing | Cross-party attack tests, Devnet deployment | - -### ai-engine (TypeScript) -| Metric | Value | -|--------|-------| -| Files | 8 source + 2 prompts | -| Tests | ~20 passing | -| Mode | Mock only (0G not configured) | -| Critical bugs | 1 (prompt injection) | -| Missing | Request timeouts, key cleanup | - -### backend (Express) -| Metric | Value | -|--------|-------| -| Routes | 8 files, 50+ endpoints | -| Tests | 0 | -| Running | Yes (port 3001) | -| Critical bugs | 3 (keys, JWT, party header) | -| Missing | Rate limiting, input validation, CORS config, tests | - -### frontend (Next.js) -| Metric | Value | -|--------|-------| -| Pages | 10 | -| Components | 31 UI + 3 layout | -| Tests | 0 | -| Running | Yes (port 3000) | -| Critical bugs | 0 (HIGH: localStorage JWT) | -| Missing | Error boundaries, form validation, tests | - ---- - -## 7. Bounty Compliance Checklist - -### ADI Foundation -| Requirement | Status | Gap | -|-------------|--------|-----| -| MVP on ADI chain | DEPLOYED | - | -| Real economic utility | YES (tokenization + vaults) | - | -| White-label ready | YES (InstitutionRegistry) | Proposal ID 0 bug (C3) | -| RBAC/multisig | YES (4 roles + 2-of-N) | First proposal blocked | - -### Canton Network -| Requirement | Status | Gap | -|-------------|--------|-----| -| Native Daml (no wrappers) | YES | - | -| Deployed on Devnet L1 | **NO** | Code ready, 28 tests, not deployed | -| Visibility separation demo | YES (3-panel demo page) | Party header bypass (C4) | - -### Hedera -| Requirement | Status | Gap | -|-------------|--------|-----| -| Schedule Service usage | YES (0x16b precompile) | - | -| Coupon payments | YES (2 bonds registered) | Bond ID 0 bug (H7) | -| Initiated from smart contract | YES (CouponScheduler) | - | - -### 0G Labs -| Requirement | Status | Gap | -|-------------|--------|-----| -| 0G Compute inference | CODE READY | Not configured (mock mode) | -| Structured decisions | YES (Zod-validated reports) | - | -| Human-in-the-loop approval | YES (approve/reject) | Prompt injection risk (C5) | - ---- - -## 8. Test Coverage Matrix - -| Package | Unit | Integration | E2E | Total | -|---------|------|-------------|-----|-------| -| contracts-adi | 111 | 0 | 0 | 111 | -| contracts-hedera | 74 | 0 | 1 (e2e-test.ts) | 75 | -| contracts-canton | 28 | 0 | 0 | 28 | -| ai-engine | ~20 | 0 | 0 | ~20 | -| backend | 0 | 0 | 0 | **0** | -| frontend | 0 | 0 | 0 | **0** | -| **Total** | **213+** | **0** | **1** | **234** | - -### Untested Critical Paths -1. Backend auth flow (nonce -> signature -> JWT) -2. Backend contract interaction error handling -3. Frontend role-gating behavior -4. Frontend form submission flows -5. AI report lifecycle (analyze -> approve -> reject) -6. Canton trade settlement -7. Hedera coupon payment recovery (`recoverPayment`) -8. VaultManager concurrent allocate + withdraw - ---- - -## 9. Priority Action Plan - -### IMMEDIATE (before demo) - -``` -1. [ ] ROTATE ALL PRIVATE KEYS (ADI, Hedera, 0G) -2. [ ] Remove .env from git history -3. [ ] Remove JWT_SECRET and HEDERA_PRIVATE_KEY fallbacks -4. [ ] Fix InstitutionRegistry proposal ID 0 bug -5. [ ] Fix Canton party header validation -6. [ ] Add CORS restrictions (whitelist localhost:3000) -``` - -### BEFORE SUBMISSION - -``` -7. [ ] Deploy Canton contracts to Devnet L1 -8. [ ] Configure 0G Compute endpoint (exit mock mode) -9. [ ] Add input validation on backend routes -10. [ ] Add rate limiting middleware -11. [ ] Fix CouponScheduler bond ID 0 validation -12. [ ] Add error boundaries to frontend -13. [ ] Replace alert()/confirm() with Dialog components -14. [ ] Add Zod validation to AI custom scenarios -``` - -### NICE TO HAVE - -``` -15. [ ] Add CI/CD pipeline (.github/workflows) -16. [ ] Add backend tests (auth, routes) -17. [ ] Add frontend tests (role-gating, forms) -18. [ ] Add pagination to unbounded view functions -19. [ ] Add ReentrancyGuard to Hedera contracts -20. [ ] Replace localStorage JWT with httpOnly cookies -21. [ ] Remove unused three.js dependency -22. [ ] Replace 53+ `any` types with proper interfaces -23. [ ] Add structured logging (replace console.log) -``` - ---- - -## 10. Architecture Diagram - -``` - FRONTEND (Next.js :3000) - ├── 10 pages (App Router) - ├── RoleGate + route-access.ts - ├── auth-context (JWT + wagmi) - └── RainbowKit (wallet connect) - | - | fetch + JWT Bearer - v - BACKEND (Express :3001) - ├── middleware/auth.ts (JWT verify) - ├── middleware/rbac.ts (on-chain roles) - ├── routes/v1.ts (aggregated API) - └── services/ (ai-client, canton-client) - / | | \ - ethers.js ethers.js HTTP 0G SDK - | | | | - ADI Chain Hedera Canton 0G Labs - (99999) Testnet Devnet Compute - | | | | - 6 contracts 2 contracts 3 Daml risk-analyzer - 111 tests 74 tests 28 tests ~20 tests - DEPLOYED DEPLOYED NOT YET MOCK MODE -``` - ---- - -*Generated by Claude Opus 4.6 — Full codebase audit across 6 packages, 47 findings.* diff --git a/markdown/CLAUDE.md b/markdown/CLAUDE.md deleted file mode 100644 index 93593c5..0000000 --- a/markdown/CLAUDE.md +++ /dev/null @@ -1,118 +0,0 @@ -# Metaphor — Claude Context - -## Project - -Metaphor is a confidential, automated RWA (Real World Assets) hub for institutional finance. Built for ETHDenver 2026, New France Village track. Targeting 4 bounties: ADI Foundation, Canton Network, Hedera, 0G Labs. - -**Documentation:** -- [Project Overview](./markdown/PROJECT_OVERVIEW.md) -- [Timeline](./markdown/TIMELINE.md) - -## Team - -3 developers working in parallel: -- **Dev A** — Solidity (ADI + Hedera contracts) -- **Dev B** — Daml (Canton) + AI (0G Labs) -- **Dev C** — Frontend (Next.js) + Backend (Express) - -## Monorepo Structure - -``` -packages/ -├── contracts-adi/ # Foundry — Solidity (ADI chain) -├── contracts-canton/ # Daml (Canton Devnet L1) -├── contracts-hedera/ # Solidity + Hedera SDK (Hedera Testnet) -├── ai-engine/ # TypeScript (0G Compute) -├── backend/ # Express API (TypeScript) -└── frontend/ # Next.js + TailwindCSS + RainbowKit -``` - -## Tech Stack - -| Layer | Tech | Language | -|-------|------|----------| -| ADI contracts | Foundry + OpenZeppelin v5.5 | Solidity 0.8.24 | -| Canton contracts | Daml SDK | Daml | -| Hedera contracts | Hedera Smart Contract Service + SDK | Solidity + TypeScript | -| AI engine | 0G Compute | TypeScript | -| Frontend | Next.js + TailwindCSS | TypeScript | -| Backend | Express | TypeScript | -| Package manager | pnpm workspaces | — | - -## Git Workflow - -``` -main ← version stable, déployable (on ne push JAMAIS directement ici) -└── develop ← branche d'intégration quotidienne (tous les PRs mergent ici) - ├── feat/adi-* ← Dev A - ├── feat/hedera-* ← Dev A - ├── feat/canton-* ← Dev B - ├── feat/ai-* ← Dev B - ├── feat/frontend-* ← Dev C - └── feat/backend-* ← Dev C -``` - -### Règles -1. **Toujours** créer sa feature branch depuis `develop` (`git checkout develop && git checkout -b feat/...`) -2. **PR vers `develop`**, jamais directement vers `main` -3. `main` est mis à jour uniquement quand `develop` est stable (avant démo, avant soumission) -4. Préfixes de commit : `feat:`, `fix:`, `test:`, `docs:`, `chore:` - -## Key Contracts - -### ADI (Solidity) — Deployed on Sepolia + ADI Chain (99999) -- `InstiVaultAccessControl.sol` — RBAC: Admin, Issuer, Investor, Auditor + whitelisting -- `RWAToken.sol` — ERC-20 with RWA metadata (ISIN, rate, maturity, issuer) + whitelist transfer restrictions -- `RWATokenFactory.sol` — Factory for creating RWA tokens + fractionalization -- `VaultManager.sol` — Vault lifecycle (create, deposit, withdraw, allocate) + multi-token + Pausable -- `InstitutionRegistry.sol` — Multi-tenant white-label registry + 2-of-N multisig proposals -- `InstitutionDeployer.sol` — External deployer (EIP-170 workaround) - -### Canton (Daml) -- `ConfidentialVault` — Private vault with party-scoped visibility -- `PrivateTrade` — Bilateral offer/counter-offer -- `AuditRight` — Limited third-party audit access - -### Hedera (Solidity) — Deployed on Hedera Testnet -- `CouponScheduler.sol` — Scheduled coupon payments via Hedera Schedule Service precompile (0x16b), access-controlled execution (self-call / issuer / owner) + Pausable -- `YieldDistributor.sol` — Snapshot-based pro-rata yield distribution to bond holders -- `HederaScheduleService.sol` — Abstract base for Hedera precompile interaction (IHRC755 + IHRC1215) - -## Typography - -- **Display font**: Space Grotesk (`font-display`) — used for landing page title, subtitle, glass text, and CTA button -- **Body font**: Geist Sans (`font-sans`) — used for all UI/body text -- **Mono font**: Geist Mono (`font-mono`) — used for code/data - -## Conventions - -- Solidity: Foundry for build/test, OpenZeppelin for base contracts -- TypeScript: strict mode, ESNext target, bundler module resolution -- Formatting: Prettier (single quotes, trailing commas, 100 char width) -- No secrets in repo — use `.env` (template in `.env.example`) -- All user-facing text across the entire site must be in English. All units must use the imperial system. - -## Known Bugs / Blockers - -### Hedera — `registerBond` reverts (`CONTRACT_REVERT_EXECUTED`) - -**Status**: FIXED — redeploy required (`pnpm deploy` in `packages/contracts-hedera`) - -**Root cause**: On Hedera, `msg.sender` in the EVM resolves to the **ECDSA-derived alias address** (keccak256 of the public key, e.g. `0x40a1Db6B...`), NOT the long-zero address from `AccountId.toSolidityAddress()` (e.g. `0x0000...79af01`). The deploy script was passing the long-zero format to the `Ownable` constructor, so `onlyOwner` checks always failed because `msg.sender != owner()`. - -**Fix applied**: `deploy.ts` now uses `PrivateKey.publicKey.toEvmAddress()` to derive the ECDSA alias and passes it as the `admin` constructor parameter. All scripts updated to use `getOperatorEvmAddress()` from `config.ts`. This ensures `owner()` stores the same address format as `msg.sender`. - -**IMPORTANT — Hedera address convention**: Never use `AccountId.toSolidityAddress()` for addresses that will be compared against `msg.sender` in Solidity (Ownable admin, issuer, access control roles). Always use `getOperatorEvmAddress()` from `config.ts`. - -**New contracts deployed** (2026-02-21): -- CouponScheduler: `0.0.7996912` / `0x00000000000000000000000000000000007a05f0` -- YieldDistributor: `0.0.7996914` / `0x00000000000000000000000000000000007a05f2` -- Admin (ECDSA alias): `0x40a1db6bf87e0416fde0d9cedd1d148186475ea0` -- 2 bonds registered (France OAT 2028 + US Treasury 10Y) - -## Bounty Requirements (must not forget) - -- **ADI**: MVP on ADI chain, real economic utility, white-label ready, RBAC/multisig -- **Canton**: Native Daml (no wrappers), deployed on Devnet L1, visibility separation demo -- **Hedera**: Schedule Service usage, coupon payments, initiated from smart contract -- **0G Labs**: 0G Compute inference, structured decisions, human-in-the-loop approval diff --git a/markdown/DEPLOY.md b/markdown/DEPLOY.md deleted file mode 100644 index 2ed3f00..0000000 --- a/markdown/DEPLOY.md +++ /dev/null @@ -1,268 +0,0 @@ -# Metaphor — Deploy Guide - -Guide pour deployer les smart contracts ADI + Hedera et configurer le backend. - ---- - -## Prerequis - -| Outil | Installation | -|-------|-------------| -| Foundry | `curl -L https://foundry.paradigm.xyz \| bash && foundryup` | -| Node.js 18+ | `brew install node` ou [nodejs.org](https://nodejs.org) | -| pnpm | `npm install -g pnpm` | -| Compte Hedera Testnet | [portal.hedera.com](https://portal.hedera.com) (gratuit, 10 000 HBAR testnet) | - ---- - -## Etape 1 — Creer le fichier `.env` - -```bash -cp .env.example .env -``` - -Remplis les valeurs dans `.env` : - -```env -# Ta cle privee (deployer) — METS TA VRAIE CLE ICI -ADI_PRIVATE_KEY=0xTACLEPRIVEE... - -# ADI chain RPC — pour test local c'est Anvil (localhost) -# Pour la vraie ADI chain, remplace par le RPC qu'ils fournissent -ADI_RPC_URL=http://localhost:8545 - -# Hedera — recupere depuis portal.hedera.com > ton profil -HEDERA_OPERATOR_ID=0.0.XXXXXX -HEDERA_OPERATOR_KEY=302e020100300506032b6570... -HEDERA_NETWORK=testnet -``` - ---- - -## Etape 2 — Deploy sur ADI Chain - -### Option A : Test local avec Anvil - -Ouvre un terminal et lance Anvil (blockchain locale) : - -```bash -anvil -``` - -Anvil affiche 10 comptes de test. Copie la premiere cle privee dans `.env` : - -``` -ADI_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 -ADI_RPC_URL=http://localhost:8545 -``` - -### Option B : Deploy sur la vraie ADI chain - -Remplace `ADI_RPC_URL` par le RPC URL fourni par ADI Foundation, et `ADI_PRIVATE_KEY` par ta cle privee avec du gas sur cette chain. - -### Lancer le deploy - -```bash -cd packages/contracts-adi - -# Charge le .env depuis la racine -source ../../.env - -# Deploy (dry run pour verifier) -forge script script/Deploy.s.sol --rpc-url $ADI_RPC_URL --broadcast -vvv -``` - -Tu verras dans la console : - -``` -=== InstiVault ADI Deploy === -Deployer: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 -InstiVaultAccessControl: 0x5FbDB2315678afecb367f032d93F642f64180aa3 -RWATokenFactory: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 -VaultManager: 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0 -InstitutionRegistry: 0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9 - -=== Copy these to your .env === -ADI_ACCESS_CONTROL_ADDRESS= 0x5FbDB2315678afecb367f032d93F642f64180aa3 -ADI_TOKEN_FACTORY_ADDRESS= 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 -ADI_VAULT_MANAGER_ADDRESS= 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0 -ADI_INSTITUTION_REGISTRY_ADDRESS= 0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9 -``` - -### Copie les adresses dans `.env` - -Ouvre `.env` et colle les adresses : - -```env -ADI_ACCESS_CONTROL_ADDRESS=0x5FbDB... -ADI_TOKEN_FACTORY_ADDRESS=0xe7f17... -ADI_VAULT_MANAGER_ADDRESS=0x9fE46... -ADI_INSTITUTION_REGISTRY_ADDRESS=0xCf7Ed... -``` - ---- - -## Etape 3 — Deploy sur Hedera Testnet - -### Creer un compte Hedera - -1. Va sur [portal.hedera.com](https://portal.hedera.com) -2. Cree un compte gratuit -3. Va dans ton profil > copie **Account ID** (ex: `0.0.4515614`) et **DER Private Key** -4. Mets-les dans `.env` : - -```env -HEDERA_OPERATOR_ID=0.0.4515614 -HEDERA_OPERATOR_KEY=302e020100300506032b6570... -HEDERA_NETWORK=testnet -``` - -### Compiler les contrats Hedera - -```bash -cd packages/contracts-hedera -forge build -``` - -### Lancer le deploy - -```bash -# Installe les deps node -pnpm install - -# Deploy -pnpm run deploy -``` - -Le script affiche : - -``` -Deploying contracts to Hedera Testnet... -Operator: 0.0.4515614 - -1. Deploying CouponScheduler... - CouponScheduler deployed: 0.0.4515700 - EVM address: 0x000000000000000000000000000000000044e3a4 - -2. Deploying YieldDistributor... - YieldDistributor deployed: 0.0.4515701 - EVM address: 0x0000000000000000000000000000000000044e3a5 - -Deployment complete! Addresses saved to /path/to/deployments.json -``` - -Les adresses sont aussi sauvegardees dans `packages/contracts-hedera/deployments.json`. - -### Copie les adresses EVM dans `.env` - -```env -HEDERA_COUPON_SCHEDULER_ADDRESS=0x0000000000000000000000000000000000044e3a4 -HEDERA_YIELD_DISTRIBUTOR_ADDRESS=0x0000000000000000000000000000000000044e3a5 -``` - ---- - -## Etape 4 — Lancer le backend - -```bash -cd packages/backend - -# Copie le .env du backend (ou il lira le .env racine si dotenv est configure) -cp .env.example .env -``` - -Remplis `packages/backend/.env` avec les memes valeurs : - -```env -# ADI -ADI_RPC_URL=http://localhost:8545 -ADI_PRIVATE_KEY=0xTACLE... - -# ADI Addresses (depuis Etape 2) -ADI_ACCESS_CONTROL_ADDRESS=0x5FbDB... -ADI_TOKEN_FACTORY_ADDRESS=0xe7f17... -ADI_VAULT_MANAGER_ADDRESS=0x9fE46... -ADI_INSTITUTION_REGISTRY_ADDRESS=0xCf7Ed... - -# Hedera Addresses (depuis Etape 3) -HEDERA_COUPON_SCHEDULER_ADDRESS=0x00000... -HEDERA_YIELD_DISTRIBUTOR_ADDRESS=0x00000... - -# Server -PORT=3001 -``` - -### Installer et lancer - -```bash -pnpm install -pnpm run dev -``` - -Le backend tourne sur `http://localhost:3001`. Verifie avec : - -```bash -curl http://localhost:3001/health -# {"status":"ok","service":"metaphor-backend"} -``` - ---- - -## Etape 5 — Verifier que tout marche - -### Test ADI (via backend) - -```bash -# Lister les tokens -curl http://localhost:3001/api/adi/tokens - -# Lister les institutions -curl http://localhost:3001/api/adi/institutions -``` - -### Test Hedera (via backend) - -```bash -# Lister les bonds -curl http://localhost:3001/api/hedera/bonds -``` - -### Test Hedera E2E (direct) - -```bash -cd packages/contracts-hedera -pnpm run e2e -``` - ---- - -## Resume : ou mettre quoi - -``` -.env (racine) -├── ADI_PRIVATE_KEY ← ta cle privee -├── ADI_RPC_URL ← RPC de la chain ADI (ou localhost:8545) -├── ADI_ACCESS_CONTROL_ADDRESS ← sortie de Deploy.s.sol -├── ADI_TOKEN_FACTORY_ADDRESS ← sortie de Deploy.s.sol -├── ADI_VAULT_MANAGER_ADDRESS ← sortie de Deploy.s.sol -├── ADI_INSTITUTION_REGISTRY_ADDRESS ← sortie de Deploy.s.sol -├── HEDERA_OPERATOR_ID ← portal.hedera.com -├── HEDERA_OPERATOR_KEY ← portal.hedera.com -├── HEDERA_COUPON_SCHEDULER_ADDRESS ← sortie de deploy.ts -└── HEDERA_YIELD_DISTRIBUTOR_ADDRESS ← sortie de deploy.ts - -packages/backend/.env ← copie les memes valeurs ici -``` - ---- - -## Troubleshooting - -| Probleme | Solution | -|----------|----------| -| `Missing ADI_PRIVATE_KEY` | Verifie que `.env` est bien rempli et que tu as fait `source .env` | -| `forge script` echoue | Verifie que Anvil tourne (`anvil`) ou que `ADI_RPC_URL` est correct | -| Hedera deploy echoue `INSUFFICIENT_PAYER_BALANCE` | Ton compte testnet n'a plus de HBAR — recree un compte sur portal.hedera.com | -| Hedera deploy echoue `CONTRACT_REVERT_EXECUTED` | Le gas est insuffisant — augmente `setGas(3_000_000)` dans deploy.ts | -| Backend crash `Cannot read abi` | Les ABIs n'existent pas — lance `forge build` dans les deux packages d'abord | -| `ECONNREFUSED localhost:8545` | Anvil n'est pas lance — ouvre un terminal et lance `anvil` | diff --git a/markdown/DEPLOYED_CONTRACTS.md b/markdown/DEPLOYED_CONTRACTS.md deleted file mode 100644 index 687fc7c..0000000 --- a/markdown/DEPLOYED_CONTRACTS.md +++ /dev/null @@ -1,33 +0,0 @@ -# Deployed Contracts - -## ADI Chain (Chain ID: 99999) - -| Contract | Address | -|----------|---------| -| InstiVaultAccessControl | `0x8e7d4e14583a37770c743d33092bbcc4e3dd656d` | -| RWATokenFactory | `0x0ed29f8c992bb10515296a301b27cd8f0a5d7d65` | -| VaultManager | `0x6b6449bdec04dd8717ac71565c7c065680c1534f` | -| InstitutionDeployer | `0x6804fc931cc3db9543b07581c3aedcf1fa66179b` | -| InstitutionRegistry | `0xab3cbc56d958245a2688b2171417679e743b1daf` | - -## Ethereum Sepolia (Chain ID: 11155111) - -| Contract | Address | -|----------|---------| -| InstiVaultAccessControl | `0x6ccfbc2c0d3a794938258d760cba69adbef05043` | -| RWATokenFactory | `0xe6c7ccccf0ea80816cd4e8fad70270cf5836921b` | -| VaultManager | `0xa162023bd4267a5649025f616016a6ea4f6b8044` | -| InstitutionDeployer | `0x531d24caee73fcabe1486036821d85b3111bb274` | -| InstitutionRegistry | `0x442ec1e3079e6db66c24af692b43e7b756031002` | - -## Hedera Testnet - -| Contract | Account ID | EVM Address | -|----------|------------|-------------| -| CouponScheduler | `0.0.7996912` | `0x00000000000000000000000000000000007a05f0` | -| YieldDistributor | `0.0.7996914` | `0x00000000000000000000000000000000007a05f2` | - -| Role | Account ID | EVM Address | -|------|------------|-------------| -| Admin (ECDSA) | — | `0x40a1db6bf87e0416fde0d9cedd1d148186475ea0` | -| Deployer | `0.0.7974657` | — | diff --git a/markdown/Explication.md b/markdown/Explication.md deleted file mode 100644 index 4f63ef1..0000000 --- a/markdown/Explication.md +++ /dev/null @@ -1,463 +0,0 @@ -# Explication — Architecture Outward (ETHDenver 2026) - -> Reference technique pour debug & fix. A supprimer apres le hackathon. - ---- - -## 1. Vue d'ensemble - -``` - FRONTEND (Next.js :3000) - | - BACKEND (Express :3001) - / | | \ - ADI Chain Hedera Canton 0G Labs - (Testnet) (Testnet) (Devnet) (Compute) -``` - -| Chain | Reseau | Chain ID | RPC | Contrats | Responsable | Bounty | -|-------|--------|----------|-----|----------|-------------|--------| -| **ADI** | ADI Testnet | 99999 | `https://rpc.ab.testnet.adifoundation.ai/` | AccessControl, TokenFactory, VaultManager, InstitutionRegistry, InstitutionDeployer | Dev A | ADI Foundation | -| **Hedera** | Testnet | — | Hedera SDK | CouponScheduler, YieldDistributor | Dev A | Hedera | -| **Canton** | Devnet L1 | — | `localhost:7575` | ConfidentialVault, PrivateTrade, AuditRight (.daml) | Dev B | Canton Network | -| **0G Labs** | Testnet | — | `https://evmrpc-testnet.0g.ai` | AI inference via 0G Compute broker | Dev B | 0G Labs | - ---- - -## 2. Adresses deployees - -### ADI (ADI Testnet — chain 99999) - -| Contrat | Adresse | Env var | -|---------|---------|---------| -| InstiVaultAccessControl | `0x8E7D4E14583a37770C743D33092bbCC4E3Dd656d` | `ADI_ACCESS_CONTROL_ADDRESS` | -| RWATokenFactory | `0x0eD29f8c992bB10515296A301B27cd8F0a5d7d65` | `ADI_TOKEN_FACTORY_ADDRESS` | -| VaultManager | `0x6b6449bDEC04dd8717AC71565C7c065680C1534f` | `ADI_VAULT_MANAGER_ADDRESS` | -| InstitutionDeployer | `0x6804Fc931CC3DB9543b07581C3AEdcf1fA66179B` | — | -| InstitutionRegistry | `0xAB3Cbc56D958245a2688b2171417679e743B1daF` | `ADI_INSTITUTION_REGISTRY_ADDRESS` | - -> Anciennes adresses Sepolia (deprecated) : AccessControl `0x6cCFbc...`, TokenFactory `0xE6C7cc...`, VaultManager `0xA16202...`, Registry `0x442EC1...` - -**Signer backend** : `0x4aC22453d386C2498bccbE9E12e43CfB56A341C5` -- Roles : ADMIN (set par le constructeur) -- Pas encore ISSUER, INVESTOR, AUDITOR — a configurer -- Pas encore whiteliste — a configurer -- Balance : ~10 ETH de gas sur ADI testnet - -### Hedera (Testnet) - -| Contrat | Adresse | Env var | -|---------|---------|---------| -| CouponScheduler | `0x000000000000000000000000000000000079e46e` | `HEDERA_COUPON_SCHEDULER_ADDRESS` | -| YieldDistributor | `0x000000000000000000000000000000000079e472` | `HEDERA_YIELD_DISTRIBUTOR_ADDRESS` | - -### Canton - -**Non deploye.** Les env vars `CANTON_LEDGER_HOST`, `CANTON_PARTY_*` sont vides. - -### 0G Labs - -**Partiellement configure.** RPC + private key presentes. `ZG_COMPUTE_ENDPOINT` et `ZG_API_KEY` vides → l'AI tourne en mock. -- RPC : `https://evmrpc-testnet.0g.ai` -- Mock : `ZG_USE_MOCK=true` - ---- - -## 3. Routes Backend — Qui appelle quoi - -### `/api/auth` — Authentification - -| Route | Method | Auth | Description | -|-------|--------|------|-------------| -| `/api/auth/nonce` | POST | Non | Genere un nonce pour le wallet | -| `/api/auth/login` | POST | Non | Verifie signature + retourne JWT | -| `/api/auth/dev-login` | POST | Non | JWT avec tous les roles (DEV_MODE=true only) | -| `/api/auth/me` | GET | JWT | Refresh roles depuis on-chain | - -### `/api/v1` — Donnees on-chain agregees (frontend) - -| Route | Method | Source | Si vide | -|-------|--------|--------|---------| -| `/api/v1/dashboard` | GET | VaultManager + TokenFactory + CouponScheduler + AI store | Stats a 0, arrays `[]` | -| `/api/v1/vaults` | GET | VaultManager.nextVaultId() → iterate | `[]` | -| `/api/v1/vaults/:id` | GET | VaultManager.getVaultInfo(id) | 404 | -| `/api/v1/tokens` | GET | TokenFactory.getAllTokens() → metadata | `[]` | -| `/api/v1/payments` | GET | CouponScheduler.bondCount() → iterate | `[]` | -| `/api/v1/ai/reports` | GET | In-memory + JSON file store | `[]` | -| `/api/v1/ai/score-history` | GET | Pas de persistence | `[]` | -| `/api/v1/canton/vaults` | GET | cantonClient.query (try/catch) | `[]` | -| `/api/v1/admin/wallets` | GET | Pas d'enumeration on-chain | `[]` | - -### `/api/adi` — Interactions ADI chain - -| Route | Method | Auth | Role | Contrat | -|-------|--------|------|------|---------| -| `/api/adi/tokens` | GET | Non | — | TokenFactory.getAllTokens() | -| `/api/adi/tokens` | POST | JWT | ISSUER | TokenFactory.createToken() | -| `/api/adi/tokens/:addr/fractionalize` | POST | JWT | ISSUER | TokenFactory.fractionalize() | -| `/api/adi/vaults` | POST | JWT | ISSUER | VaultManager.createVault() | -| `/api/adi/vaults/:id` | GET | Non | — | VaultManager.getVaultInfo() | -| `/api/adi/vaults/:id/deposit` | POST | JWT | INVESTOR | VaultManager.deposit() | -| `/api/adi/vaults/:id/withdraw` | POST | JWT | INVESTOR | VaultManager.withdraw() | -| `/api/adi/vaults/:id/allocate` | POST | JWT | ISSUER | VaultManager.allocate() | -| `/api/adi/vaults/:id/deallocate` | POST | JWT | ISSUER | VaultManager.deallocate() | -| `/api/adi/institutions` | GET | Non | — | InstitutionRegistry.getInstitutionCount() | -| `/api/adi/institutions` | POST | JWT | ADMIN | InstitutionRegistry.registerInstitution() | -| `/api/adi/whitelist` | POST | JWT | ADMIN | AccessControl.addToWhitelist() | -| `/api/adi/roles` | POST | JWT | ADMIN | AccessControl.grantRole() | - -### `/api/hedera` — Interactions Hedera - -| Route | Method | Auth | Role | Contrat | -|-------|--------|------|------|---------| -| `/api/hedera/bonds` | GET | Non | — | CouponScheduler.bondCount() → iterate | -| `/api/hedera/bonds/:id` | GET | Non | — | CouponScheduler.getBond() + getPaymentDates() | -| `/api/hedera/bonds` | POST | JWT | ADMIN/ISSUER | CouponScheduler.registerBond() | -| `/api/hedera/bonds/:id/schedule-all` | POST | JWT | ISSUER/ADMIN | CouponScheduler.scheduleAllCoupons() | -| `/api/hedera/bonds/:id/schedule` | POST | JWT | ISSUER/ADMIN | CouponScheduler.scheduleCoupon() | -| `/api/hedera/yield/distribute` | POST | JWT | ADMIN/ISSUER | YieldDistributor.distribute() | -| `/api/hedera/yield/claim` | POST | JWT | INVESTOR | YieldDistributor.claimYield() | - -### `/api/ai` — 0G Compute - -| Route | Method | Auth | Description | -|-------|--------|------|-------------| -| `/api/ai/analyze` | POST | JWT | Lance inference 0G (ou mock). Auto-fetch vault data on-chain si pas d'assets[] | -| `/api/ai/reports` | GET | Non | Liste tous les reports (filtre ?vaultId=) | -| `/api/ai/reports/:id` | GET | Non | Un report | -| `/api/ai/reports/:id/approve` | POST | JWT ADMIN/ISSUER | Approuve une recommandation | -| `/api/ai/reports/:id/reject` | POST | JWT ADMIN/ISSUER | Rejette une recommandation | - -### `/api/canton` — Canton Network - -| Route | Method | Description | -|-------|--------|-------------| -| `/api/canton/vaults` | POST/GET | Creer/lister vaults confidentiels | -| `/api/canton/vaults/:id/invite` | POST | Inviter une party | -| `/api/canton/vaults/:id/assets` | POST/DELETE | Deposer/retirer un asset | -| `/api/canton/trades` | GET | Lister les trades | -| `/api/canton/trades/:id/accept` | POST | Accepter un trade | -| `/api/canton/trades/:id/reject` | POST | Rejeter un trade | -| `/api/canton/vaults/:id/freeze` | POST | Geler un vault | - -> **Note**: Toutes les routes Canton echouent silencieusement si Canton n'est pas configure. - -### `/api/demo` — Mock data (legacy) - -Encore utilise par `/demo/canton` pour la demo 3 panneaux (owner/counterparty/auditor). Ne pas supprimer. - ---- - -## 4. Contrats — Fonctions principales - -### InstiVaultAccessControl (ADI) - -``` -Roles: ADMIN_ROLE, ISSUER_ROLE, INVESTOR_ROLE, AUDITOR_ROLE -Fonctions: - addToWhitelist(address) — ADMIN only - removeFromWhitelist(address) — ADMIN only - isWhitelisted(address) → bool - hasRole(bytes32, address) → bool - grantRole(bytes32, address) — ADMIN only - -Erreurs courantes: - NotWhitelisted(address) → 0xdf17e316 -``` - -### RWATokenFactory (ADI) - -``` -Fonctions: - createToken({name, symbol, isin, rate, maturity, initialSupply}) → address - fractionalize(token, fractions) → address - getAllTokens() → address[] - getTokenCount() → uint256 - -Erreurs courantes: - NotIssuer() → 0x54ec5063 ← signer n'a pas ISSUER_ROLE - TransferNotWhitelisted() → 0xc7be2aea ← signer pas whiteliste (mint = transfer) - ISINAlreadyExists() → isin deja utilise -``` - -### RWAToken (ADI) - -``` -Fonctions: - name() → string - symbol() → string - totalSupply() → uint256 - getMetadata() → (isin, rate, maturity, issuer) - mint(to, amount) — factory ou issuer only - transfer() — les 2 parties doivent etre whitelisted ! - -Erreurs courantes: - TransferNotWhitelisted(address) → le from OU le to n'est pas whiteliste - OnlyFactoryOrIssuer() → seul la factory ou l'issuer peut mint -``` - -### VaultManager (ADI) - -``` -Fonctions: - createVault() → uint256 vaultId — ISSUER only - deposit(vaultId, token, amount) — INVESTOR only, vault must be Active - withdraw(vaultId, token, amount) — INVESTOR only - allocate(vaultId, token, strategy, amount) — ISSUER only - deallocate(vaultId, token, strategy, amount) — ISSUER only - - nextVaultId() → uint256 - getVaultInfo(id) → (owner, status, createdAt) - getVaultTokens(id) → address[] - getVaultBalance(id, token) → uint256 - -Status: 0=Active, 1=Paused, 2=Closed - -Erreurs courantes: - NotIssuer() → pas ISSUER_ROLE - NotInvestor() → pas INVESTOR_ROLE - VaultNotActive() → vault pause ou ferme - TokenNotRegistered() → le token n'est pas dans la factory - NotWhitelisted() → pas dans la whitelist -``` - -### CouponScheduler (Hedera) - -``` -Fonctions: - registerBond(token, paymentToken, faceValue, rate, frequency, startDate, maturityDate, issuer) → bondId - scheduleCoupon(bondId, paymentDate) — utilise precompile 0x16b ! - scheduleAllCoupons(bondId) - executeCoupon(bondId, paymentDate) — callback Hedera - - bondCount() → uint256 - getBond(id) → Bond - getPaymentDates(bondId) → uint256[] - getPayment(bondId, date) → ScheduledPayment - getCouponAmount(bondId) → uint256 - -Frequency: 0=Monthly, 1=Quarterly, 2=SemiAnnual, 3=Annual -PaymentStatus: 0=Pending, 1=Scheduled, 2=Executed, 3=Failed, 4=Suspended -``` - -### YieldDistributor (Hedera) - -``` -Fonctions: - distribute(token, paymentToken, totalYield, holders[]) → snapshotId - claimYield(paymentToken, snapshotId) - getUnclaimedYield(holder, paymentToken) → uint256 - getSnapshotInfo(id) → (token, paymentToken, totalYield, totalSupply, timestamp, claimed, holderCount) -``` - ---- - -## 5. Pages Frontend — Quelle API chaque page utilise - -| Page | URL | API v1 | API directe | Commentaire | -|------|-----|--------|-------------|-------------| -| Dashboard | `/app` | `v1/dashboard` | — | Empty state si rien on-chain | -| Vaults | `/vaults` | `v1/vaults` | — | Pas de bouton "Create Vault" (manquant !) | -| Vault detail | `/vaults/[id]` | `v1/vaults/:id`, `v1/payments`, `v1/ai/reports`, `v1/ai/score-history` | `ai/analyze`, `ai/reports/:id/approve`, `ai/reports/:id/reject` | Analyze with AI + human-in-the-loop | -| Issue token | `/issue` | — | `adi/tokens` (POST) | Role gate: ADMIN/ISSUER | -| Admin | `/admin` | `v1/admin/wallets` | `adi/whitelist`, `adi/roles` | Role gate: ADMIN | -| AI Reports | `/ai-reports` | `v1/ai/reports`, `v1/ai/score-history`, `v1/vaults` | `ai/reports/:id/approve`, `ai/reports/:id/reject` | Approve/reject recommendations | -| Data Room | `/data-room` | `v1/canton/vaults` | `canton/vaults/:id/invite`, `canton/trades/:id/accept`, `canton/trades/:id/reject` | Vide si Canton pas config | -| Yield Calendar | `/yield-calendar` | `v1/payments`, `v1/vaults` | — | Vide si pas de bonds Hedera | -| Canton Demo | `/demo/canton` | — | `demo/canton/demo/:vaultId/:role` | **Garde les mocks** pour la demo bounty | - ---- - -## 6. Flux d'authentification - -``` -1. User connecte wallet (RainbowKit) ← juste l'adresse, PAS de JWT -2. User clique "Sign In" -3. Frontend → POST /api/auth/nonce {address} -4. Backend genere nonce, stocke 5min -5. Frontend → wallet.signMessage(message) ← l'user signe -6. Frontend → POST /api/auth/login {address, signature, message} -7. Backend verifie signature + check roles on-chain -8. Backend retourne JWT {address, roles, exp: 24h} -9. JWT stocke dans localStorage('metaphor_jwt') -10. Toutes les requetes incluent Authorization: Bearer -``` - -**Raccourci dev** : `POST /api/auth/dev-login` → JWT avec ADMIN+ISSUER+INVESTOR+AUDITOR (si `DEV_MODE=true` dans .env) - ---- - -## 7. Erreurs communes et solutions - -| Erreur | Cause | Fix | -|--------|-------|-----| -| `NotIssuer() 0x54ec5063` | Signer n'a pas ISSUER_ROLE | `POST /api/adi/roles {address, role: "issuer"}` avec JWT ADMIN | -| `TransferNotWhitelisted() 0xc7be2aea` | Adresse pas whitelistee (mint = transfer) | `POST /api/adi/whitelist {address}` avec JWT ADMIN | -| `NotWhitelisted() 0xdf17e316` | Adresse pas dans la whitelist pour VaultManager | Idem whitelist | -| `Missing Authorization header` | Pas de JWT dans la requete | Se connecter wallet + Sign In, ou dev-login | -| `Invalid or expired token` | JWT expire (>24h) ou mauvais secret | Re-login | -| `Vault has no assets on-chain` | AI analyze sur un vault vide | Deposer des tokens d'abord | -| `TokenNotRegistered()` | Token pas cree via la factory | Creer via `/api/adi/tokens` | -| `CORS error` | Frontend et backend sur des ports differents | Backend a `cors()` active, verifier `NEXT_PUBLIC_API_URL` | -| Canton routes retournent `[]` | Canton pas configure | Remplir `CANTON_LEDGER_HOST` + `CANTON_PARTY_*` | -| AI toujours `[Mock]` | 0G pas configure | Remplir `ZG_COMPUTE_ENDPOINT` + `ZG_API_KEY` | - ---- - -## 8. Ce qui est fait vs ce qui manque - -### ADI (Dev A) — 90% fait - -- [x] Contrats deployes sur ADI Testnet (chain 99999) -- [x] Routes backend completes -- [x] Frontend connecte a on-chain (v1 routes) -- [x] Issue page fonctionne -- [ ] **Signer pas encore ISSUER + whiteliste sur ADI testnet** (fresh deploy) -- [ ] **Pas de bouton "Create Vault" dans le frontend** -- [ ] Rien depose dans les vaults (0 assets on-chain) -- [ ] Pas d'institution enregistree - -### Hedera (Dev A) — 80% fait - -- [x] Contrats deployes sur testnet -- [x] Routes backend completes -- [ ] Pas de bonds enregistres (bondCount = 0) -- [ ] Schedule Service pas teste end-to-end - -### Canton (Dev B) — 40% fait - -- [x] Contrats Daml ecrits (3 templates + tests) -- [x] Backend client + routes -- [x] Demo page (mock) pour bounty -- [ ] **Pas deploye sur Canton Devnet** -- [ ] **Env vars vides** -- [ ] Pas de lien avec les donnees ADI - -### 0G Labs (Dev B) — 55% fait - -- [x] Client 0G Compute code -- [x] Routes backend (analyze, approve, reject) -- [x] Human-in-the-loop (approve/reject) -- [x] Reports persistes en JSON -- [x] Auto-fetch vault data on-chain -- [x] RPC + private key configures -- [ ] **ZG_COMPUTE_ENDPOINT vide** (mock seulement) -- [ ] **Pas d'execution des recommandations** - -### Frontend (Dev C) — 85% fait - -- [x] Toutes les pages existent -- [x] Auth wallet + JWT -- [x] Role gating -- [x] Empty states -- [x] Connecte a on-chain (v1) -- [ ] **Manque bouton Create Vault** -- [ ] Manque feedback erreur plus visible sur /issue - ---- - -## 9. Variables d'environnement (.env) - -```bash -# ADI (ADI Testnet chain 99999) — FONCTIONNEL -ADI_RPC_URL=https://rpc.ab.testnet.adifoundation.ai/ -ADI_PRIVATE_KEY=0x086770b... -ADI_CHAIN_ID=99999 -ADI_ACCESS_CONTROL_ADDRESS=0x8E7D4E14... -ADI_TOKEN_FACTORY_ADDRESS=0x0eD29f8c... -ADI_VAULT_MANAGER_ADDRESS=0x6b6449bD... -ADI_INSTITUTION_REGISTRY_ADDRESS=0xAB3Cbc56... - -# Hedera (Testnet) — FONCTIONNEL -HEDERA_OPERATOR_ID=0.0.7974657 -HEDERA_OPERATOR_KEY=3030020100... -HEDERA_COUPON_SCHEDULER_ADDRESS=0x00000000...79e46e -HEDERA_YIELD_DISTRIBUTOR_ADDRESS=0x00000000...79e472 - -# Canton — VIDE (Dev B doit configurer) -CANTON_LEDGER_HOST= -CANTON_PARTY_ADMIN= -CANTON_PARTY_ISSUER= -CANTON_PARTY_INVESTOR= -CANTON_PARTY_AUDITOR= - -# 0G Labs — PARTIELLEMENT CONFIGURE -ZG_RPC_URL=https://evmrpc-testnet.0g.ai -ZG_PRIVATE_KEY=0xd0c537... -ZG_USE_MOCK=true -ZG_COMPUTE_ENDPOINT= ← VIDE (Dev B doit configurer) -ZG_API_KEY= ← VIDE (Dev B doit configurer) - -# Backend -PORT=3001 -DEV_MODE=true - -# Frontend -NEXT_PUBLIC_API_URL=http://localhost:3001 -NEXT_PUBLIC_ADI_RPC_URL=https://rpc.ab.testnet.adifoundation.ai/ -``` - ---- - -## 10. Fichiers cles par package - -``` -packages/ -├── contracts-adi/ -│ ├── src/ ← 6 contrats Solidity -│ ├── abi/ ← ABIs JSON (utilises par le backend) -│ ├── script/Deploy.s.sol ← Script de deploiement Foundry -│ └── script/Demo.s.sol ← Script de demo (create token + vault) -│ -├── contracts-hedera/ -│ ├── contracts/ ← CouponScheduler, YieldDistributor, HederaScheduleService -│ ├── abi/ ← ABIs JSON -│ └── src/deploy.ts ← Script de deploiement Hedera SDK -│ -├── contracts-canton/ -│ ├── daml/ConfidentialVault.daml ← Template principal -│ ├── daml/PrivateTrade.daml ← Negociation bilaterale -│ ├── daml/AuditRight.daml ← Acces audit limite -│ └── daml.yaml ← Config SDK Daml 2.10.3 -│ -├── ai-engine/ -│ ├── src/0g-client.ts ← Client 0G Compute reel -│ ├── src/risk-analyzer.ts ← Analyse de risque + prompt -│ ├── src/strategy-simulator.ts ← Stress tests -│ └── src/mock.ts ← Mock quand 0G pas dispo -│ -├── backend/ -│ ├── src/index.ts ← Express app, monte toutes les routes -│ ├── src/config.ts ← Provider ethers, ABIs, adresses -│ ├── src/routes/ -│ │ ├── auth.ts ← Nonce + login + dev-login -│ │ ├── adi.ts ← Tokens, vaults, institutions, roles -│ │ ├── hedera.ts ← Bonds, scheduling, yield -│ │ ├── canton.ts ← Vaults confidentiels, trades -│ │ ├── ai.ts ← Analyze, reports, approve/reject -│ │ ├── v1.ts ← Routes agregees on-chain pour frontend -│ │ └── demo.ts ← Mock data (garde pour demo Canton) -│ ├── src/services/ -│ │ ├── ai-client.ts ← Store AI + forward 0G + persistence JSON -│ │ └── canton-client.ts ← Client HTTP Daml JSON API -│ ├── src/middleware/ -│ │ ├── auth.ts ← JWT sign/verify + nonce store -│ │ └── rbac.ts ← Role check on-chain -│ └── data/ai-reports.json ← Persistence AI (gitignored) -│ -└── frontend/ - ├── src/app/ - │ ├── page.tsx ← Landing (/) - │ ├── app/page.tsx ← Dashboard (/app) - │ ├── vaults/page.tsx ← Vaults list (/vaults) - │ ├── vaults/[id]/page.tsx ← Vault detail (/vaults/:id) - │ ├── issue/page.tsx ← Issue token (/issue) - │ ├── admin/page.tsx ← Admin panel (/admin) - │ ├── ai-reports/page.tsx ← AI reports (/ai-reports) - │ ├── data-room/page.tsx ← Canton data room (/data-room) - │ ├── yield-calendar/page.tsx ← Hedera payments (/yield-calendar) - │ └── demo/canton/page.tsx ← Canton visibility demo (/demo/canton) - ├── src/contexts/auth-context.tsx ← JWT + wallet auth state - ├── src/lib/api.ts ← Fetch wrapper avec JWT auto - └── src/lib/mock-data.ts ← Types + helpers (plus de mock data unused) -``` diff --git a/markdown/PROJECT_OVERVIEW.md b/markdown/PROJECT_OVERVIEW.md deleted file mode 100644 index 35748a0..0000000 --- a/markdown/PROJECT_OVERVIEW.md +++ /dev/null @@ -1,573 +0,0 @@ -# Metaphor — Hub RWA Confidentiel et Automatisé pour les Institutions - -## Contexte - -### Hackathon -- **Événement :** ETHDenver 2026 -- **Track ciblé :** New France Village -- **Thématiques du track :** DeFi, TradFi, Real World Assets (RWA), adoption institutionnelle - -### Problème adressé -Les institutions financières souhaitant tokeniser et gérer des actifs du monde réel (obligations, factures, immobilier) font face à trois obstacles majeurs : - -1. **Confidentialité** — Les stratégies d'investissement et les données de portefeuille sont exposées sur les blockchains publiques -2. **Automatisation** — Le versement des rendements/coupons dépend de serveurs centralisés (off-chain), créant des points de défaillance -3. **Intelligence décisionnelle** — L'analyse de risque des portefeuilles RWA reste manuelle et fragmentée - -### Solution : Metaphor -Un hub intégré où les institutions peuvent : -- **Tokeniser** des RWA sur une infrastructure dédiée -- **Négocier** ces actifs en toute confidentialité -- **Automatiser** les paiements de coupons/rendements de manière déterministe on-chain -- **Analyser** leurs vaults via un assistant IA embarqué - ---- - -## Fonctionnalités Concrètes - -### Vue d'ensemble produit - -Metaphor se présente comme une **plateforme SaaS white-label** destinée aux asset managers, banques privées et family offices. L'interface est un dashboard institutionnel unique qui orchestre les 4 couches techniques de manière transparente pour l'utilisateur final. - -### F1 — Émission & Tokenisation d'actifs (ADI) - -**Ce que l'utilisateur fait concrètement :** - -Un asset manager se connecte au dashboard, clique sur "Émettre un nouvel actif" et remplit un formulaire structuré : - -| Champ | Exemple | -|---|---| -| Type d'actif | Obligation corporate | invoices -| Nom | BondToken-ACME-2026 | -| Valeur nominale | 1 000 000 USD | -| Taux de coupon | 5% annuel | -| Fréquence de paiement | Semestrielle | -| Date de maturité | 15/02/2028 | -| Nombre de tokens | 1 000 (= 1 000 USD / token) | -| Juridiction | France | - -**Ce qui se passe en coulisses :** -- Le contrat `RWATokenFactory` mint 1 000 tokens ERC-20 sur la chaîne ADI -- Chaque token porte des métadonnées on-chain (ISIN, taux, maturité, émetteur) -- Le contrat `AccessControl` attribue les rôles : l'émetteur est `Issuer`, les acheteurs seront `Investor`, un cabinet d'audit externe peut être ajouté comme `Auditor` - -**Fonctionnalités détaillées :** -- **Registre d'actifs** — Liste de tous les RWA tokenisés avec statut (actif, échu, en défaut) -- **Fractionnement** — Un actif de 1M USD peut être divisé en 1 000 tokens de 1 000 USD, rendant l'investissement accessible à des tickets plus petits -- **Transferts contrôlés** — Seuls les wallets whitelistés (KYC validé) peuvent recevoir des tokens. Un transfert vers un wallet non autorisé est bloqué au niveau du smart contract -- **Burn à maturité** — À l'échéance de l'obligation, les tokens sont automatiquement brûlés et le nominal est remboursé -- **Multi-tenant white-label** — Chaque institution peut déployer sa propre instance avec son branding (logo, couleurs, nom de domaine) - ---- - -### F2 — Vaults Confidentiels & Data Rooms Privées (Canton) - -**Ce que l'utilisateur fait concrètement :** - -Une banque privée crée un "Vault Confidentiel" et y dépose des tokens RWA. Elle invite une contrepartie (un fonds d'investissement) à consulter le vault pour une potentielle transaction. Un auditeur est ajouté avec des droits limités. - -**Scénario concret — Data Room M&A :** -``` -1. BNP Paribas tokenise un portefeuille de créances (10M USD) sur ADI -2. BNP crée un Vault Confidentiel sur Canton et y dépose les tokens -3. BNP invite BlackRock à consulter le vault : - → BlackRock voit : composition du portefeuille, rendements historiques, rating - → BlackRock ne voit PAS : les autres vaults de BNP, ni le prix de réserve -4. BNP invite Deloitte comme auditeur : - → Deloitte voit : la conformité réglementaire, les dates, les montants - → Deloitte ne voit PAS : l'identité de BlackRock ni les termes de négociation -5. BlackRock fait une offre via un PrivateTrade (visible uniquement par BNP et BlackRock) -6. BNP accepte → le transfert de tokens s'exécute, personne d'autre ne le sait -``` - -**Fonctionnalités détaillées :** -- **Création de vault confidentiel** — L'utilisateur choisit les parties autorisées et leur niveau d'accès (lecture seule, proposition de trade, audit) -- **Invitation de parties** — Mécanisme d'invitation par clé publique Canton. La partie invitée reçoit une notification et accepte/refuse -- **Niveaux de visibilité granulaires** : - - `Owner` — Voit tout, peut modifier le vault, accepter/refuser des trades - - `Counterparty` — Voit la composition et peut proposer un trade - - `Auditor` — Vue en lecture seule limitée aux données de compliance - - `Public` — Ne voit rien (le vault n'existe pas pour le monde extérieur) -- **Négociation privée (PrivateTrade)** — Système d'offre/contre-offre bilatéral. Chaque proposition est un contrat Daml visible uniquement par les deux parties -- **Historique d'audit immuable** — Chaque action (consultation, offre, acceptation) est loggée dans Canton mais visible uniquement par les parties concernées - ---- - -### F3 — Paiements de Coupons Automatisés (Hedera) - -**Ce que l'utilisateur fait concrètement :** - -Lors de la créa tion d'un vault contenant un titre obligataire, l'utilisateur active l'option "Automatiser les rendements". Le système configure automatiquement les paiements planifiés. - -**Scénario concret — Coupon semestriel :** -``` -Obligation : BondToken-ACME-2026 -├── Valeur totale : 1 000 000 USD -├── Taux : 5% annuel → 2.5% par semestre → 25 000 USD / paiement -├── Fréquence : Semestrielle -├── Détenteurs : 15 investisseurs institutionnels -│ -│ Jour J (création du vault) : -│ └─ Le CouponScheduler crée 4 transactions planifiées via Hedera : -│ ├── Paiement #1 : 15/08/2026 → 25 000 USD distribués au prorata -│ ├── Paiement #2 : 15/02/2027 → 25 000 USD distribués au prorata -│ ├── Paiement #3 : 15/08/2027 → 25 000 USD distribués au prorata -│ └── Paiement #4 : 15/02/2028 → 25 000 USD + remboursement nominal -│ -│ Jour du paiement (automatique, sans intervention) : -│ └─ Hedera Schedule Service exécute la transaction -│ └─ YieldDistributor répartit les tokens aux 15 détenteurs -│ ├── Investisseur A (détient 10%) → reçoit 2 500 USD -│ ├── Investisseur B (détient 25%) → reçoit 6 250 USD -│ └── ... (au prorata des parts détenues) -``` - -**Fonctionnalités détaillées :** -- **Configuration automatique** — L'utilisateur ne fait rien manuellement : les dates de paiement sont calculées à partir des paramètres de l'obligation -- **Distribution au prorata** — Si un investisseur vend une partie de ses tokens entre deux coupons, le paiement suivant est recalculé automatiquement en fonction du snapshot des détenteurs -- **Dashboard de suivi des rendements** — Vue calendrier montrant : paiements passés (avec montants), paiements à venir (avec dates), rendement cumulé -- **Alertes** — Notification 48h avant chaque paiement planifié + confirmation après exécution -- **Gestion des défauts** — Si le pool de liquidité du vault est insuffisant pour couvrir un coupon, une alerte est remontée à l'émetteur et aux investisseurs. Le paiement est suspendu (pas d'exécution partielle silencieuse) -- **Remboursement à maturité** — Le dernier paiement inclut le remboursement du nominal + le dernier coupon. Les tokens RWA sont brûlés automatiquement - ---- - -### F4 — Assistant IA de Gestion des Risques (0G Labs) - -**Ce que l'utilisateur fait concrètement :** - -Sur le dashboard d'un vault, l'utilisateur clique sur "Analyser ce vault". L'assistant IA scanne la composition du vault et retourne un rapport structuré en 10-15 secondes. - -**Scénario concret — Analyse d'un vault multi-actifs :** -``` -Vault : "Fixed Income Europe Q1" -├── Composition : -│ ├── 40% — Obligations souveraines France (AAA, 2.1%) -│ ├── 35% — Corporate bonds Allemagne (A+, 4.3%) -│ └── 25% — Factures affacturées Italie (BBB, 7.8%) -│ -│ L'utilisateur clique "Analyser ce vault" -│ -│ RAPPORT IA (généré via 0G Compute) : -│ ┌──────────────────────────────────────────────────┐ -│ │ SCORE DE RISQUE GLOBAL : 42/100 (Modéré) │ -│ │ │ -│ │ ANALYSE PAR POSITION : │ -│ │ ✅ Obligations France : Risque faible (12/100) │ -│ │ → Rating souverain stable, duration courte │ -│ │ ⚠️ Corporate Allemagne : Risque modéré (38/100) │ -│ │ → Secteur industriel exposé au cycle │ -│ │ 🔴 Factures Italie : Risque élevé (71/100) │ -│ │ → Concentration géographique + rating BBB │ -│ │ │ -│ │ RECOMMANDATIONS : │ -│ │ 1. Réduire l'exposition Italie de 25% à 15% │ -│ │ → Réallouer 10% vers obligations France │ -│ │ 2. Ajouter une couverture de taux (swap) │ -│ │ → Duration du portefeuille = 3.2 ans │ -│ │ │ -│ │ STRESS TEST : │ -│ │ • Si taux BCE +1% → Valeur du vault : -2.8% │ -│ │ • Si taux BCE +2% → Valeur du vault : -5.4% │ -│ │ • Si défaut Italie → Valeur du vault : -18.2% │ -│ │ │ -│ │ [Approuver rééquilibrage] [Rejeter] [Détails] │ -│ └──────────────────────────────────────────────────┘ -``` - -**Fonctionnalités détaillées :** -- **Analyse on-demand** — L'utilisateur déclenche l'analyse manuellement (pas de trading automatique) -- **Score de risque composite** — Note de 1 à 100 calculée à partir de : rating des actifs, concentration géographique/sectorielle, duration, volatilité historique -- **Recommandations actionnables** — Chaque recommandation est liée à une action concrète (rééquilibrage, ajout de collatéral, sortie de position) avec un bouton d'exécution -- **Stress testing** — Simulation de scénarios macro (hausse des taux, défaut d'un émetteur, crise sectorielle) avec impact chiffré sur la valeur du vault -- **Human-in-the-loop strict** — L'IA ne peut JAMAIS exécuter une transaction seule. Chaque action recommandée passe par un écran de confirmation explicite avec résumé de l'impact -- **Historique des analyses** — L'utilisateur peut consulter les analyses passées et suivre l'évolution du score de risque dans le temps -- **Export PDF** — Le rapport IA peut être exporté en PDF pour reporting interne ou partage avec les auditeurs - ---- - -### F5 — Dashboard Institutionnel (Frontend) - -**Vue principale — Portfolio Overview :** -``` -┌──────────────────────────────────────────────────────────────┐ -│ Metaphor [Vault: Fixed Income EU] [🔔] [Admin] │ -├──────────────────────────────────────────────────────────────┤ -│ │ -│ VALEUR TOTALE DES ACTIFS RENDEMENT YTD │ -│ $12,450,000 +4.2% │ -│ │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ -│ │ 3 Vaults │ │ 12 Actifs │ │ 2 Paiements │ │ -│ │ actifs │ │ tokenisés │ │ à venir │ │ -│ └─────────────┘ └─────────────┘ └─────────────┘ │ -│ │ -│ VAULTS │ -│ ┌──────────────────────────────────────────────────────┐ │ -│ │ Fixed Income EU │ $5.2M │ Risk: 42 │ 🟢 Actif │ │ -│ │ US Treasury Pool │ $4.8M │ Risk: 18 │ 🟢 Actif │ │ -│ │ EM Corporate │ $2.4M │ Risk: 67 │ 🟡 Attention│ │ -│ └──────────────────────────────────────────────────────┘ │ -│ │ -│ PROCHAIN PAIEMENT │ -│ BondToken-ACME-2026 → 25,000 USD → dans 12 jours │ -│ │ -│ DERNIÈRE ANALYSE IA │ -│ Vault "EM Corporate" — Score 67/100 — 1 recommandation │ -│ [Voir le rapport] │ -│ │ -└──────────────────────────────────────────────────────────────┘ -``` - -**Pages et fonctionnalités du frontend :** - -| Page | Description | -|---|---| -| **Dashboard** | Vue d'ensemble : valeur totale, nombre de vaults, prochains paiements, alertes | -| **Mes Vaults** | Liste des vaults avec filtres (par risque, par type d'actif, par statut) | -| **Détail Vault** | Composition, historique des rendements, graphique d'évolution, bouton "Analyser IA" | -| **Émettre un actif** | Formulaire de tokenisation (type, montant, taux, maturité, juridiction) | -| **Data Room** | Gestion des vaults confidentiels Canton : invitations, niveaux d'accès, négociations | -| **Calendrier Rendements** | Vue calendrier des paiements automatisés Hedera (passés et à venir) | -| **Rapports IA** | Historique des analyses, évolution des scores, exports PDF | -| **Administration** | Gestion des rôles (RBAC), whitelist de wallets, configuration white-label | - ---- - -### F6 — Gestion des Rôles & Permissions (RBAC) - -Le système définit **4 rôles** avec des permissions strictes : - -| Rôle | Peut émettre | Peut investir | Peut auditer | Peut administrer | Voit les données confidentielles | -|---|---|---|---|---|---| -| **Admin** | ✅ | ✅ | ✅ | ✅ | ✅ (toutes) | -| **Issuer** (Émetteur) | ✅ | ❌ | ❌ | ❌ | ✅ (ses propres actifs) | -| **Investor** | ❌ | ✅ | ❌ | ❌ | ✅ (ses vaults uniquement) | -| **Auditor** | ❌ | ❌ | ✅ | ❌ | ⚠️ (vue compliance limitée) | - -**Cas d'usage concrets :** -- Un `Admin` de BNP déploie l'instance Metaphor avec le branding BNP -- Un `Issuer` tokenise un portefeuille de créances et crée un vault -- Un `Investor` (BlackRock) achète des tokens et suit ses rendements -- Un `Auditor` (Deloitte) vérifie la conformité sans voir les stratégies - ---- - -## Scénario de Démo Complet (Vidéo < 3 min) - -Ce scénario sera utilisé pour la vidéo de démonstration et la présentation aux juges : - -``` -00:00 - 00:20 INTRO - "Metaphor permet aux institutions de tokeniser, négocier en confidentialité, - automatiser les rendements et analyser les risques de leurs actifs réels." - -00:20 - 00:50 TOKENISATION (ADI) - → L'asset manager se connecte - → Il tokenise une obligation corporate de 1M USD, coupon 5% semestriel - → 1 000 tokens sont créés sur ADI - -00:50 - 01:20 CONFIDENTIALITÉ (Canton) - → Création d'un vault confidentiel - → Invitation d'une contrepartie (vue investisseur) et d'un auditeur (vue limitée) - → Démonstration : 3 écrans côte à côte montrant ce que chaque partie voit - -01:20 - 01:50 AUTOMATISATION (Hedera) - → Les paiements de coupons sont planifiés automatiquement - → Vue calendrier : 4 paiements sur 2 ans - → Simulation d'un paiement exécuté → les investisseurs reçoivent leur part - -01:50 - 02:30 ANALYSE IA (0G Labs) - → Clic sur "Analyser ce vault" - → Le rapport IA apparaît : score de risque, recommandations, stress test - → L'utilisateur clique "Approuver rééquilibrage" → la transaction se prépare - → Confirmation explicite avant exécution - -02:30 - 02:50 RÉCAP - "4 couches, 1 plateforme. Tokenisation, confidentialité, automatisation, intelligence. - Metaphor — le hub RWA institutionnel." -``` - ---- - -## Architecture Technique — 4 Couches - -Le projet s'appuie sur **4 technologies sponsors**, chacune avec un rôle strict et indispensable. Aucune n'est un ajout cosmétique — chaque couche est une dépendance fonctionnelle du système. - -``` -┌─────────────────────────────────────────────────────────┐ -│ FRONTEND (Web App) │ -│ Interface institutionnelle React │ -├─────────────┬──────────────┬─────────────┬──────────────┤ -│ Couche 1 │ Couche 2 │ Couche 3 │ Couche 4 │ -│ ADI │ Canton │ Hedera │ 0G Labs │ -│ Tokenisation│ Confidentialité│ Automatisation│ IA │ -└─────────────┴──────────────┴─────────────┴──────────────┘ -``` - -### Couche 1 — Exécution & Tokenisation (ADI Foundation) - -| Élément | Détail | -|---|---| -| **Rôle** | Infrastructure principale de tokenisation et gestion des RWA | -| **Actifs tokenisés** | Obligations, factures, titres de créance | -| **Déploiement** | Chaîne ADI (MVP déployé) | -| **Fonctionnalités clés** | Mint/burn de tokens RWA, registre d'actifs, transferts contrôlés | - -**Exigences du bounty ADI :** -- MVP déployé sur la chaîne ADI adapté à un usage institutionnel -- Utilité économique réelle (pas un PoC théorique) -- Architecture prête pour la marque blanche (white-label ready) -- Contrôles d'administration basés sur les rôles (RBAC) ou multisigs - -**Contrats déployés (Sepolia + ADI Chain 99999) :** -- `InstiVaultAccessControl` — RBAC (Admin, Issuer, Investor, Auditor) + whitelisting -- `RWAToken` — ERC-20 avec métadonnées RWA + restrictions de transfert + burn à maturité -- `RWATokenFactory` — Factory de tokens RWA + fractionnement -- `VaultManager` — Gestion des vaults (dépôt, retrait, allocation) + Pausable -- `InstitutionRegistry` — Registre multi-tenant white-label + multisig 2-of-N -- `InstitutionDeployer` — Deployer externe (contournement EIP-170) - ---- - -### Couche 2 — Confidentialité (Canton Network) - -| Élément | Détail | -|---|---| -| **Rôle** | Permettre les transactions RWA sans exposer les stratégies des institutions | -| **Cas d'usage** | Private M&A data rooms, Private DeFi | -| **Déploiement** | Devnet Canton L1 | -| **Langage** | Daml (contrats natifs, pas de wrappers) | - -**Exigences du bounty Canton :** -- Contrats intelligents écrits **nativement en Daml** -- Déploiement sur le **Devnet Canton L1** -- Démonstration claire de la **séparation de visibilité** entre les parties (qui voit quoi) - -**Modèle de confidentialité :** -``` -Institution A ──┐ - ├── Vault partagé (données visibles uniquement aux parties autorisées) -Institution B ──┘ - │ -Auditeur ───────────┘ (vue limitée : compliance uniquement) - │ -Public ─────────────X (aucune visibilité sur les positions/stratégies) -``` - -**Templates Daml prévus :** -- `ConfidentialVault` — Vault dont les détails ne sont visibles que par les parties autorisées -- `PrivateTrade` — Proposition et exécution de trades RWA en confidentialité -- `AuditRight` — Droit d'audit limité accordé à un tiers (vue partielle) - ---- - -### Couche 3 — Automatisation (Hedera) - -| Élément | Détail | -|---|---| -| **Rôle** | Automatiser le versement des rendements/coupons de manière déterministe | -| **Mécanisme** | Hedera Schedule Service (transactions planifiées) | -| **Avantage** | Aucune dépendance à des serveurs off-chain (cron jobs, keepers) | - -**Exigences du bounty Hedera :** -- Utilisation du **Hedera Schedule Service** pour créer et exécuter des transactions planifiées -- Paiements de coupons pour titres tokenisés -- Transactions initiées **directement depuis un smart contract** - -**Flux d'automatisation :** -``` -1. Institution crée un vault avec un titre obligataire tokenisé (ADI) -2. Le smart contract Hedera planifie automatiquement les paiements de coupons - → Ex: coupon de 5% semestriel → paiement planifié tous les 6 mois -3. À la date prévue, le Hedera Schedule Service exécute le paiement -4. Les tokens de rendement sont distribués aux détenteurs du vault -5. Tout est on-chain, déterministe, sans intervention humaine -``` - -**Contrats déployés (Hedera Testnet) :** -- `CouponScheduler` — Planification via precompile 0x16b (IHRC755 + IHRC1215) + access control + Pausable -- `YieldDistributor` — Distribution pro-rata par snapshot aux détenteurs de tokens RWA -- `HederaScheduleService` — Base abstraite pour l'interaction avec le precompile Hedera - ---- - -### Couche 4 — Intelligence Artificielle / DeFAI (0G Labs) - -| Élément | Détail | -|---|---| -| **Rôle** | Assistant IA pour l'analyse de risque et la recommandation de gestion de vault | -| **Infrastructure** | 0G Compute (inférence on-chain) | -| **Principe** | Human-in-the-loop — l'utilisateur approuve avant toute exécution | - -**Exigences du bounty 0G Labs :** -- Intégration de **0G Compute** pour l'inférence IA -- L'IA produit des **décisions structurées** (simulations de stratégies de vault) -- **Approbation explicite** de l'utilisateur avant toute exécution de transaction - -**Fonctionnalités IA :** -``` -Entrée : Données du vault (composition, rendements, échéances, risques) - │ - ▼ -0G Compute (inférence) - │ - ▼ -Sortie structurée : - - Score de risque du vault (1-100) - - Recommandations (rééquilibrage, sortie de position, ajout de collatéral) - - Simulation de scénarios (stress test : que se passe-t-il si taux +2% ?) - │ - ▼ -Dashboard utilisateur → Bouton "Approuver & Exécuter" ou "Rejeter" -``` - ---- - -## Flux Utilisateur Global - -``` -┌──────────────────────────────────────────────────────────────────┐ -│ FLUX METAPHOR │ -│ │ -│ 1. LOGIN │ -│ └─ Connexion wallet institutionnel (rôle assigné via RBAC) │ -│ │ -│ 2. TOKENISATION (ADI) │ -│ └─ L'institution tokenise un actif (ex: obligation 5% p.a.) │ -│ └─ Le token est créé sur la chaîne ADI │ -│ │ -│ 3. CONFIGURATION VAULT (ADI + Canton) │ -│ └─ Création d'un vault confidentiel │ -│ └─ Définition des parties autorisées (Canton/Daml) │ -│ └─ Les données restent privées entre les parties │ -│ │ -│ 4. AUTOMATISATION RENDEMENTS (Hedera) │ -│ └─ Le vault configure les paiements de coupons automatiques │ -│ └─ Hedera Schedule Service planifie les transactions │ -│ └─ Exécution déterministe sans serveur off-chain │ -│ │ -│ 5. ANALYSE IA (0G Labs) │ -│ └─ L'assistant IA analyse le vault en temps réel │ -│ └─ Recommandations de gestion des risques │ -│ └─ L'utilisateur approuve ou rejette avant exécution │ -│ │ -│ 6. MONITORING │ -│ └─ Dashboard institutionnel : positions, rendements, risques │ -│ └─ Vue auditeur limitée (compliance) │ -└──────────────────────────────────────────────────────────────────┘ -``` - ---- - -## Stack Technique - -| Composant | Technologie | -|---|---| -| **Frontend** | React / Next.js + TailwindCSS | -| **Wallet** | WalletConnect / MetaMask (adapté ADI) | -| **Smart Contracts (ADI)** | Solidity (EVM-compatible) | -| **Smart Contracts (Canton)** | Daml | -| **Smart Contracts (Hedera)** | Solidity (Hedera Smart Contract Service) + Hedera SDK | -| **IA / Inférence** | 0G Compute | -| **Backend API** | Node.js / Express (bridge entre les couches) | -| **Déploiement** | Vercel (frontend) + Devnets/Testnets (contrats) | - ---- - -## Structure du Dépôt - -``` -ETH-Denver/ -├── CLAUDE.md # Context Claude Code -├── PROJECT_OVERVIEW.md # Ce fichier -├── TIMELINE.md # Roadmap et suivi d'avancement -├── .env.example # Template des variables d'environnement -├── packages/ -│ ├── contracts-adi/ # Foundry — Solidity (ADI chain) -│ │ ├── src/ # 6 contrats (InstiVaultAccessControl, RWAToken, etc.) -│ │ ├── test/ # 111 tests Forge -│ │ ├── script/ # Deploy.s.sol + Demo.s.sol -│ │ ├── abi/ # ABIs extraits pour le backend -│ │ └── broadcast/ # Records de déploiement (Sepolia + ADI) -│ ├── contracts-hedera/ # Solidity + Hedera SDK -│ │ ├── contracts/ # CouponScheduler, YieldDistributor, HederaScheduleService -│ │ ├── test/ # 74 tests Forge -│ │ ├── src/ # Scripts TS (deploy, schedule-coupon, e2e-test) -│ │ ├── abi/ # ABIs extraits pour le backend -│ │ └── deployments.json # Adresses déployées Hedera Testnet -│ ├── contracts-canton/ # Templates Daml (Canton Network) -│ │ └── daml/ # ConfidentialVault, PrivateTrade, AuditRight + tests -│ ├── ai-engine/ # Module IA (0G Compute) -│ │ └── src/ # risk-analyzer, strategy-simulator, 0g-client -│ ├── backend/ # Express API (TypeScript) -│ │ └── src/ # Routes (adi, hedera, canton, ai) + config -│ └── frontend/ # Next.js + TailwindCSS + RainbowKit -│ └── src/ # Pages, composants UI, mock data -└── pnpm-workspace.yaml -``` - ---- - -## Bounties Ciblés — Checklist de Conformité - -### ADI Foundation -- [x] MVP déployé sur chaîne ADI (99999) + Sepolia (11155111) -- [x] Utilité économique réelle (tokenisation + vault + fractionnement + allocation) -- [x] Architecture white-label ready (InstitutionRegistry multi-tenant) -- [x] RBAC (4 rôles) + multisig 2-of-N pour l'administration -- [x] Pausable sur VaultManager (arrêt d'urgence) -- [x] 111 tests passants + script de démo (`Demo.s.sol`) - -### Canton Network -- [x] Contrats Daml natifs (ConfidentialVault, PrivateTrade, AuditRight) -- [ ] Déployés sur Devnet Canton L1 -- [x] Séparation de visibilité démontrée (Owner/Counterparty/Auditor) - -### Hedera -- [x] Utilisation du Hedera Schedule Service (precompile 0x16b) -- [x] Transactions planifiées créées et exécutées (paiements de coupons) -- [x] Initiation depuis un smart contract (pas depuis un script off-chain) -- [x] Access control sur executeCoupon + Pausable -- [x] 74 tests passants, déployé sur Hedera Testnet - -### 0G Labs -- [x] Intégration de 0G Compute (inférence) -- [x] Décisions structurées produites par l'IA (score de risque, recommandations) -- [x] Human-in-the-loop : approbation utilisateur avant exécution - ---- - -## Livrables Hackathon - -| Livrable | Statut | Description | -|---|---|---| -| Dépôt GitHub public | [x] Créé | github.com/DVB-ANS/ETH-DENVER | -| URL de démo live | [ ] À déployer | Interface web institutionnelle fonctionnelle | -| Vidéo de démo | [ ] À enregistrer | < 3 minutes, flux complet du produit | -| README complet | [ ] À rédiger | Setup, architecture, modèle de confidentialité | - ---- - -## Risques Techniques Identifiés - -| Risque | Impact | Mitigation | -|---|---|---| -| Daml (Canton) — langage peu familier | Élevé | Commencer le développement Daml en priorité | -| Hedera Schedule Service — documentation limitée | Moyen | Prototyper rapidement avec le SDK Hedera | -| Interopérabilité entre 4 chaînes/services | Élevé | Backend API comme couche d'orchestration | -| 0G Compute — SDK en phase early | Moyen | Fallback possible sur un mock d'inférence pour la démo | -| Temps limité (hackathon) | Élevé | Prioriser les exigences critiques de chaque bounty | - ---- - -## Prochaines Étapes - -1. ~~Initialiser le repo~~ ✅ -2. ~~Canton/Daml~~ ✅ (templates + tests, reste deploy Devnet L1) -3. ~~ADI~~ ✅ (6 contrats, 111 tests, déployé Sepolia + ADI) -4. ~~Hedera~~ ✅ (74 tests, déployé Hedera Testnet) -5. ~~0G Labs~~ ✅ (risk-analyzer, strategy-simulator, mock fallback) -6. **Frontend** — Remplacer les mock data par les vrais appels API backend -7. **Deploy Canton** — Déployer les templates Daml sur Devnet L1 -8. **Tests & Démo** — Scénario de bout en bout + enregistrement vidéo diff --git a/markdown/TIMELINE.md b/markdown/TIMELINE.md deleted file mode 100644 index 2954c40..0000000 --- a/markdown/TIMELINE.md +++ /dev/null @@ -1,224 +0,0 @@ -# Metaphor — Roadmap (3 Devs) - -## Git Workflow - -``` -main ← stable, deployable -├── develop ← integration branch (merge PRs here) -│ ├── feat/adi-* ← Dev A branches -│ ├── feat/hedera-* ← Dev A branches -│ ├── feat/canton-* ← Dev B branches -│ ├── feat/ai-* ← Dev B branches -│ ├── feat/frontend-* ← Dev C branches -│ └── feat/backend-* ← Dev C branches -``` - -**Rules:** -- Always branch from `develop` -- PR into `develop`, never directly into `main` -- `main` is updated only when `develop` is stable (before demo, before submission) -- Prefix commits: `feat:`, `fix:`, `test:`, `docs:`, `chore:` ---- - -## Team Split - -| Dev | Scope | Packages | -|-----|-------|----------| -| **Dev A** | Solidity — ADI + Hedera | `contracts-adi/`, `contracts-hedera/` | -| **Dev B** | Daml + AI — Canton + 0G Labs | `contracts-canton/`, `ai-engine/` | -| **Dev C** | Web — Frontend + Backend API | `frontend/`, `backend/` | - ---- - -## Phase 0 — Project Setup (All) - -- [x] Initialize monorepo structure (`packages/`) -- [x] Setup package manager and workspace configuration -- [x] Configure shared tooling (TypeScript, linting, formatting) -- [x] Setup environment variables template (`.env.example`) -- [x] Initialize git repository and `.gitignore` -- [x] Create `develop` branch from `main` - ---- - -## Phase 1 — Core Contracts & Scaffolding (Parallel) - -> All 3 devs work simultaneously on their own packages. - -### Dev A — ADI Contracts `feat/adi-core` -- [x] Implement `InstiVaultAccessControl.sol` — Roles: Admin, Issuer, Investor, Auditor + whitelisting -- [x] Implement `RWATokenFactory.sol` — ERC-20 mint with on-chain metadata (ISIN, rate, maturity, issuer) -- [x] Implement `RWAToken.sol` — ERC-20 with whitelist transfer restrictions + burn-at-maturity -- [x] Implement `VaultManager.sol` — Vault creation, deposit, withdrawal, allocation + Pausable -- [x] Implement `InstitutionRegistry.sol` — Multi-tenant white-label + 2-of-N multisig -- [x] Implement `InstitutionDeployer.sol` — External deployer (EIP-170 workaround) -- [x] Whitelist-gated transfers (KYC wallets only) -- [x] Unit tests (111 tests passing) -- [x] Deployed to Sepolia + ADI Chain (99999) -- [x] ABIs exported to `abi/` for backend -- [x] PR → `develop` - -### Dev B — Canton Templates `feat/canton-core` -- [x] Install Daml SDK, configure project -- [x] Implement `ConfidentialVault` — Vault visible only to authorized parties -- [x] Implement `PrivateTrade` — Bilateral offer/counter-offer -- [x] Implement `AuditRight` — Limited audit view for third parties -- [x] Daml script tests for each template -- [x] PR → `develop` - -### Dev C — Frontend Scaffold + Backend Init `feat/frontend-scaffold` -- [x] Initialize Next.js + TailwindCSS (`packages/frontend/`) -- [x] Configure wallet connection (RainbowKit + WalletConnect) — SSR-safe -- [x] Setup routing, layout (sidebar + main content), navigation -- [x] Build static **Dashboard** page (mock data) -- [x] Build static **Issue Asset** form page (mock data) -- [x] Setup Express/Node.js backend (`packages/backend/`) -- [x] PR → `develop` - ---- - -## Phase 2 — Extended Logic (Parallel) - -> Devs continue on their scope, adding business logic. - -### Dev A — Hedera Contracts `feat/hedera-core` -- [x] Implement `CouponScheduler.sol` — Scheduled transactions via Hedera Schedule Service precompile (0x16b) -- [x] Compute payment dates from bond parameters (rate, frequency, maturity) -- [x] Ensure scheduling is initiated from the smart contract (not off-chain) -- [x] Implement `YieldDistributor.sol` — Pro-rata distribution to token holders -- [x] Snapshot mechanism (recalculate shares if tokens transferred between coupons) -- [x] Access control on `executeCoupon` (self-call / issuer / owner) -- [x] Pausable on scheduling operations -- [x] Unit tests (74 tests passing) -- [x] Deployed to Hedera Testnet -- [x] ABIs exported to `abi/` for backend -- [x] PR → `develop` - -### Dev A — ADI Token Logic `feat/adi-token-logic` -- [x] Fractionnement logic (split asset into N tokens) -- [x] Burn-at-maturity mechanism (auto burn + nominal reimbursement) -- [x] Final payment: last coupon + nominal + token burn -- [x] Integration tests (mint → transfer → burn full lifecycle) -- [x] Demo script (`script/Demo.s.sol`) — full flow on Sepolia -- [x] PR → `develop` - -### Dev B — Canton Visibility Model `feat/canton-visibility` -- [x] Implement `Owner` visibility (full access) -- [x] Implement `Counterparty` visibility (composition + trade proposals) -- [x] Implement `Auditor` visibility (compliance-only read access) -- [x] Verify unauthorized parties see nothing -- [x] Test multi-party scenarios (3 parties with different views) -- [x] PR → `develop` - -### Dev B — AI Engine `feat/ai-risk-analyzer` -- [x] Configure 0G Compute client (`0g-client.ts`) -- [x] Implement `risk-analyzer.ts` — Composite risk score (1-100) -- [x] Implement `strategy-simulator.ts` — Stress testing (rate changes, defaults, crises) -- [x] Generate actionable recommendations (rebalance, exit, add collateral) -- [x] Test with mock vault data -- [x] Fallback: mock inference if 0G SDK is unstable -- [x] PR → `develop` - -### Dev C — Frontend Pages `feat/frontend-pages` -- [x] **My Vaults** page — Vault list with filters (risk, asset type, status) -- [x] **Vault Detail** page — Composition, yield history, chart, "Analyze with AI" button -- [x] **Data Room** page — Canton vault management (invitations, access levels, negotiations) -- [x] **Yield Calendar** page — Calendar view of Hedera payments -- [x] **AI Reports** page — Analysis history, score evolution, PDF export -- [x] **Administration** page — RBAC management, wallet whitelist, white-label config -- [ ] Replace mock data with real API calls (currently 100% mock) -- [x] PR → `develop` - ---- - -## Phase 3 — Backend Bridges & Contract Wiring (Parallel) - -> Connect frontend to contracts through the backend API. - -### Dev A — Hedera Edge Cases + Deploy `feat/hedera-edge-cases` -- [x] Insufficient liquidity handling (suspend payment, alert issuer + investors) -- [x] No silent partial execution (all-or-nothing) -- [x] End-to-end test: schedule → execute → verify balances -- [x] Deploy ADI contracts to ADI chain + Sepolia -- [x] Deploy Hedera contracts to Hedera Testnet -- [x] PR → `develop` - -### Dev B — Canton Deploy + AI Human-in-the-Loop `feat/canton-deploy` -- [x] Deploy Daml templates to Canton LocalNet (28/28 tests passing, sandbox verified) -- [x] Ensure AI never auto-executes transactions -- [x] Every AI recommendation requires explicit user confirmation -- [x] Validate structured output format (score, recommendations, stress test) -- [x] PR → `develop` - -### Dev C — Backend API Bridges `feat/backend-bridges` -- [x] ADI bridge — Tokenization + vault + institution endpoints -- [x] Canton bridge — Proxy for Daml ledger API (vault creation, invitations, trades) -- [x] Hedera bridge — Coupon scheduling + payment status + yield endpoints -- [x] 0G bridge — Trigger AI analysis and return structured results -- [x] Fix ESM __dirname issue for ABI loading -- [x] Authentication middleware (wallet-based nonce + signature + JWT) -- [x] Role verification middleware (check RBAC from ADI contracts, fast JWT + on-chain fallback) -- [x] PR → `develop` - ---- - -## Phase 4 — Integration & Wiring (All together) - -> All devs work on connecting their layers into the frontend. - -### Dev C (lead) + Dev A — ADI + Hedera Frontend Integration `feat/frontend-adi-hedera` -- [ ] Wire **Issue Asset** form to ADI `RWATokenFactory` via backend -- [ ] Wire **My Vaults** to `VaultManager` via backend -- [ ] Wire **Yield Calendar** to Hedera `CouponScheduler` via backend -- [ ] Live data on **Dashboard** (total value, vault count, upcoming payments) -- [ ] PR → `develop` - -### Dev C (lead) + Dev B — Canton + AI Frontend Integration `feat/frontend-canton-ai` -- [ ] Wire **Data Room** page to Canton Daml via backend -- [ ] Wire **Vault Detail** → "Analyze with AI" to 0G via backend -- [ ] Wire **AI Reports** page to display structured results -- [ ] Human-in-the-loop UI: confirm/reject buttons on AI recommendations -- [ ] PR → `develop` - -### Dev A + Dev B — RBAC + White-Label `feat/adi-rbac-whitelabel` -- [x] Multi-tenant registry (InstitutionRegistry — each institution gets isolated contracts) -- [x] Role-based function access modifiers across all contracts -- [x] Multisig (2-of-N approval for institution registration) -- [x] PR → `develop` - ---- - -## Phase 5 — Role-Based Views & Polish (All together) - -### Dev C — Role-Based Views `feat/frontend-roles` -- [ ] Admin view (full access) -- [ ] Issuer view (own assets only) -- [ ] Investor view (own vaults only) -- [ ] Auditor view (compliance-limited) -- [ ] PR → `develop` - -### All — UX & Polish `feat/polish` -- [ ] Notification system (48h before payments, post-execution confirmation) -- [ ] Loading states and error handling -- [ ] Responsive design -- [ ] PR → `develop` - ---- - -## Phase 6 — End-to-End Testing (All together) - -- [x] Full flow: auth → dashboard → AI analyze → approve → reports → payments (E2E verified) -- [ ] Multi-party demo: 3 users with different roles seeing different data -- [x] Verify bounty compliance for each sponsor (ADI, Canton, Hedera, 0G) — see BOUNTY_COMPLIANCE.md -- [x] All tests passing: ADI 111, Hedera 74, Canton 28 = 213 total -- [ ] Merge `develop` → `main` - ---- - -## Phase 7 — Deliverables (All together) - -- [ ] Public GitHub repository with complete documentation -- [ ] Live demo URL (deploy frontend on Vercel) -- [ ] README with setup instructions, architecture, privacy model -- [x] `BOUNTY_COMPLIANCE.md` — Mapping bounties to implemented features -- [ ] Demo video (< 3 min) covering the full product flow diff --git a/markdown/devC.md b/markdown/devC.md deleted file mode 100644 index d341fd1..0000000 --- a/markdown/devC.md +++ /dev/null @@ -1,212 +0,0 @@ -# Dev C — Progress Notes - -## Phase 1 — Frontend Scaffold + Backend Init (DONE) - -### Completed -- [x] Initialize Next.js 16 + TailwindCSS v4 (`packages/frontend/`) — App Router -- [x] Install and configure shadcn/ui (new-york style, neutral, lucide icons) -- [x] Configure wallet connection — RainbowKit 2.x + wagmi 2.x + viem 2.x + react-query -- [x] App layout: Sidebar navigation + Topbar with ConnectButton -- [x] Static Dashboard page (mock data) -- [x] Static Issue Asset form -- [x] Setup Express backend (`packages/backend/`) — health endpoint, CORS -- [x] Backend added to pnpm workspace + root scripts - -## Phase 2 — Enhanced Pages (DONE) - -### Completed -- [x] **My Vaults** — Filter controls: search, risk level, status, asset type. Cards link to vault detail. -- [x] **Vault Detail** (`/vaults/[id]`) — Key metrics, asset composition table, allocation pie chart (recharts), risk score history bar chart, upcoming + past payments, "Analyze with AI" button with loading state, AI analysis panel with position analysis + stress tests + recommendations, human-in-the-loop approve/reject with confirmation dialog -- [x] **Data Room** — Canton visibility model explainer (Owner/Counterparty/Auditor), confidential vault list with authorized parties table (role, visibility, public key), PrivateTrade proposals with accept/counter/reject actions, invite party dialog -- [x] **Yield Calendar** — Summary stats (total distributed, upcoming, completed count, scheduled count), tabbed view (Timeline / Upcoming / Completed), visual timeline with month groupings and "Now" marker, vault filter -- [x] **AI Reports** — Risk score evolution line chart (recharts) with risk zone reference lines, vault filter, position analysis per report, approve/reject per recommendation with confirmation dialog, PDF export button (mock) -- [x] **Administration** — RBAC grid with role counts + permission badges, wallet whitelist table with add/remove, white-label config form (institution name, domain, color picker, logo upload placeholder, live preview) - -### Dependencies added -- `recharts` — Charts (pie, bar, line) -- `progress` shadcn component — Risk score visualization - -### Tech Choices -- **Router**: App Router (app/ directory) -- **UI**: shadcn/ui + TailwindCSS v4 -- **Wallet**: RainbowKit + wagmi v2 -- **Icons**: lucide-react -- **Charts**: recharts -- **Backend**: Express + tsx (dev), TypeScript strict -- **Language rule**: All user-facing text must be in English. All units must use the imperial system. - -### Run Commands -```bash -pnpm dev:frontend # Next.js on port 3000 -pnpm dev:backend # Express on port 4000 -``` - -### Routes -| Route | Page | Status | -|-------|------|--------| -| `/` | Landing | Done | -| `/app` | Dashboard | Done | -| `/vaults` | My Vaults (with filters) | Done | -| `/vaults/[id]` | Vault Detail + AI analysis | Done | -| `/issue` | Issue Asset form | Done | -| `/data-room` | Canton Data Room | Done | -| `/yield-calendar` | Hedera Yield Calendar | Done | -| `/ai-reports` | 0G AI Reports | Done | -| `/admin` | Administration | Done | -| `/demo/canton` | Canton 3-Panel Demo | Done | - -## Phase 3 (Backend Bridges) — DONE - -### Completed -- [x] **Canton bridge** — Full Daml JSON API proxy (`packages/backend/src/routes/canton.ts`) - - Canton JSON API client (`services/canton-client.ts`) — create, exercise, query, fetch with party-scoped JWT auth - - Vault CRUD: `POST/GET /api/canton/vaults`, `GET /api/canton/vaults/:id` - - Asset management: `POST/DELETE /api/canton/vaults/:id/assets` - - Invitations: `POST /api/canton/vaults/:id/invite`, accept/decline - - Counterparties: `POST/DELETE /api/canton/vaults/:id/counterparties` - - Trades: `POST /api/canton/vaults/:id/trades`, accept/reject, `GET /api/canton/trades` - - Lifecycle: freeze, activate, close - - Party resolution via `X-Canton-Party` header or env fallback -- [x] **0G bridge** — AI analysis endpoints (`packages/backend/src/routes/ai.ts`) - - `POST /api/ai/analyze` — triggers 0G Compute inference (mock fallback when 0G not configured) - - `GET /api/ai/reports` — list reports (filter by vaultId) - - `GET /api/ai/reports/:id` — single report detail - - `POST /api/ai/reports/:id/approve` — approve recommendation (single or all) - - `POST /api/ai/reports/:id/reject` — reject recommendation (single or all) - - In-memory report store with structured response matching Dev B's spec -- [x] **ADI bridge** — Tokenization + vault + institution endpoints (`packages/backend/src/routes/adi.ts`) - - `GET/POST /api/adi/tokens` — list & create RWA tokens - - `POST /api/adi/tokens/:address/fractionalize` — fractionalize tokens - - `POST /api/adi/vaults` — create vault, `GET /api/adi/vaults/:id` — vault info - - `GET /api/adi/vaults/:id/balance/:token` — balance check - - `POST /api/adi/vaults/:id/deposit|withdraw|allocate|deallocate` — vault operations - - `GET/POST /api/adi/institutions` — list & register institutions - - `POST /api/adi/institutions/propose` — multisig proposal flow - - `POST /api/adi/institutions/proposals/:id/approve|execute` — governance actions -- [x] **Hedera bridge** — Coupon scheduling + yield distribution (`packages/backend/src/routes/hedera.ts`) - - `GET/POST /api/hedera/bonds` — list & register bonds - - `GET /api/hedera/bonds/:id` — bond detail with payment schedule - - `POST /api/hedera/bonds/:id/schedule-all|schedule` — schedule coupons - - `POST /api/hedera/bonds/:bondId/payments/:date/recover` — recover failed payments - - `GET /api/hedera/yield/snapshots/:id` — snapshot info - - `POST /api/hedera/yield/distribute` — yield distribution - - `POST /api/hedera/yield/claim` — claim yield - - `GET /api/hedera/yield/unclaimed/:holder/:paymentToken` — unclaimed amounts -- [x] **Auth middleware** — Wallet-based authentication (`packages/backend/src/middleware/auth.ts`) - - Nonce generation + SIWE-style signature verification - - JWT token issuance (24h expiry) - - `requireAuth` middleware — blocks unauthenticated requests - - `optionalAuth` middleware — populates req.auth if token present - - Auth routes: `POST /api/auth/nonce`, `POST /api/auth/login`, `GET /api/auth/me` -- [x] **RBAC middleware** — Role verification (`packages/backend/src/middleware/rbac.ts`) - - `requireRole('ADMIN', 'ISSUER', ...)` — checks JWT claim + on-chain fallback - - `requireWhitelist()` — verifies wallet whitelist on ADI AccessControl - - `fetchWalletRoles(address)` — queries all 4 roles from contract - - Role hashes computed via `ethers.id()` matching Solidity `keccak256()` -- [x] Auth + RBAC applied to all write endpoints across ADI, Hedera, Canton, and AI routes -- [x] Shared types: `src/types/canton.ts`, `src/types/ai.ts`, `src/types/auth.ts` -- [x] Updated `.env.example` with `CANTON_JSON_API_PORT`, `CANTON_LEDGER_ID`, `CANTON_PACKAGE_ID`, `JWT_SECRET` - -## Phase 4 (Frontend ↔ Backend Integration) — DONE - -### Completed -- [x] **API client** — `packages/frontend/src/lib/api.ts` - - Shared fetch wrapper with JWT auth header injection - - Token stored in localStorage, auto-attached to all requests - - `ApiError` class with status + body for structured error handling - - Convenience methods: `api.get()`, `api.post()`, `api.put()`, `api.delete()` -- [x] **Auth context** — `packages/frontend/src/contexts/auth-context.tsx` - - Full nonce → wallet signature → JWT flow using wagmi `signMessageAsync` - - Session restore from localStorage on mount (validates via `/api/auth/me`) - - Auto-clear on wallet disconnect or address change - - Exposes: `isAuthenticated`, `roles`, `signIn()`, `signOut()`, `hasRole()` -- [x] **Sign In / Sign Out** — Topbar shows explicit "Sign In" button when wallet connected but not authenticated - - Role badges displayed after sign-in - - Error display for failed sign-in attempts -- [x] **Backend demo API** — `packages/backend/src/routes/demo.ts` - - New route file serving UI-friendly demo data with mock fallbacks - - Does NOT modify Dev A's routes (no merge conflict risk) - - Endpoints: `/api/demo/dashboard`, `/api/demo/vaults`, `/api/demo/payments`, `/api/demo/canton/vaults`, `/api/demo/canton/demo/:vaultId/:role`, `/api/demo/ai/reports`, `/api/demo/ai/score-history`, `/api/demo/admin/wallets`, `/api/demo/admin/roles` - - Canton demo endpoint returns party-scoped views (owner/counterparty/auditor) with proper data filtering -- [x] **Dashboard** wired to `/api/demo/dashboard` — stats, vaults, upcoming payments, latest AI analysis -- [x] **My Vaults** wired to `/api/demo/vaults` — vault list with filters -- [x] **Data Room** wired to `/api/demo/canton/vaults` — confidential vaults + trades -- [x] **Yield Calendar** wired to `/api/demo/payments` + `/api/demo/vaults` — payments + vault filter -- [x] **AI Reports** wired to `/api/demo/ai/reports` + `/api/demo/ai/score-history` — reports + chart data -- [x] **Administration** wired to `/api/demo/admin/wallets` — wallet whitelist + role counts -- [x] All pages have loading states (animated pulse) and error states (red message + backend hint) - -## Phase 4b (Canton Bounty Demo) — DONE - -### Completed -- [x] **Canton 3-Panel Demo** — `/demo/canton` - - Dedicated page with 3 side-by-side panels: Owner / Counterparty / Auditor - - Each panel fetches from `/api/demo/canton/demo/cv-1/:role` - - **Owner view**: Full vault data, all assets with values, all parties, all trades (with accept/counter/reject buttons), complete audit log - - **Counterparty view**: Vault data with values, assets with financials, only own party + owner visible, only own trades visible, no audit log - - **Auditor view**: Vault name + asset count (no total value), assets with ratings/jurisdiction only (no values/coupons), only owner visible, no trades, compliance-only audit log - - Restricted data shown with lock icons and "restricted" labels - - Legend explaining each role's access level - - Explanation of Canton Network / Daml templates (ConfidentialVault, PrivateTrade, AuditRight) - - Added to sidebar navigation (Columns3 icon) - - Color-coded panel borders: neutral (owner), blue (counterparty), yellow (auditor) - -## Phase 5 (Role-Based Views) — DONE - -### Completed -- [x] **RoleGate component** — `packages/frontend/src/components/role-gate.tsx` - - `` — wraps content, shows "Restricted Access" message if user lacks role - - `` — silent variant, renders nothing if unauthorized - - Shows user's current roles and what roles are required - - Unauthenticated users see content by default (pages handle their own auth) -- [x] **Issue Asset** — gated to ADMIN + ISSUER roles -- [x] **Administration** — gated to ADMIN role only -- [x] Loading states on all API-wired pages -- [x] Error states with backend connection hints - -### New Files Created -| File | Purpose | -|------|---------| -| `frontend/src/lib/api.ts` | API client with JWT auth | -| `frontend/src/contexts/auth-context.tsx` | Auth state management | -| `frontend/src/hooks/use-api.ts` | Generic data-fetching hook | -| `frontend/src/components/role-gate.tsx` | Role-based access control UI | -| `frontend/src/app/demo/canton/page.tsx` | Canton 3-panel bounty demo | -| `backend/src/routes/demo.ts` | Demo API with mock fallbacks | - -### Modified Files -| File | Change | -|------|--------| -| `frontend/src/providers/web3-provider.tsx` | Added AuthProvider inside RainbowKit | -| `frontend/src/components/layout/topbar.tsx` | Added Sign In/Out buttons + role badges | -| `frontend/src/components/layout/sidebar.tsx` | Added Canton Demo nav item | -| `frontend/src/app/app/page.tsx` | Wired to `/api/demo/dashboard` | -| `frontend/src/app/vaults/page.tsx` | Wired to `/api/demo/vaults` | -| `frontend/src/app/data-room/page.tsx` | Wired to `/api/demo/canton/vaults` | -| `frontend/src/app/yield-calendar/page.tsx` | Wired to `/api/demo/payments` | -| `frontend/src/app/ai-reports/page.tsx` | Wired to `/api/demo/ai/reports` | -| `frontend/src/app/admin/page.tsx` | Wired to `/api/demo/admin/wallets` + RoleGate | -| `frontend/src/app/issue/page.tsx` | Added RoleGate for ADMIN/ISSUER | -| `backend/src/index.ts` | Registered demo routes | - -## Running the Demo - -```bash -# Terminal 1 — Backend -pnpm dev:backend # Express on port 4000 - -# Terminal 2 — Frontend -pnpm dev:frontend # Next.js on port 3000 -``` - -Both servers must be running. The frontend fetches data from the backend's demo API which provides mock fallbacks for all services (ADI, Hedera, Canton, 0G). - -### Demo Flow -1. Open `http://localhost:3000` — Landing page -2. Click "Launch App" — Dashboard -3. Connect wallet (MetaMask / WalletConnect) -4. Click "Sign In" — wallet signature prompt -5. Navigate through all pages — data loads from backend -6. Visit `/demo/canton` — 3-panel visibility demo for Canton bounty -7. Try `/admin` — requires ADMIN role -8. Try `/issue` — requires ADMIN or ISSUER role diff --git a/packages/frontend/README.md b/packages/frontend/README.md deleted file mode 100644 index e215bc4..0000000 --- a/packages/frontend/README.md +++ /dev/null @@ -1,36 +0,0 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). - -## Getting Started - -First, run the development server: - -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/sentier.jpeg b/sentier.jpeg deleted file mode 100644 index 03a9c6a..0000000 Binary files a/sentier.jpeg and /dev/null differ