# ERC-8004 identity viewer

A static page that shows an AI agent's ERC-8004 identity (owner, tokenURI, registration file) and its reputation feedback, on Base and Base Sepolia. HTML, CSS and JavaScript only: no backend, no wallet, no dependency. The page calls the chain with `eth_call` through a public RPC.

Live demo: https://agentgate-builder.github.io/erc8004-identity-viewer/ (try https://agentgate-builder.github.io/erc8004-identity-viewer/?network=base&agent=1, or Base Sepolia agent 1, which has reputation feedback: https://agentgate-builder.github.io/erc8004-identity-viewer/?network=base-sepolia&agent=1).

Tests: `npm test` runs the offline A1 to A6 tests with a fake RPC (no network). `VIEWER_LIVE=1 npm test` adds one live read from Base.

## Use it

Open `index.html` from any static host (GitHub Pages works), or run `npm run serve` and open http://localhost:8080. Deep links: `?network=base&agent=1` or `?network=base-sepolia&agent=1`. The Advanced panel takes your own RPC URL and IPFS gateway.

## Library

`viewer.js` is an ES module that runs in the browser and in Node 20.

```js
import { loadAgent, httpRpc, httpFetchJson, REGISTRIES } from './viewer.js';

const cfg = REGISTRIES['base-sepolia'];
const agent = await loadAgent({
  agentId: 1,
  network: 'base-sepolia',
  identityRegistry: cfg.identity,
  reputationRegistry: cfg.reputation, // optional
  rpc: httpRpc(cfg.rpcUrl),           // rpc(method, params) -> Promise
  fetchJson: httpFetchJson(),         // fetchJson(url) -> Promise
});
// { status: 'ok' | 'empty' | 'error', agentId, owner, tokenURI, registration, feedback, error? }
```

- `loadAgent` never throws. `status` is `ok`, `empty` (ownerOf reverts or returns the zero address: no such agent) or `error` (the RPC or the file failed, with a plain message in `error`).
- `rpc` throws an Error carrying the JSON-RPC `code` and `message`. A revert is code 3 or a message with "revert".
- `ipfs://CID/path` is fetched through an https gateway (default `https://ipfs.io/ipfs/`, option `ipfsGateway`). `data:application/json` URIs, base64 or not, are decoded locally without a request.
- `registration` has `name`, `description`, `image`, `endpoints` (from `endpoints` or the newer `services` field), `supportedTrust` and `raw`.
- `feedback` is `{count, average, items: [{client, score, tags}]}`, read in one call with `readAllFeedback(agentId, [], "", "", false)`, so revoked entries are left out. `score` is `value / 10^valueDecimals`. When reputation cannot be read, the identity still shows and `feedback.error` says why.

## Registries (config.js)

| Network | Identity registry | Reputation registry |
|---|---|---|
| base (8453) | 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 | 0x8004BAa17C55a88189AE136b182e5fdA19dE9b63 |
| base-sepolia (84532) | 0x8004A818BFB912233c491871b3d84c89A494BD9e | 0x8004B663056A597Dffe9eCcC1965A193B7388713 |

Source: the ERC-8004 reference deployment, https://github.com/erc-8004/erc-8004-contracts (README, Contract Addresses), cross checked with the QuickNode ERC-8004 explorer contract list (https://erc-8004.quicknode.com/docs/contracts).

## Tests

`npm test` runs the offline suite with Node's built in runner. Each test is named after the acceptance item it proves (A1 to A6), and every test passes its own `rpc` and `fetchJson`. ABI fixtures in `test/fixtures.json` were produced with an independent encoder (ethers v6), so the decoder is checked against a second implementation.

`npm run test:live` also reads real agents on Base and Base Sepolia (set `KOGNAI_TEST_AGENT_ID` for the Kognai test identity).

## Notes

- Some registration hosts do not send CORS headers, so a browser cannot read them. The page then shows a clear error that names the host; Node is not affected.
- Everything the page shows is inserted as text, never as HTML. Images load only from https or data:image URIs, and links only from http(s).

MIT licence.
