Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Changelog

## 0.1.0

Initial release.

### Identity

- `registerAgent` — register as an ERC-8004 agent (mints agent NFT)
- `parseRegisterReceipt` — extract agentId from register transaction receipt
- `isRegistered` — check if an address is a registered agent
- `verifyAgentId` — verify that an agentId belongs to a claimed address
- `resolveAgent` — resolve agent by ID (owner, wallet, URI, ownerMismatch flag)
- `getAgentWallet` / `setAgentWallet` / `unsetAgentWallet` — wallet management
- `getMetadata` / `setMetadata` — on-chain key-value metadata
- `setAgentURI` — update agent URI

### Reputation

- `giveFeedback` — submit feedback for an agent
- `parseGiveFeedbackReceipt` — extract feedbackIndex from feedback transaction receipt
- `revokeFeedback` — revoke previously given feedback
- `appendResponse` — append a response to existing feedback
- `readFeedback` / `readAllFeedback` / `readAllFeedbackBatched` — read feedback entries
- `getSummary` — aggregated reputation summary
- `getClients` — all reviewer addresses for an agent
- `getLastIndex` — latest feedback index for an agent-client pair
- `getResponseCount` — count responses to a feedback entry

### Infrastructure

- Registry addresses for 7 chains (Ethereum, Base, Polygon, Arbitrum, Optimism, Base Sepolia, Ethereum Sepolia)
- Auto-resolve registry address from `client.chain`
- Sub-path exports: `/identity`, `/reputation`, `/abis`
124 changes: 124 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# @x402r/erc8004

