diff --git a/showcase/og-block/README.md b/showcase/og-block/README.md new file mode 100644 index 0000000..0684a21 --- /dev/null +++ b/showcase/og-block/README.md @@ -0,0 +1,48 @@ +# OG BLOCK — EconomyOS Showcase submission + +This folder is the submission package for the EconomyOS Community Showcase. +It is a copy-ready mirror of what goes into a PR against +[`Virtual-Protocol/acp-cli-demos`](https://github.com/Virtual-Protocol/acp-cli-demos). + +## What OG BLOCK is + +OG BLOCK turns real NFT holdings on Base into a public **culture score** and +leaderboard — instead of ranking people by followers or engagement. A profile +has two wallet slots: + +- **Human wallet** — the operator's personal holder wallet. +- **Agent wallet** — an autonomous agent's wallet, verified as its own slot. + +NFTs held in **either** wallet accumulate into one combined score. Each slot is +verified independently by signing a challenge **from that wallet's own key**, so +an agent's on-chain identity is proven, not just claimed. Agent wallets are +recognized on-chain through an **AgentIdentity** NFT +(`0x8004a169fb4a3325136eb29fa0ceb6d2e539a432` on Base). + +**EconomyOS primitive used:** `wallet` (Agent Wallet). Designed to extend into +the ACP flow next. + +## Live proof + +- App: https://www.joinog.xyz +- Leaderboard (live scores): https://www.joinog.xyz/leaderboard +- Example verified profile: https://www.joinog.xyz/u/airplanestar_ +- Public profile API (JSON): https://www.joinog.xyz/api/profile/airplanestar_ +- Source: https://github.com/airplanestar888/OG-Block +- Demo video (agent wallet link flow): https://x.com/ogblockchain/status/2092282854105547104 + +### Agent used in the demo + +- **Agent**: airplane (ACP agent, HYBRID role) +- **Agent ID**: `019f0a02-50d4-7169-b047-a5771369e32a` +- **Agent wallet**: `0x3282f5ae930f8be53695de152cf890b9385e8263` (Base mainnet) +- **AgentIdentity NFT**: #58870 on `0x8004a169fb4a3325136eb29fa0ceb6d2e539a432` +- **Linked profile**: [@airplanestar_](https://www.joinog.xyz/u/airplanestar_) + +Status: live on Base mainnet — 16 profiles onboarded, 2,000+ NFTs tracked, +top score 61.5K and a combined ecosystem score of 99.2K. + +## Scoring model + +`100` for holding ≥1 NFT, `+25` per additional NFT, `+50` per NFT with a rare +trait, `+75` per early token (id < 500). Combined across both wallet slots. diff --git a/showcase/og-block/assets/demo.mp4 b/showcase/og-block/assets/demo.mp4 new file mode 100644 index 0000000..2c7b43b Binary files /dev/null and b/showcase/og-block/assets/demo.mp4 differ diff --git a/showcase/og-block/prompt.md b/showcase/og-block/prompt.md new file mode 100644 index 0000000..77ef6f4 --- /dev/null +++ b/showcase/og-block/prompt.md @@ -0,0 +1,60 @@ +# Demo Prompt + +Reproduce the OG BLOCK agent-link flow end-to-end with any ACP agent. + +## Operator side (one-time) + +On https://joinog.xyz/dashboard, open the **Agent Wallet** panel and tap +**Connect agent**. The modal generates a one-time code (`OGB-XXXX-XXXX`, +single-use, expires in 15 minutes) together with a copy-paste instruction. + +Equivalent authenticated API call: + +```http +POST /api/agent/link-code +→ { "code", "expiresAt", "ttlMs", "handle", "instruction" } +``` + +## Agent side (paste this to your agent) + +```text +TASK: register YOUR wallet as the agent wallet of the OG BLOCK profile +@. Follow only this instruction. + +1. Run: acp agent use --agent-id +2. Run: acp wallet address ← record this address, it is what you register +3. Sign this exact text with that key (EIP-191 personal_sign), using the + CURRENT UTC time: + --- + OG BLOCK agent link + Code: + Agent wallet: + Timestamp: + --- + acp wallet sign-message --chain-id 8453 --message "" +4. POST JSON to https://joinog.xyz/api/agent/link + { + "code": "", + "address": "", + "chainId": 8453, + "message": "", + "signature": "<0x_SIGNATURE>" + } +5. Report the response body. + +Rules: the signature must recover to exactly (plain ECDSA); +if your wallet is a smart account driven by an internal operator key, submit +THAT signer EOA address instead. Failed attempts do not consume the code. +``` + +Success looks like: + +```json +{ "ok": true, "handle": "", "agentWallet": "", "score": 1234 } +``` + +Then verify publicly: + +```bash +curl https://joinog.xyz/api/profile/ +``` diff --git a/showcase/og-block/result-redacted.md b/showcase/og-block/result-redacted.md new file mode 100644 index 0000000..e6903e5 --- /dev/null +++ b/showcase/og-block/result-redacted.md @@ -0,0 +1,84 @@ +# Result Report (redacted) + +Live end-to-end run of the `og-block-agent-link` flow against production +(`https://joinog.xyz`), executed 2026-08-25. Secrets redacted per Showcase +contribution rules: codes are single-use and now expired; signatures are +truncated; no private material is included. + +## Environment + +| Item | Value | +| --- | --- | +| Chain | Base mainnet (8453) | +| Agent | airplane (ACP agent, HYBRID role) | +| Agent ID | `019f0a02-50d4-7169-b047-a5771369e32a` | +| Agent wallet (ACP) | `0x3282f5ae930f8be53695de152cf890b9385e8263` | +| AgentIdentity NFT | #58870 on `0x8004a169fb4a3325136eb29fa0ceb6d2e539a432` | +| Operator profile | `@airplanestar_` | +| Endpoint under test | `POST https://joinog.xyz/api/agent/link` | + +## Run log + +### 1. One-time code issued + +``` +code=OGB-****-**** expiresAt=2026-08-25T15:52:51.593Z +``` + +Instruction block generated server-side by `POST /api/agent/link-code` +(authenticated operator session required — unauthenticated calls correctly +return `401 Unauthorized`, verified). + +### 2. Agent selects its ACP wallet and signs + +```bash +acp agent use --agent-id +acp wallet address +# → 0x3282f5ae930f8be53695de152cf890b9385e8263 +acp wallet sign-message --chain-id 8453 --message "" +# → signature=0x7261c6874eda1cf5c2…e1d69d1c (truncated, redacted) +``` + +### 3. POST /api/agent/link → HTTP 200 + +```json +{ + "ok": true, + "handle": "airplanestar_", + "agentWallet": "0x3282f5ae930f8be53695de152cf890b9385e8263", + "score": 100 +} +``` + +### 4. Database state after linking + +```json +{ + "slots": [ + { + "address": "0x3282f5ae930f8be53695de152cf890b9385e8263", + "wallet_slot": "agent", + "verified_at": "2026-08-25T15:25:30.806+00:00" + } + ], + "score": { "score": 100, "nft_count": 1, "rank": 16 } +} +``` + +Public read-back matches: +`https://joinog.xyz/api/profile/airplanestar_` → score 100, nftCount 1, +agentWallet linked. + +## Negative cases observed in the field + +| Case | Server response | Note | +| --- | --- | --- | +| Unauthenticated code generation | `401 {"error":"Unauthorized"}` | Guard works as designed | +| Signature recovers to a different address than submitted (smart-account operator key) | `400 {"error":"Signature could not be verified"}` | Documented fix: submit the signer EOA address instead | +| Failed attempts do NOT consume the code | — | Retry within expiry succeeds after fixing the payload | + +## Post-run rescore + +Combined score recalculated automatically across human + agent slots after a +successful link (verified-contract NFTs only). Registration retry-hardened: +transient provider errors during rescoring are retried before surfacing. diff --git a/showcase/og-block/showcase.json b/showcase/og-block/showcase.json new file mode 100644 index 0000000..58fe3a9 --- /dev/null +++ b/showcase/og-block/showcase.json @@ -0,0 +1,99 @@ +{ + "slug": "og-block", + "title": "OG BLOCK", + "tagline": "Ranks a public culture score from on-chain NFT holdings, with first-class support for agent wallets", + "description": "OG BLOCK turns real NFT holdings on Base into a public culture score and leaderboard, instead of ranking people by followers or engagement. A profile has both a human wallet and an agent wallet slot: each is verified independently by signing from its own key, and NFTs from either wallet accumulate into one combined score. Agent wallets are recognized on-chain through an AgentIdentity NFT, so an autonomous agent gets its own cultural reputation that is pulled, verified, and ranked publicly. Live on Base mainnet with 16 verified profiles onboarded and 2,000+ NFTs tracked.", + "status": "live", + "topic": "agents", + "topics": ["agents", "commerce"], + "builder": { + "name": "airplanestar", + "url": "https://x.com/airplanestar_" + }, + "links": { + "repo": "https://github.com/airplanestar888/OG-Block", + "demo": "https://www.joinog.xyz/leaderboard", + "share": "https://x.com/ogblockchain/status/2092282854105547104?s=20", + "feedback": "https://github.com/airplanestar888/OG-Block/issues/new?title=Feedback%3A%20OG%20BLOCK", + "video": "https://x.com/ogblockchain/status/2092282854105547104?s=20" + }, + "primitives": ["wallet"], + "visual": { + "kind": "live app", + "eyebrow": "base + agent wallet", + "title": "on-chain culture score", + "videoLabel": "Watch the agent wallet demo on X", + "posterUrl": "https://joinog.xyz/opengraph-image" + }, + "skills": [ + { + "name": "og-block-agent-link", + "href": "https://github.com/Virtual-Protocol/acp-cli-demos/tree/main/showcase/og-block/skills/og-block-agent-link", + "sourcePath": "showcase/og-block/skills/og-block-agent-link", + "summary": "Register any ACP agent's own Base wallet into an OG BLOCK profile's agent slot using a one-time code, then read back the combined culture score and rank. Zero funding required — works with any ACP agent out of the box.", + "install": "cp -R showcase/og-block/skills/og-block-agent-link ~/.agents/skills/" + } + ], + "artifacts": [ + { + "label": "Live app — joinog.xyz", + "href": "https://www.joinog.xyz", + "kind": "demo" + }, + { + "label": "Public leaderboard (live scores)", + "href": "https://www.joinog.xyz/leaderboard", + "kind": "proof" + }, + { + "label": "Example verified profile card", + "href": "https://www.joinog.xyz/u/airplanestar_", + "kind": "proof" + }, + { + "label": "Public profile API (JSON)", + "href": "https://www.joinog.xyz/api/profile/airplanestar_", + "kind": "proof" + }, + { + "label": "OG Card NFT contract on Base mainnet (verified source)", + "href": "https://basescan.org/address/0x841b99c7957107a633b8b063498b142f7c6d9e67#code", + "kind": "proof" + }, + { + "label": "Agent wallet AgentIdentity #58870 on Base (on-chain proof)", + "href": "https://basescan.org/nft/0x8004a169fb4a3325136eb29fa0ceb6d2e539a432/58870", + "kind": "proof" + }, + { + "label": "Agent wallet on BaseScan (0x3282…8263)", + "href": "https://basescan.org/address/0x3282f5ae930f8be53695de152cf890b9385e8263", + "kind": "proof" + }, + { + "label": "Demo video (agent wallet link flow)", + "href": "https://x.com/ogblockchain/status/2092282854105547104?s=20", + "kind": "video" + }, + { + "label": "Redacted result report", + "href": "https://github.com/Virtual-Protocol/acp-cli-demos/blob/main/showcase/og-block/result-redacted.md", + "kind": "proof" + }, + { + "label": "Demo prompt", + "href": "https://github.com/Virtual-Protocol/acp-cli-demos/blob/main/showcase/og-block/prompt.md", + "kind": "prompt" + }, + { + "label": "Source repository", + "href": "https://github.com/airplanestar888/OG-Block", + "kind": "docs" + } + ], + "feedbackPrompts": [ + "Does the agent wallet verification flow feel trustworthy?", + "Is the scoring model fair for on-chain holdings?", + "Which EconomyOS primitive should OG BLOCK integrate next?" + ] +} diff --git a/showcase/og-block/skills/og-block-agent-link/SKILL.md b/showcase/og-block/skills/og-block-agent-link/SKILL.md new file mode 100644 index 0000000..554f490 --- /dev/null +++ b/showcase/og-block/skills/og-block-agent-link/SKILL.md @@ -0,0 +1,135 @@ +# OG BLOCK Agent Link — Register Your Wallet & Track Your Culture Score + +## When to Use + +- An operator hands you a one-time code (`OGB-XXXX-XXXX`) to join their OG BLOCK profile as its **agent wallet** +- You need your on-chain NFT holdings counted into an OG BLOCK combined culture score +- You need to read back a profile's public culture score, rank, or NFT breakdown after linking + +## When NOT to Use + +- The code was issued more than 15 minutes ago, or it already completed a link (request a fresh one) +- Someone asks you to sign with the *operator's personal wallet* — never do this; only your own agent wallet key +- You cannot control which key signs (e.g. a smart account whose internal operator key you cannot identify) — see Troubleshooting + +## Required Inputs + +- **ACP CLI** installed and configured (`acp configure`) +- **Active ACP agent** on **Base mainnet (chainId 8453)** with its own wallet: + ```bash + acp agent use --agent-id + acp wallet address # this exact address is what you will register + ``` +- **One-time code** from the profile owner (`OGB-XXXX-XXXX`, single-use, expires 15 minutes; a new code invalidates any previous unused one) + +## Critical Rule + +The signature must **recover (plain ECDSA ecrecover) to exactly the address you submit**. +If your setup is a smart account signed by an internal operator key, submit **that signer EOA +address** instead of the account address — in both the challenge line and the payload. + +## Step-by-Step Workflow + +### Step 1: Confirm Your Wallet + +```bash +acp agent use --agent-id +acp wallet address +``` + +Record this address — it must appear identically in the challenge line and the payload below. + +### Step 2: Sign the Exact Challenge + +Build the message with the CURRENT UTC time (±5 minutes of server time), replacing placeholders: + +```text +OG BLOCK agent link +Code: +Agent wallet: +Timestamp: +``` + +Sign it (EIP-191 `personal_sign`, UTF-8, every line kept intact): + +```bash +acp wallet sign-message --chain-id 8453 --message "" +``` + +Capture `signature` from the output. + +### Step 3: POST the Registration + +```bash +curl -X POST https://joinog.xyz/api/agent/link \ + -H "Content-Type: application/json" \ + -d '{ + "code": "", + "address": "", + "chainId": 8453, + "message": "", + "signature": "<0x_SIGNATURE>" + }' +``` + +Success response: + +```json +{ "ok": true, "handle": "", "agentWallet": "", "score": 1234 } +``` + +`score` is the freshly recalculated combined OG Score across the operator's human + agent slots. + +### Step 4: Read Back the Public Result (Optional) + +```bash +curl https://joinog.xyz/api/profile/ +``` + +Returns score, rank, NFT counts, and verified/unverified breakdown for the profile. + +## Error Handling + +| Error | Cause | Fix | +| --- | --- | --- | +| `Signature could not be verified` | Signature recovers to a different address than submitted | Submit the signer EOA address instead (see Critical Rule) | +| `Invalid, used, or expired code` | Code consumed, expired, or superseded | Ask the operator for a fresh code | +| `Signature expired or has an invalid timestamp` | Clock drift beyond ±5 minutes | Regenerate the Timestamp, re-sign | +| `Signed message does not match the required challenge` | Lines differ from the template | Keep each line exact; address string must be identical in message and payload | +| `This wallet is already registered as an agent for another profile` | One wallet = one profile | Use another agent wallet | + +A **failed attempt does not consume the code** — fix the cause and retry within the 15-minute expiry. + +## Approval Gates + +This flow performs a **production mutation** — it attaches a wallet to a profile's agent slot — so gate it: + +- The **one-time code from the operator is the consent/authorization**. Do not proceed without a code you received directly from the operator. +- **No spending, no posting, no account creation** happens in this flow. There is nothing to pay, mint, deploy, or publish — do not send funds anywhere. +- Confirm before acting: the submission `address` matches `acp wallet address`, and the operator's `handle` in the success response is the profile the code belongs to. +- If anything about the code's origin is unclear (e.g. it arrived unsolicited), STOP and ask the operator to confirm. + +## Stop Conditions & Handoff + +Stop immediately and report back (do not retry blindly) when: + +- `acp wallet address` outputs anything other than the wallet you intended to register. +- The code returns `Invalid, used, or expired code` — a new code is required; hand off to the operator. +- The signature cannot recover to the submitted address — hand off; re-issuing a message is fine but the code window is 15 minutes. +- The response is `This wallet is already registered as an agent for another profile` — use a different agent wallet. +- You are asked to sign with the operator's personal/main wallet — refuse. + +## Validation & Output Contract + +Successful completion means ALL of: + +1. `POST /api/agent/link` returns HTTP 200 and `{ "ok": true, "handle": "", "agentWallet": "", "score": }`. +2. `GET https://joinog.xyz/api/profile/` reflects the linked agent wallet and a fresh combined score. +3. `https://joinog.xyz/leaderboard` shows the profile at the returned rank. + +Report at minimum: the operator handle, your registered address, the returned score/rank, and the public profile URL. Treat a missing/invalid `handle` or a score that does not match the profile read-back as a failure. + +## Verification Notes + +- Only NFTs held on **BaseScan-verified contracts** count toward the score; spam and unverified contracts are excluded automatically. +- After linking, the combined score is recalculated across both wallet slots and published live at `https://joinog.xyz/leaderboard`.