How PRUEBA works
A technical-but-readable walkthrough of the pieces that make up PRUEBA, the data it produces, the public API, and how a community or developer can start using or contributing to it.
In one paragraph
PRUEBA is a thin layer that sits on top of conversations communities are already having. A small bot, added to a community's existing WhatsApp or Telegram group, listens for natural-language descriptions of what happened ("we had practice today, 28 girls, 90 minutes"). It confirms the details back in the same chat, in the community's own language. When three community members confirm, the bot writes a permanent, signed record to a public ledger. Anyone can later verify what was recorded, who confirmed it, and when, without depending on PRUEBA, the bot, or even the community itself still being around.
The trust model: community confirmation
The thing that makes PRUEBA different from typical web3 attestation tools is that community members never touch a wallet. The signing key is held by the bot. The trust comes from people, three community members typing "confirm" in the chat, not from cryptography on the human side. (We don't call this a "multisig": there's one signer, the bot; the multiple confirmations happen in the chat, not on-chain.)
Why this works:
- No crypto literacy required. A coach in Hargeisa doesn't need to install MetaMask, manage a seed phrase, or even know what a wallet is.
- No risk of one person faking records. The bot won't write anything to the chain until enough humans have confirmed. The threshold is configurable per community (default: 3).
- The bot can't forge records either. The metadata is stored on IPFS with a content-addressed CID, if you change one character, the CID changes. The bot signs that specific CID on-chain. Anyone can later fetch the metadata and confirm it matches the signed hash.
The cryptography is doing the boring permanence work; the trust is doing the meaningful "did this really happen?" work. That split is the whole point.
The five-step flow
- Describe: somebody types in the group: "Saturday practice, 22 girls, 2 hours."
- Confirm with the bot: the bot replies in the same language: "Got it, 22 girls, 2 hours, Saturday June 1st. Is that right?"
- Community confirmation: three other community members reply "confirm" (or π, or "yes", in their own language).
- Keep: the bot uploads the structured metadata to IPFS, then signs an EAS attestation on Base referencing that metadata's CID. The on-chain record now exists.
- Share: the bot replies with a verification link. Anyone can click it to see the record on the public dashboard, or look up the attestation on EAS Scan.
Each step takes seconds. The whole flow, from "Saturday practice" to "saved forever," takes about two minutes.
The architecture
WhatsApp / Telegram
β
βΌ
ββββββββββββββββββββββββββββββ
β Bot (sarreya-bot, etc.) β Multilingual chat agent.
β β media: Whisper (audio), β Transcribes voice notes,
β GPT-4o-mini (images) β describes images.
β β understanding: Anthropicβ
β β memory: SQLite β
ββββββββββββββββ¬ββββββββββββββ
β
βΌ structured JSON
ββββββββββββββββββββββββββββββ
β IPFS (via Pinata) β Metadata pinned to IPFS;
β β activity-v1 / governanceβ returns a content-addressed
β β JSON β CID (e.g. QmecVv4Gβ¦).
ββββββββββββββββ¬ββββββββββββββ
β
βΌ keccak256(CID) β bytes32
ββββββββββββββββββββββββββββββ
β EAS on Base mainnet β Bot wallet signs an attestation
β β Schema A: Activity β referencing the metadata.
β β Schema B: Governance β ~$0.01 per attestation in gas.
ββββββββββββββββ¬ββββββββββββββ
β
βΌ EAS event
ββββββββββββββββββββββββββββββ
β Indexer β Subscribes to EAS events on
β β SQLite database β Base; pulls back metadata
β β REST API at β from IPFS; serves data via
β api.pruebaprotocol.org β HTTP for downstream use.
ββββββββββββββββ¬ββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββ
β Dashboard β Public web UI at
β β pruebaprotocol.org β pruebaprotocol.org.
β β per-community pages β Anyone can browse records,
β β per-attestation pages β verify on-chain.
ββββββββββββββββββββββββββββββ
The pieces in detail
Bot. Currently runs on OpenClaw (a community chat-agent framework), in a Docker container, with a separate router that handles Whapi webhooks and pre-processes media. Multilingual via Whisper for voice notes + GPT-4o-mini for image descriptions. The agent itself replies in whatever language the user wrote in. Roadmap: migrating to a Cloudflare Workers + Flue runtime for edge-native deployment.
IPFS via Pinata. Every record's rich data (participant count, photos, summary, date, location) lives in IPFS, addressed by content hash. Pinata pins the data so it stays retrievable. Anyone can fetch a record from any IPFS gateway given the CID, Pinata is not a dependency for reading, only for ensuring the data sticks around.
Bot wallet. A single Ethereum-style wallet at address 0xc2568e680076eb5c9B488f65Cb5076048E5E0805 on Base. The bot uses this to sign attestations. Future: per-community signing keys for stronger separation, and possibly EAS delegation.
EAS schemas on Base. Two prototype schemas, both deployed on Base mainnet. See the next section for the on-chain layout.
Indexer. A small Node service that subscribes to EAS events on Base for our two schema UIDs. When a new attestation appears, it pulls the referenced metadata from IPFS, parses it, and writes both the on-chain attestation and the off-chain metadata to a local SQLite database. Serves the API at api.pruebaprotocol.org.
Dashboard. A Next.js app (this site) that calls the indexer's API to render per-community pages, per-record pages, and a "see what's been recorded" overview.
The data model
Activity attestation
A community session, a training, a tournament, a workshop, a meeting that happened.
On-chain (EAS schema A):
bytes32 entityId // community identifier (e.g. keccak("Sarreya Sport"))
bytes32 activityRef // keccak256(IPFS CID), points at the metadata
uint64 timestamp // unix seconds, when the session occurred
address attestedBy // bot wallet address (currently shared across communities)
Schema UID 0x2fc2d7β¦fdc2e on EAS Scan
Off-chain (IPFS, prueba-activity-v1):
{
"schema": "prueba-activity-v1",
"community": "Sarreya Sport",
"date": "2026-05-15",
"type": "workshop",
"facilityName": "Community sports hall",
"participantCount": 29,
"durationMinutes": 420,
"summary": "29 girls and young women joined a one-day workshop in Hargeisaβ¦",
"recordedAt": "2026-05-15T14:21:33.891Z",
"photos": ["QmQTeJβ¦", "QmeLqβ¦"],
"confirmedBy": ["Asma", "Fatima", "Hodan"]
}
Governance attestation
A community decision, voting on a venue change, allocating funds, agreeing on a rule.
On-chain (EAS schema B):
bytes32 entityId // same community identifier as above
bytes32 proposalRef // keccak256(IPFS CID), points at governance metadata
uint64 timestamp // unix seconds
address attestedBy // bot wallet address
Schema UID 0xc6f1d7β¦b152e on EAS Scan
Off-chain (IPFS, prueba-governance-v1):
{
"schema": "prueba-governance-v1",
"community": "Sarreya Sport",
"proposalText": "Move Saturday practice to 4pm for the next month",
"decisionProcess": "consensus",
"outcome": "approved",
"participantCount": 12,
"recordedAt": "2026-05-20T11:14:02.500Z",
"confirmedBy": ["Asma", "Savannah", "Hodan", "Fatima"]
}
Governance captures the decision process (consensus, vote, elder, coordinator), not just the outcome. PRUEBA doesn't assume Western voting models.
Public API
The indexer exposes a small REST API at https://api.pruebaprotocol.org. CORS is open. No auth. JSON only. All endpoints follow { ok: true, data: {...} } or { ok: false, error: "..." }.
GET /api/health
Liveness probe.
{
"ok": true,
"data": {
"status": "ok",
"last_block": 46898270,
"schemas_configured": { "activity": true, "governance": true },
"uptime_seconds": 1648572
}
}
GET /api/communities
All communities with at least one attestation.
{
"ok": true,
"data": [
{
"entity_id": "Sarreya Sport",
"name": "Sarreya Sport",
"description": null,
"created_at": 1775546240,
"total_sessions": 11,
"total_decisions": 0,
"total_participants": 98
}
]
}
GET /api/communities/:entityId
Detail for one community. URL-encode the entity ID.
GET /api/communities/:entityId/stats
Aggregate counts for a community.
{
"ok": true,
"data": {
"entity_id": "Sarreya Sport",
"name": "Sarreya Sport",
"total_sessions": 11,
"total_decisions": 0,
"total_participants": 98,
"first_attestation": 1775546240
}
}
GET /api/communities/:entityId/sessions
Activity attestations for a community. Supports ?page=1&limit=100 paging.
Each item:
{
"uid": "0x8b6409b3eff193β¦",
"schema_type": "activity",
"entity_id": "Sarreya Sport",
"ref_cid": "QmecVv4Gβ¦",
"timestamp": 1778854894,
"attested_by": "0xc2568e6800β¦",
"tx_hash": "0x7284f0b51β¦",
"block_number": 46032775,
"metadata": { "...prueba-activity-v1..." }
}
GET /api/communities/:entityId/decisions
Governance attestations for a community.
GET /api/attestations/:uid
Lookup a single attestation by EAS UID. Returns the same shape as the sessions/decisions items.
For communities: how to get started
If your community does meaningful work and you want to keep verifiable proof of it:
- Reach out. Use the contact form or email
1heenal@gmail.com. Tell us what your community is, where you operate, what kinds of things you'd want to record (training, decisions, milestones, attendance). - A short discovery call. We figure out together: what gets recorded, how often, who confirms, in what language(s). Each community is different, we adapt the bot's behaviour to how you already work.
- The bot joins your group. Either we add the bot to your existing WhatsApp/Telegram group, or we help you set up a fresh group. The bot's identity is local to your community.
- First few sessions are hand-held. We sit with you (asynchronously, in chat) through the first handful of records, confirming you like how it reads back, that the language flows naturally, that the photos pin correctly.
- You're running. From here on, recording is just "type what happened, confirm." The dashboard updates automatically.
There's no fee. PRUEBA is an open-source protocol. We're onboarding pilot communities slowly (no more than a couple at a time right now) so we can learn alongside each one.
For developers: how to get started
PRUEBA is open source. github.com/explorience/prueba-protocol
The repo has three main parts:
lib/: the protocol layer:eas-prueba.ts(writes attestations on Base) andipfs-prueba.ts(pins metadata to Pinata via JWT). These are the reusable building blocks.indexer/: Node + Express + SQLite. Subscribes to EAS events on Base, fetches metadata from IPFS, exposes the REST API documented above.frontend/: Next.js dashboard (this site). Reads the indexer's API.schemas/: JSON-schema definitions forprueba-activity-v1andprueba-governance-v1(the off-chain metadata format).
To run locally:
git clone https://github.com/explorience/prueba-protocol
cd prueba-protocol
# Install both packages
npm install
cd indexer && npm install
cd ../frontend && npm install
# Configure: copy indexer/.env.example β indexer/.env and fill in
# BASE_RPC_URL, ACTIVITY_SCHEMA_UID, GOVERNANCE_SCHEMA_UID, PINATA_JWT
# Run the indexer (it backfills from genesis block, then watches live)
cd indexer && npm run dev
# In another terminal: run the frontend
cd frontend && NEXT_PUBLIC_API_URL=http://localhost:3300 npm run dev
The bot itself isn't in this repo yet, it's a separate concern (currently OpenClaw, migrating to Flue). The protocol layer (lib/) can be used by any bot or service that wants to write PRUEBA-shaped attestations.
Contributing:
- Schemas are versioned. If you want to propose a v2 schema (with new fields), open an issue. We'd prefer additive changes over breaking ones; the indexer can carry multiple schema versions in parallel.
- Translations. The bot speaks Somali, English, and Spanish today. Adding a language is mostly model-prompting work, not code. If your community needs another language, get in touch.
- Resolver contracts. The current schemas have no on-chain validation, anyone could in principle submit a malformed attestation under the same schema UID. We're considering EAS resolver contracts to enforce minimum participant counts, valid
entityIdformats, etc. Design input welcome.
How to verify a record (anyone, anywhere)
You don't need to trust this site. You don't need to trust PRUEBA. You don't need to trust the community. Every record can be checked independently:
- Find the attestation UID (any record on the dashboard has one, it's the
uidfield, starts with0x...). - Look it up on EAS Scan:
https://base.easscan.org/attestation/view/<uid>, confirms the attestation exists on Base, signed by the bot wallet, at a specific block. - Fetch the metadata directly from IPFS: the on-chain record carries
activityRef = keccak256(CID). Get the CID from the indexer (ref_cidfield), then fetch from any IPFS gateway:https://ipfs.io/ipfs/<CID>orhttps://gateway.pinata.cloud/ipfs/<CID>. - Hash the metadata yourself with
keccak256and confirm it matches the on-chainactivityRef. If it does, the metadata you just fetched is exactly what was signed.
If the indexer, this dashboard, and Pinata all disappeared tomorrow, every record would still be verifiable using Base + any IPFS node.
Multilingual support
The bot today handles three languages reliably: Somali, English, Spanish. Behind the scenes:
- Voice notes: downloaded from the chat platform, sent to OpenAI Whisper for transcription, then routed to the bot as text. Whisper handles ~100 languages.
- Images / photos: sent to GPT-4o-mini's vision endpoint for a short description. The description gets passed to the bot as if a human had typed it.
- Text messages: sent to the bot agent directly. The bot's system prompt instructs it to reply in the user's language. Translation happens at the LLM level (currently Anthropic Claude), not via a separate translation service.
Adding a language is a configuration change, not a code change. If your community needs another, tell us.
What PRUEBA explicitly does NOT do
- Does not store private chat messages. Only signals the community chose to record become PRUEBA records.
- Does not give the bot read-access to anything outside its own chats. The bot can't see other communities' data.
- Does not require community members to have wallets, install apps, or know what blockchain is.
- Does not make decisions for the community. It captures decisions the community made; it never proposes or vetoes.
- Does not custody money. PRUEBA is an attestation protocol, not a payment processor. Communities can layer payment systems on top, but PRUEBA itself doesn't move funds.
- Does not lock a community in. All metadata is on IPFS (open standard), all attestations are on Base (public chain). A community can walk away with their entire record at any time, with zero permission from anyone.
Privacy & data
| Data | Where it lives | Who can read it |
|---|---|---|
| Community group chat (raw messages) | On WhatsApp/Telegram, with the chat provider | Group members only |
| Signals the community chose to record | IPFS (public) + Base (public) | Anyone, forever |
| The bot's working memory of past chats | SQLite on the host running the bot | Whoever runs the bot (currently AIFS / SuperBenefit) |
| Bot's signing key | Held server-side; the community never has it | Server operator only |
The deliberate split: personal chat content is private; signals the community wanted recorded are public. The community is in control of which is which.
Roadmap snapshot
Short version.
- Q3 2026: Richer dashboard analytics (cumulative participant-hours, decision-impact tracking). Resolver contracts on Base to enforce schema validity on-chain. First version of the Confetti extension that reads PRUEBA attestation history for participatory funding.
- Q4 2026: Onboard a second pilot community. Pilot a Confetti contest using PRUEBA data. Deeper poidh collaboration for casual proof-of-action submissions.
- Beyond: per-community signing keys (eliminate the shared bot wallet), EAS delegation patterns, Hypercerts aggregation for impact claims, integration with NEAR-based IronClaw agents.
FAQ
Q: What if Base mainnet shuts down? A: Attestations are also referenceable via IPFS metadata. We can mirror onto Ethereum mainnet, Optimism, or any other chain at any time, the schema is portable. The records themselves never disappear.
Q: What if Pinata stops pinning? A: The IPFS CIDs work with any IPFS gateway. We can re-pin to another provider (Filecoin, Web3.Storage, etc.) without changing any on-chain data.
Q: Can a community withdraw their data? A: The records are public and permanent, they can't be deleted (that's the whole point of "saved forever"). What a community can do is stop adding new records, and request that we mark their community as inactive in the indexer.
Q: What's the gas cost? A: ~$0.01 per attestation at current Base gas prices. The bot wallet pays it. Communities don't see or care about this.
Q: How do you handle abusive or false records? A: Records that go on-chain have already been confirmed by 3+ community members. If a community later wants to flag a record as disputed, we add a follow-up "dispute" attestation that references the original, the original stays in place (permanence) but the dispute is visible alongside it. This is more honest than silent deletion.
Q: What if the confirmations are gamed (3 colluding members)? A: Then the record is wrong, but it's attributably wrong, the three confirmers' names are in the metadata. Downstream verifiers (funders, partners) can choose to weight records by which community members confirmed them. The protocol doesn't fix this; community accountability does.
Q: Why Base, why EAS, why IPFS? A: Base for low gas + Coinbase trust signal. EAS because it's the standard attestation primitive on Ethereum + L2s and there's already broad tooling. IPFS because we want metadata portability + content addressing, and Pinata is reliable + has a generous free tier.
Get in touch
- Add your community: /contact or
1heenal@gmail.com - Technical questions: open an issue on GitHub
- AIFS Consortium: allinforsport.org Β· Blog
- SuperBenefit: superbenefit.org