diff --git a/README.md b/README.md
index 89ae4be..a23e51e 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@
-
+
@@ -235,7 +235,8 @@ Each agent has an A2A Agent Card describing its capabilities:
],
"capabilities": { "streaming": false, "pushNotifications": false },
"defaultInputModes": ["text/plain"],
- "defaultOutputModes": ["text/plain"]
+ "defaultOutputModes": ["text/plain"],
+ "fundingAddress": "0x742d...8f4a"
}
```
@@ -449,7 +450,7 @@ The protocol version is defined in a single place:
```typescript
// protocol/src/types.ts
-export const REEF_VERSION = "0.2.17";
+export const REEF_VERSION = "0.2.18";
export const A2A_PROTOCOL_VERSION = "0.3.0";
```
diff --git a/client/package.json b/client/package.json
index bc2d0b9..fb8ee02 100644
--- a/client/package.json
+++ b/client/package.json
@@ -1,6 +1,6 @@
{
"name": "@reef-protocol/client",
- "version": "0.2.17",
+ "version": "0.2.18",
"description": "Reef Protocol client — daemon, CLI, and identity management",
"type": "module",
"main": "dist/daemon.js",
diff --git a/directory/package.json b/directory/package.json
index 8ca046d..b9013bc 100644
--- a/directory/package.json
+++ b/directory/package.json
@@ -1,7 +1,7 @@
{
"name": "@reef-protocol/directory",
"private": true,
- "version": "0.2.17",
+ "version": "0.2.18",
"description": "Reef Protocol directory server — agent discovery and network stats",
"type": "module",
"main": "dist/index.js",
diff --git a/directory/src/migrations/00011_add-funding-address.ts b/directory/src/migrations/00011_add-funding-address.ts
new file mode 100644
index 0000000..2d45907
--- /dev/null
+++ b/directory/src/migrations/00011_add-funding-address.ts
@@ -0,0 +1,16 @@
+import { DataTypes, type Sequelize } from "sequelize";
+
+export async function up({ context: sequelize }: { context: Sequelize }) {
+ const qi = sequelize.getQueryInterface();
+
+ await qi.addColumn("agents", "funding_address", {
+ type: DataTypes.STRING(42),
+ allowNull: true,
+ defaultValue: null,
+ });
+}
+
+export async function down({ context: sequelize }: { context: Sequelize }) {
+ const qi = sequelize.getQueryInterface();
+ await qi.removeColumn("agents", "funding_address");
+}
diff --git a/directory/src/models/Agent.ts b/directory/src/models/Agent.ts
index 24dd4cd..6af9ec6 100644
--- a/directory/src/models/Agent.ts
+++ b/directory/src/models/Agent.ts
@@ -20,6 +20,7 @@ export interface AgentAttributes {
reputation_updated_at: Date | null;
country: string | null;
icon_url: string | null;
+ funding_address: string | null;
}
export class Agent extends Model {
@@ -41,6 +42,7 @@ export class Agent extends Model {
declare reputation_updated_at: Date | null;
declare country: string | null;
declare icon_url: string | null;
+ declare funding_address: string | null;
declare readonly created_at: Date;
declare readonly updated_at: Date;
}
@@ -133,6 +135,11 @@ export function initAgentModel(sequelize: Sequelize): void {
allowNull: true,
defaultValue: null,
},
+ funding_address: {
+ type: DataTypes.STRING(42),
+ allowNull: true,
+ defaultValue: null,
+ },
},
{
sequelize,
diff --git a/directory/src/routes/agents.ts b/directory/src/routes/agents.ts
index 29fced3..55e35d5 100644
--- a/directory/src/routes/agents.ts
+++ b/directory/src/routes/agents.ts
@@ -56,6 +56,8 @@ agentsRouter.post("/register", registrationLimiter, async (req, res, next) => {
const skillTags = agentCard.skills.flatMap((s) => s.tags);
const iconUrl = (agentCard as unknown as Record)
.iconUrl as string | undefined;
+ const fundingAddress = (agentCard as unknown as Record)
+ .fundingAddress as string | undefined;
let agent = await Agent.findByPk(addr);
@@ -70,6 +72,7 @@ agentsRouter.post("/register", registrationLimiter, async (req, res, next) => {
last_heartbeat: new Date(),
agent_card: agentCard,
icon_url: iconUrl || agent.icon_url,
+ funding_address: fundingAddress || agent.funding_address,
});
} else {
agent = await Agent.create({
@@ -90,6 +93,7 @@ agentsRouter.post("/register", registrationLimiter, async (req, res, next) => {
app_interactions: {},
reputation_updated_at: null,
icon_url: iconUrl || null,
+ funding_address: fundingAddress || null,
});
}
@@ -152,6 +156,7 @@ agentsRouter.get("/search", searchLimiter, async (req, res, next) => {
availability: a.availability,
agentCard: a.agent_card,
iconUrl: a.icon_url ?? null,
+ fundingAddress: a.funding_address ?? null,
registeredAt: a.created_at?.toISOString(),
lastHeartbeat: a.last_heartbeat?.toISOString(),
reputationScore: a.reputation_score,
@@ -378,6 +383,7 @@ agentsRouter.get("/:address", readLimiter, async (req, res, next) => {
tasksFailed: agent.tasks_failed,
totalInteractions: agent.total_interactions,
country: agent.country ?? null,
+ fundingAddress: agent.funding_address ?? null,
});
} catch (err) {
next(err);
diff --git a/package.json b/package.json
index d2612d3..30e9b55 100644
--- a/package.json
+++ b/package.json
@@ -32,5 +32,5 @@
"typescript-eslint": "^8.56.0",
"vitest": "^3.0.0"
},
- "version": "0.2.17"
+ "version": "0.2.18"
}
diff --git a/protocol/package.json b/protocol/package.json
index de5d73d..789654c 100644
--- a/protocol/package.json
+++ b/protocol/package.json
@@ -1,6 +1,6 @@
{
"name": "@reef-protocol/protocol",
- "version": "0.2.17",
+ "version": "0.2.18",
"description": "Shared message types, envelope codec, and validation for Reef Protocol",
"type": "module",
"main": "dist/index.js",
diff --git a/protocol/src/builders.ts b/protocol/src/builders.ts
index 8e3e42a..04f6c1d 100644
--- a/protocol/src/builders.ts
+++ b/protocol/src/builders.ts
@@ -84,7 +84,7 @@ export function buildReefAgentCard(
name: string,
description: string,
skills: AgentSkill[],
- options?: { iconUrl?: string },
+ options?: { iconUrl?: string; fundingAddress?: string },
): AgentCard {
const card: AgentCard = {
name,
@@ -105,6 +105,10 @@ export function buildReefAgentCard(
if (options?.iconUrl) {
(card as unknown as Record).iconUrl = options.iconUrl;
}
+ if (options?.fundingAddress) {
+ (card as unknown as Record).fundingAddress =
+ options.fundingAddress;
+ }
return card;
}
diff --git a/protocol/src/types.ts b/protocol/src/types.ts
index 020b4ca..a1fb0e6 100644
--- a/protocol/src/types.ts
+++ b/protocol/src/types.ts
@@ -2,7 +2,7 @@
import type { AgentCard } from "@a2a-js/sdk";
-export const REEF_VERSION = "0.2.17";
+export const REEF_VERSION = "0.2.18";
export const A2A_PROTOCOL_VERSION = "0.3.0";
export const DEFAULT_DIRECTORY_URL =
"https://reef-protocol-production.up.railway.app";
@@ -104,6 +104,8 @@ export interface AgentSearchResult {
agentCard: AgentCard | null;
/** URL to an icon/avatar image for this agent */
iconUrl?: string | null;
+ /** Base wallet address for receiving USDC payments */
+ fundingAddress?: string | null;
registeredAt?: string;
lastHeartbeat?: string;
reputationScore?: number;
diff --git a/protocol/src/validation.ts b/protocol/src/validation.ts
index b03eab4..f4aeb0e 100644
--- a/protocol/src/validation.ts
+++ b/protocol/src/validation.ts
@@ -116,6 +116,7 @@ export const agentCardSchema = z.object({
defaultOutputModes: z.array(z.string()),
preferredTransport: z.string().optional(),
iconUrl: z.string().url().optional(),
+ fundingAddress: z.string().optional(),
provider: z
.object({
organization: z.string(),