TypeScript SDK for [ERC-8004](https://eips.ethereum.org/EIPS/eip-8004) Identity and Reputation registries. Pure [viem](https://viem.sh), zero additional dependencies.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems marking jargon. keep it technical


## Install

```bash
pnpm add @x402r/erc8004 viem
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If view is dep ? do we need to list view ? why not pnpm install or something

```

## Usage

### Register an agent

```ts
import { registerAgent, parseRegisterReceipt } from '@x402r/erc8004/identity'

const hash = await registerAgent(walletClient, {
agentURI: 'https://example.com/agent.json',
})

const receipt = await publicClient.waitForTransactionReceipt({ hash })
const { agentId } = parseRegisterReceipt(receipt)
```

### Verify identity

```ts
import { verifyAgentId, resolveAgent } from '@x402r/erc8004/identity'

const valid = await verifyAgentId(publicClient, {
agentId: 42n,
claimedAddress: '0x...',
})

const agent = await resolveAgent(publicClient, { agentId: 42n })
// { agentId, owner, agentWallet, agentURI, ownerMismatch }
```

### Give feedback

```ts
import { giveFeedback, getSummary } from '@x402r/erc8004/reputation'

await giveFeedback(walletClient, {
agentId: 42n,
value: 85n,
valueDecimals: 0,
tag1: 'service',
tag2: 'quality',
})

const summary = await getSummary(publicClient, {
agentId: 42n,
clientAddresses: ['0x...'],
tag1: 'service',
tag2: 'quality',
})
```

## API

### Identity

| Function | Description |
|---|---|
| `registerAgent` | Register as an ERC-8004 agent (mints NFT) |
| `parseRegisterReceipt` | Extract `agentId` from register tx receipt |
| `isRegistered` | Check if an address is registered |
| `verifyAgentId` | Verify agentId belongs to a claimed address |
| `resolveAgent` | Resolve agent by ID (owner, wallet, URI) |
| `getAgentWallet` | Get wallet address for an agent |
| `setAgentWallet` | Set verified payment wallet (EIP-712 sig) |
| `unsetAgentWallet` | Clear agent wallet |
| `getMetadata` | Read on-chain metadata by key |
| `setMetadata` | Write on-chain metadata |
| `setAgentURI` | Update agent URI |

### Reputation

| Function | Description |
|---|---|
| `giveFeedback` | Submit feedback for an agent |
| `parseGiveFeedbackReceipt` | Extract `feedbackIndex` from feedback tx receipt |
| `revokeFeedback` | Revoke previously given feedback |
| `appendResponse` | Append a response to feedback |
| `readFeedback` | Read a single feedback entry |
| `readAllFeedback` | Read all feedback (filtered by reviewers and tags) |
| `readAllFeedbackBatched` | Batched version — chunks `clientAddresses` to avoid RPC limits |
| `getSummary` | Aggregated reputation summary |
| `getClients` | All addresses that have given feedback |
| `getLastIndex` | Latest feedback index for an agent-client pair |
| `getResponseCount` | Count responses to a feedback entry |

## Chains

| Chain | ID | Network |
|---|---|---|
| Ethereum | 1 | Mainnet |
| Base | 8453 | Mainnet |
| Polygon | 137 | Mainnet |
| Arbitrum | 42161 | Mainnet |
| Optimism | 10 | Mainnet |
| Base Sepolia | 84532 | Testnet |
| Ethereum Sepolia | 11155111 | Testnet |

Registry addresses auto-resolve from `client.chain`. Pass `registryAddress` to override.

## Exports

| Path | Contents |
|---|---|
| `@x402r/erc8004` | Everything |
| `@x402r/erc8004/identity` | Identity registry functions and types |
| `@x402r/erc8004/reputation` | Reputation registry functions and types |
| `@x402r/erc8004/abis` | Raw contract ABIs |

## Stability

ERC-8004 is Draft status. The on-chain contracts are UUPS upgradeable. At 0.x, minor version bumps may contain breaking changes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to mention it ? Isn't this common knowledge


## License

[Apache-2.0](./LICENSE)
12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
{
"name": "@x402r/erc8004",
"version": "0.0.0",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe release alpha version first for testing with SDK, than can release actual stable one ?

"version": "0.1.0",
"description": "Lightweight TypeScript SDK for ERC-8004 (Trustless Agents) — Identity and Reputation registries",
"type": "module",
"license": "Apache-2.0",
"sideEffects": false,
"repository": {
"type": "git",
"url": "git+https://github.com/BackTrackCo/erc8004.git"
},
"homepage": "https://github.com/BackTrackCo/erc8004#readme",
"bugs": {
"url": "https://github.com/BackTrackCo/erc8004/issues"
},
"engines": {
"node": ">=22"
"node": ">=18"
},
"packageManager": "pnpm@10.23.0",
"files": [
Expand Down
6 changes: 6 additions & 0 deletions src/identity/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
export { getAgentWallet } from './getAgentWallet.js'
export { getMetadata } from './getMetadata.js'
export { isRegistered } from './isRegistered.js'
export type { RegisterResult } from './parseRegisterReceipt.js'
export { parseRegisterReceipt } from './parseRegisterReceipt.js'
export { registerAgent } from './register.js'
export { resolveAgent } from './resolveAgent.js'
export { setAgentURI } from './setAgentURI.js'
export { setAgentWallet } from './setAgentWallet.js'
export { setMetadata } from './setMetadata.js'
export type {
GetAgentWalletParameters,
Expand All @@ -13,7 +16,10 @@ export type {
ResolveAgentParameters,
ResolvedAgent,
SetAgentURIParameters,
SetAgentWalletParameters,
SetMetadataParameters,
UnsetAgentWalletParameters,
VerifyAgentIdParameters,
} from './types.js'
export { unsetAgentWallet } from './unsetAgentWallet.js'
export { verifyAgentId } from './verifyAgentId.js'
27 changes: 27 additions & 0 deletions src/identity/parseRegisterReceipt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { type Address, parseEventLogs, type TransactionReceipt } from 'viem'
import { identityRegistryAbi } from '../abis/index.js'

export interface RegisterResult {
agentId: bigint
owner: Address
agentURI: string
}

/**
* Extract the agentId, owner, and agentURI from a `registerAgent` transaction receipt.
* Parses the `Registered` event emitted by the Identity Registry.
*/
export function parseRegisterReceipt(
receipt: TransactionReceipt,
): RegisterResult {
const logs = parseEventLogs({
abi: identityRegistryAbi,
logs: receipt.logs,
eventName: 'Registered',
})
if (logs.length === 0) {
throw new Error('No Registered event found in receipt')
}
const { agentId, owner, agentURI } = logs[0].args
return { agentId, owner, agentURI }
}
15 changes: 13 additions & 2 deletions src/identity/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export async function registerAgent(
parameters.registryAddress,
)

if (metadata && metadata.length > 0) {
if (agentURI && metadata && metadata.length > 0) {
return walletClient.writeContract({
address: registry,
abi: identityRegistryAbi,
Expand All @@ -37,11 +37,22 @@ export async function registerAgent(
})
}

if (agentURI) {
return walletClient.writeContract({
address: registry,
abi: identityRegistryAbi,
functionName: 'register',
args: [agentURI],
chain: walletClient.chain,
account,
})
}

return walletClient.writeContract({
address: registry,
abi: identityRegistryAbi,
functionName: 'register',
args: [agentURI],
args: [],
chain: walletClient.chain,
account,
})
Expand Down
35 changes: 35 additions & 0 deletions src/identity/setAgentWallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { Hash, WalletClient } from 'viem'
import { identityRegistryAbi } from '../abis/index.js'
import { requireAccount } from '../internal/requireAccount.js'
import { resolveIdentityRegistry } from '../internal/resolveRegistryAddress.js'
import type { SetAgentWalletParameters } from './types.js'

/**
* Set the verified payment wallet for an agent.
* Requires an EIP-712 signature from `newWallet` proving consent.
* The wallet clears on NFT transfer — call this again after any transfer.
*/
export async function setAgentWallet(
walletClient: WalletClient,
parameters: SetAgentWalletParameters,
): Promise<Hash> {
const account = requireAccount(walletClient)
const registry = resolveIdentityRegistry(
walletClient,
parameters.registryAddress,
)

return walletClient.writeContract({
address: registry,
abi: identityRegistryAbi,
functionName: 'setAgentWallet',
args: [
parameters.agentId,
parameters.newWallet,
parameters.deadline,
parameters.signature,
],
chain: walletClient.chain,
account,
})
}
15 changes: 14 additions & 1 deletion src/identity/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Address, Hex } from 'viem'

export interface RegisterAgentParameters {
registryAddress?: Address
agentURI: string
agentURI?: string
metadata?: Array<{ key: string; value: Hex }>
}

Expand Down Expand Up @@ -53,3 +53,16 @@ export interface SetAgentURIParameters {
agentId: bigint
newURI: string
}

export interface SetAgentWalletParameters {
registryAddress?: Address
agentId: bigint
newWallet: Address
deadline: bigint
signature: Hex
}

export interface UnsetAgentWalletParameters {
registryAddress?: Address
agentId: bigint
}
29 changes: 29 additions & 0 deletions src/identity/unsetAgentWallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { Hash, WalletClient } from 'viem'
import { identityRegistryAbi } from '../abis/index.js'
import { requireAccount } from '../internal/requireAccount.js'
import { resolveIdentityRegistry } from '../internal/resolveRegistryAddress.js'
import type { UnsetAgentWalletParameters } from './types.js'

/**
* Clear the agent wallet, reverting to the NFT owner as the default.
* Only the agent owner or an approved operator can call this.
*/
export async function unsetAgentWallet(
walletClient: WalletClient,
parameters: UnsetAgentWalletParameters,
): Promise<Hash> {
const account = requireAccount(walletClient)
const registry = resolveIdentityRegistry(
walletClient,
parameters.registryAddress,
)

return walletClient.writeContract({
address: registry,
abi: identityRegistryAbi,
functionName: 'unsetAgentWallet',
args: [parameters.agentId],
chain: walletClient.chain,
account,
})
}
Loading
Loading