diff --git a/.agent0/required_paths.txt b/.agent0/required_paths.txt index 797665f..bcdbfe6 100644 --- a/.agent0/required_paths.txt +++ b/.agent0/required_paths.txt @@ -6,6 +6,7 @@ identity/README.md # Python identity/verify_identity.py +identity/forge_check.py pyproject.toml # GitHub diff --git a/docs/IDENTITY_QUICKSTART.md b/docs/IDENTITY_QUICKSTART.md new file mode 100644 index 0000000..c50cd46 --- /dev/null +++ b/docs/IDENTITY_QUICKSTART.md @@ -0,0 +1,61 @@ +# Identity Quickstart Guide (5-min) + +Get your identity forged and verify status on Base Mainnet. + +## Prerequisites +- **Wallet**: With Base ETH (gas) and ≥ 1.0 MPASS (gate token). +- **Environment**: Python 3.8+ installed. +- **Foundry**: `cast` CLI tool installed (`curl -L https://foundry.paradigm.xyz | bash`). + +## Step 1: Check Readiness + +Before attempting to forge, verify your wallet meets the requirements. + +```bash +# Verify MPASS balance and Router status +python3 identity/forge_check.py 0xYourWalletAddress +``` + +**Output:** +``` +ToadAid Forge Check: READY TO FORGE +-------------------------------------------------- +Router Status: ✓ Active +MPASS Balance: 1.5000 (Min: 1.0) +Gate Check: ✓ Pass +``` + +If checks pass (exit code 0), proceed to Step 2. + +## Step 2: Forge Identity + +1. **Visit**: [https://toadaid.github.io/forge](https://toadaid.github.io/forge) +2. **Connect**: Your wallet (Base Mainnet). +3. **Fill**: Agent Name, Description, Image URL. +4. **Submit**: Sign the transaction. + +## Step 3: Verify Registration + +Confirm your identity is live on the registry. + +```bash +# Check registry status +python3 identity/verify_identity.py 0xYourWalletAddress +``` + +**Output:** +``` +✓ Found 1 registered agent(s) + - Agent #12345 + https://toadaid.github.io/agent?id=12345 +``` + +## Troubleshooting + +* **Error: `cast not found`**: Install Foundry. +* **Error: `RPC request timed out`**: Use `--rpc-url` with a custom endpoint (Alchemy/Infura). +* **Status: NOT READY**: Ensure you hold at least 1.0 MPASS on Base. + +## Next Steps +- Explore `tools/` for advanced utilities. +- Read `identity/README.md` for technical details. diff --git a/identity/README.md b/identity/README.md index 604f2e9..ffbe778 100644 --- a/identity/README.md +++ b/identity/README.md @@ -1,28 +1,39 @@ -# identity/ +# Identity Toolkit -Identity verification toolkit for ToadAid ERC-8004 registry. - -## Purpose - -Tools for verifying and interacting with ToadAid identity infrastructure: -- Check wallet status in registry -- Verify MPASS gating requirements -- Lookup agent metadata -- Validate registration status +Tools for verifying and interacting with ToadAid ERC-8004 registry on Base. ## Tools -- `verify_identity.py` — Check wallet registry status -- `forge_check.py` — Verify MPASS gating and router configuration +* `verify_identity.py`: Check if a wallet has registered agent(s). +* `forge_check.py`: Verify readiness to forge (MPASS balance + Router status). ## Contracts (Base Mainnet) -- Registry Proxy: `0x8004A169F84a3325136EB29fA0ceB6D2e539a432` -- Base Implementation: `0x7274e874CA62410a93Bd8bf61c69d8045E399c02` -- MPASS Token: Check registry for current gate token +| Component | Address | Purpose | +| :--- | :--- | :--- | +| **Registry Proxy** | `0x8004A169F84a3325136EB29fA0ceB6D2e539a432` | Main identity registry | +| **Registry Router** | `0x17163e538029b04D4cC24f82aa6AC3B877Bd0e0` | Forging interface | +| **MPASS Token** | `0xdb9e64465d4b5fbc7ee9091c459094efc7df5cde` | Gating requirement (≥ 1.0) | +| **Reputation Router** | `0x94D7B431dD8eAFc9E1b71624DF0a90468622537a` | Attestation logic | + +## Usage + +**Check Readiness (Pre-Forge):** +```bash +python3 identity/forge_check.py 0xWalletAddress +``` + +**Check Status (Post-Forge):** +```bash +python3 identity/verify_identity.py 0xWalletAddress +``` ## Safety -- Read-only operations only -- No wallet connection required -- Safe defaults on all queries +* **Read-only**: No private keys required. +* **Subprocess Isolation**: Uses `cast` for safe onchain reads. +* **No API Keys**: Default RPC is public Base endpoint (rate limited). + +## Contributing + +See `docs/TOOLING_STANDARD.md` for CLI guidelines. diff --git a/identity/forge_check.py b/identity/forge_check.py new file mode 100644 index 0000000..0f0ad46 --- /dev/null +++ b/identity/forge_check.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +""" +forge_check.py - Verify readiness to forge a ToadAid identity. + +Design: +- Read-only checks against Base Mainnet. +- Verifies MPASS balance (gating requirement). +- Verifies Router contract availability. +- Exit codes: 0=Ready, 2=Not Ready, 3=Error. + +Usage: + python3 identity/forge_check.py 0xWalletAddress [options] +""" + +import sys +import subprocess +import json +import re +import argparse + +# Contract Addresses (Base Mainnet) +CONTRACTS = { + "REGISTRY_ROUTER": "0x17163e538029b04D4cC24f82aa6AC3B877Bd0e0", + "REPUTATION_ROUTER": "0x94D7B431dD8eAFc9E1b71624DF0a90468622537a", + "MPASS_TOKEN": "0xdb9e64465d4b5fbc7ee9091c459094efc7df5cde", + "REGISTRY_PROXY": "0x8004A169F84a3325136EB29fA0ceB6D2e539a432" # Canonical Agent 0 Registry +} + +# Gate Requirements +MPASS_MIN_BALANCE = 1.0 + +def is_valid_address(addr): + """Validate Ethereum address format.""" + if not addr: return False + return bool(re.match(r'^0x[a-fA-F0-9]{40}$', addr)) + +def call_cast(args, rpc_url=None): + """Safe cast call wrapper.""" + cmd = ["cast"] + args + if rpc_url: + cmd.extend(["--rpc-url", rpc_url]) + + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + timeout=30 + ) + if result.returncode != 0: + raise RuntimeError(f"cast failed: {result.stderr.strip()}") + return result.stdout.strip() + except FileNotFoundError: + raise RuntimeError("cast not found. Install Foundry: https://book.getfoundry.sh/") + except subprocess.TimeoutExpired: + raise RuntimeError("RPC request timed out") + +def get_balance(token, wallet, rpc_url=None): + """Get ERC-20 balance (formatted).""" + # 1. Get decimals + try: + decimals = int(call_cast(["call", token, "decimals()(uint8)"], rpc_url)) + except Exception: + decimals = 18 # Default if fails + + # 2. Get balance + raw = call_cast(["call", token, "balanceOf(address)(uint256)", wallet], rpc_url) + return int(raw) / (10 ** decimals) + +def check_contract_code(address, rpc_url=None): + """Verify contract exists on chain.""" + code = call_cast(["code", address], rpc_url) + return code != "0x" + +def main(): + parser = argparse.ArgumentParser(description="Check ToadAid Forge readiness.") + parser.add_argument("wallet", help="Wallet address to check") + parser.add_argument("--rpc-url", help="Base Mainnet RPC URL", default="https://mainnet.base.org") + parser.add_argument("--json", action="store_true", help="Output JSON format") + args = parser.parse_args() + + if not is_valid_address(args.wallet): + print(f"Error: Invalid wallet address: {args.wallet}", file=sys.stderr) + sys.exit(3) + + results = { + "wallet": args.wallet, + "ready": False, + "checks": {}, + "contracts": CONTRACTS + } + + try: + # 1. Check Router Status + router_ok = check_contract_code(CONTRACTS["REGISTRY_ROUTER"], args.rpc_url) + results["checks"]["router_active"] = router_ok + + # 2. Check MPASS Balance + mpass_bal = get_balance(CONTRACTS["MPASS_TOKEN"], args.wallet, args.rpc_url) + results["checks"]["mpass_balance"] = mpass_bal + results["checks"]["mpass_sufficient"] = mpass_bal >= MPASS_MIN_BALANCE + + # 3. Determine Readiness + if router_ok and (mpass_bal >= MPASS_MIN_BALANCE): + results["ready"] = True + exit_code = 0 + status_msg = "READY TO FORGE" + else: + exit_code = 2 + status_msg = "NOT READY" + + except Exception as e: + if args.json: + print(json.dumps({"error": str(e)})) + else: + print(f"Error: {e}", file=sys.stderr) + sys.exit(3) + + # Output + if args.json: + print(json.dumps(results, indent=2)) + else: + print("=" * 50) + print(f"ToadAid Forge Check: {status_msg}") + print("=" * 50) + print(f"Wallet: {args.wallet}") + print("-" * 50) + print(f"Router Status: {'✓ Active' if results['checks']['router_active'] else '✗ Inactive/Unreachable'}") + print(f"MPASS Balance: {results['checks']['mpass_balance']:.4f} (Min: {MPASS_MIN_BALANCE})") + print(f"Gate Check: {'✓ Pass' if results['checks']['mpass_sufficient'] else '✗ Fail'}") + print("-" * 50) + if results["ready"]: + print("Next Step: Visit https://toadaid.github.io/forge") + else: + print("Action Required: Acquire >= 1.0 MPASS to forge identity.") + + sys.exit(exit_code) + +if __name__ == "__main__": + main()