@q00bs/agent-sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Q00bsAgent.d.ts +331 -0
- package/dist/Q00bsAgent.d.ts.map +1 -0
- package/dist/Q00bsAgent.js +695 -0
- package/dist/Q00bsAgent.js.map +1 -0
- package/dist/abis/AgentEscrow.d.ts +336 -0
- package/dist/abis/AgentEscrow.d.ts.map +1 -0
- package/dist/abis/AgentEscrow.js +206 -0
- package/dist/abis/AgentEscrow.js.map +1 -0
- package/dist/abis/AgentRegistry.d.ts +496 -0
- package/dist/abis/AgentRegistry.d.ts.map +1 -0
- package/dist/abis/AgentRegistry.js +280 -0
- package/dist/abis/AgentRegistry.js.map +1 -0
- package/dist/abis/ConsensusModule.d.ts +270 -0
- package/dist/abis/ConsensusModule.d.ts.map +1 -0
- package/dist/abis/ConsensusModule.js +157 -0
- package/dist/abis/ConsensusModule.js.map +1 -0
- package/dist/abis/ERC8004Identity.d.ts +293 -0
- package/dist/abis/ERC8004Identity.d.ts.map +1 -0
- package/dist/abis/ERC8004Identity.js +223 -0
- package/dist/abis/ERC8004Identity.js.map +1 -0
- package/dist/abis/ERC8004Reputation.d.ts +362 -0
- package/dist/abis/ERC8004Reputation.d.ts.map +1 -0
- package/dist/abis/ERC8004Reputation.js +229 -0
- package/dist/abis/ERC8004Reputation.js.map +1 -0
- package/dist/abis/ERC8004Validation.d.ts +234 -0
- package/dist/abis/ERC8004Validation.d.ts.map +1 -0
- package/dist/abis/ERC8004Validation.js +162 -0
- package/dist/abis/ERC8004Validation.js.map +1 -0
- package/dist/abis/Q00bFactory.d.ts +123 -0
- package/dist/abis/Q00bFactory.d.ts.map +1 -0
- package/dist/abis/Q00bFactory.js +65 -0
- package/dist/abis/Q00bFactory.js.map +1 -0
- package/dist/abis/TheQ00bs.d.ts +119 -0
- package/dist/abis/TheQ00bs.d.ts.map +1 -0
- package/dist/abis/TheQ00bs.js +73 -0
- package/dist/abis/TheQ00bs.js.map +1 -0
- package/dist/abis/index.d.ts +9 -0
- package/dist/abis/index.d.ts.map +1 -0
- package/dist/abis/index.js +17 -0
- package/dist/abis/index.js.map +1 -0
- package/dist/client.d.ts +111 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +134 -0
- package/dist/client.js.map +1 -0
- package/dist/consensus.d.ts +85 -0
- package/dist/consensus.d.ts.map +1 -0
- package/dist/consensus.js +227 -0
- package/dist/consensus.js.map +1 -0
- package/dist/constants.d.ts +85 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +113 -0
- package/dist/constants.js.map +1 -0
- package/dist/discovery.d.ts +70 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +214 -0
- package/dist/discovery.js.map +1 -0
- package/dist/erc8004.d.ts +311 -0
- package/dist/erc8004.d.ts.map +1 -0
- package/dist/erc8004.js +824 -0
- package/dist/erc8004.js.map +1 -0
- package/dist/errors.d.ts +107 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +210 -0
- package/dist/errors.js.map +1 -0
- package/dist/escrow.d.ts +86 -0
- package/dist/escrow.d.ts.map +1 -0
- package/dist/escrow.js +267 -0
- package/dist/escrow.js.map +1 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +118 -0
- package/dist/index.js.map +1 -0
- package/dist/privy.d.ts +197 -0
- package/dist/privy.d.ts.map +1 -0
- package/dist/privy.js +524 -0
- package/dist/privy.js.map +1 -0
- package/dist/trust.d.ts +49 -0
- package/dist/trust.d.ts.map +1 -0
- package/dist/trust.js +117 -0
- package/dist/trust.js.map +1 -0
- package/dist/types.d.ts +472 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +36 -0
- package/dist/types.js.map +1 -0
- package/package.json +30 -0
|
@@ -0,0 +1,695 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @q00bs/agent-sdk — Q00bsAgent (Main Entry Point)
|
|
4
|
+
*
|
|
5
|
+
* This is the primary class developers interact with. It wraps all SDK
|
|
6
|
+
* modules (trust, escrow, consensus, discovery) behind a clean interface.
|
|
7
|
+
*
|
|
8
|
+
* WHAT THIS CLASS DOES:
|
|
9
|
+
* - Initializes blockchain clients from a private key (Mode 1) OR Privy (Mode 2).
|
|
10
|
+
* - Registers the agent on-chain as an ERC-721 on the owner's q00b.
|
|
11
|
+
* - Provides methods for trust verification, agent discovery, payments, and consensus.
|
|
12
|
+
* - Enforces spend limits and trust-path checks BEFORE sending transactions.
|
|
13
|
+
*
|
|
14
|
+
* TWO WALLET MODES:
|
|
15
|
+
*
|
|
16
|
+
* MODE 1 — Raw Private Key (legacy):
|
|
17
|
+
* Pass `privateKey` in config. The SDK creates viem clients locally.
|
|
18
|
+
*
|
|
19
|
+
* MODE 2 — Privy Server Wallet (recommended for ClawBot / OpenClaw agents):
|
|
20
|
+
* Pass `privy` in config (appId + appSecret). The SDK creates a Privy-managed
|
|
21
|
+
* wallet with spending policies. No private keys in your code.
|
|
22
|
+
* See: https://privy.io/blog/securely-equipping-openclaw-agents-with-privy-wallets
|
|
23
|
+
*
|
|
24
|
+
* SECURITY GUARANTEES:
|
|
25
|
+
* - In Mode 1: Private keys are used by viem locally and never leave the process.
|
|
26
|
+
* - In Mode 2: Private keys are held by Privy's HSM and NEVER appear in your code.
|
|
27
|
+
* - All state-changing operations go through on-chain contracts.
|
|
28
|
+
* - Spend limits are enforced at 3 layers: Privy policy → SDK pre-check → on-chain.
|
|
29
|
+
* - Trust paths are verified on-chain through the q00b graph before communication.
|
|
30
|
+
*
|
|
31
|
+
* USAGE (Mode 1 — raw key):
|
|
32
|
+
* ```ts
|
|
33
|
+
* const agent = new Q00bsAgent({
|
|
34
|
+
* privateKey: process.env.AGENT_PRIVATE_KEY!,
|
|
35
|
+
* rpcUrl: process.env.BASE_RPC_URL!,
|
|
36
|
+
* registryAddress: '0x...',
|
|
37
|
+
* });
|
|
38
|
+
* await agent.initialize();
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* USAGE (Mode 2 — Privy, recommended):
|
|
42
|
+
* ```ts
|
|
43
|
+
* const agent = new Q00bsAgent({
|
|
44
|
+
* privy: {
|
|
45
|
+
* appId: process.env.PRIVY_APP_ID!,
|
|
46
|
+
* appSecret: process.env.PRIVY_APP_SECRET!,
|
|
47
|
+
* walletId: process.env.PRIVY_WALLET_ID, // optional, creates new if omitted
|
|
48
|
+
* },
|
|
49
|
+
* rpcUrl: process.env.BASE_RPC_URL!,
|
|
50
|
+
* registryAddress: '0x...',
|
|
51
|
+
* });
|
|
52
|
+
* await agent.initialize();
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
56
|
+
exports.Q00bsAgent = void 0;
|
|
57
|
+
const viem_1 = require("viem");
|
|
58
|
+
const client_1 = require("./client");
|
|
59
|
+
const trust_1 = require("./trust");
|
|
60
|
+
const escrow_1 = require("./escrow");
|
|
61
|
+
const consensus_1 = require("./consensus");
|
|
62
|
+
const discovery_1 = require("./discovery");
|
|
63
|
+
const privy_1 = require("./privy");
|
|
64
|
+
const erc8004_1 = require("./erc8004");
|
|
65
|
+
const AgentRegistry_1 = require("./abis/AgentRegistry");
|
|
66
|
+
const errors_1 = require("./errors");
|
|
67
|
+
// ─────────────────────────────────────────────────────────────
|
|
68
|
+
// Q00BS AGENT
|
|
69
|
+
// ─────────────────────────────────────────────────────────────
|
|
70
|
+
class Q00bsAgent {
|
|
71
|
+
// ── Configuration ───────────────────────────────────────────
|
|
72
|
+
config;
|
|
73
|
+
logger;
|
|
74
|
+
// ── Blockchain clients ──────────────────────────────────────
|
|
75
|
+
publicClient;
|
|
76
|
+
walletClient;
|
|
77
|
+
walletAddress;
|
|
78
|
+
// ── Privy wallet (Mode 2) ──────────────────────────────────
|
|
79
|
+
privyManager;
|
|
80
|
+
_walletMode = 'privateKey';
|
|
81
|
+
// ── Sub-modules ─────────────────────────────────────────────
|
|
82
|
+
trustResolver;
|
|
83
|
+
escrowManager;
|
|
84
|
+
consensusManager;
|
|
85
|
+
agentDiscovery;
|
|
86
|
+
_erc8004Manager;
|
|
87
|
+
// ── State ───────────────────────────────────────────────────
|
|
88
|
+
_agentId;
|
|
89
|
+
_initialized = false;
|
|
90
|
+
/** The agent's on-chain ID (set after register() or from config). */
|
|
91
|
+
get agentId() {
|
|
92
|
+
return this._agentId;
|
|
93
|
+
}
|
|
94
|
+
/** Whether initialize() has been called. */
|
|
95
|
+
get initialized() {
|
|
96
|
+
return this._initialized;
|
|
97
|
+
}
|
|
98
|
+
/** The agent's wallet address (derived from private key or Privy). */
|
|
99
|
+
get address() {
|
|
100
|
+
return this.walletAddress;
|
|
101
|
+
}
|
|
102
|
+
/** Which wallet mode is active: 'privateKey' (Mode 1) or 'privy' (Mode 2). */
|
|
103
|
+
get walletMode() {
|
|
104
|
+
return this._walletMode;
|
|
105
|
+
}
|
|
106
|
+
/** Whether this agent uses a Privy-managed wallet (Mode 2). */
|
|
107
|
+
get isPrivyMode() {
|
|
108
|
+
return this._walletMode === 'privy';
|
|
109
|
+
}
|
|
110
|
+
/** The Privy wallet manager (only available in Mode 2). */
|
|
111
|
+
get privyWallet() {
|
|
112
|
+
return this.privyManager;
|
|
113
|
+
}
|
|
114
|
+
/** The ERC-8004 manager (available if erc8004 config is set or after initialize). */
|
|
115
|
+
get erc8004() {
|
|
116
|
+
return this._erc8004Manager;
|
|
117
|
+
}
|
|
118
|
+
// ─────────────────────────────────────────────────────────────
|
|
119
|
+
// CONSTRUCTOR
|
|
120
|
+
// ─────────────────────────────────────────────────────────────
|
|
121
|
+
/**
|
|
122
|
+
* Create a new Q00bsAgent.
|
|
123
|
+
*
|
|
124
|
+
* @param config - Agent configuration. Must include either `privateKey` (Mode 1) or `privy` (Mode 2).
|
|
125
|
+
*
|
|
126
|
+
* NOTE: This does NOT connect to the blockchain yet. Call initialize() next.
|
|
127
|
+
*/
|
|
128
|
+
constructor(config) {
|
|
129
|
+
// Validate that at least one wallet mode is configured
|
|
130
|
+
if (!config.privateKey && !config.privy) {
|
|
131
|
+
throw new Error('Agent requires a wallet. Provide either:\n' +
|
|
132
|
+
' • privateKey (Mode 1 — raw key, simpler but less secure)\n' +
|
|
133
|
+
' • privy (Mode 2 — Privy server wallet, recommended for ClawBots)\n' +
|
|
134
|
+
'See: https://privy.io/blog/securely-equipping-openclaw-agents-with-privy-wallets');
|
|
135
|
+
}
|
|
136
|
+
// Privy mode takes precedence (safer default)
|
|
137
|
+
this._walletMode = config.privy ? 'privy' : 'privateKey';
|
|
138
|
+
this.config = config;
|
|
139
|
+
this.logger = (0, client_1.createLogger)(config.logLevel || 'info');
|
|
140
|
+
this._agentId = config.agentId;
|
|
141
|
+
}
|
|
142
|
+
// ─────────────────────────────────────────────────────────────
|
|
143
|
+
// INITIALIZATION
|
|
144
|
+
// ─────────────────────────────────────────────────────────────
|
|
145
|
+
/**
|
|
146
|
+
* Initialize blockchain connections and sub-modules.
|
|
147
|
+
* Must be called before any other method.
|
|
148
|
+
*
|
|
149
|
+
* In Mode 1 (private key): Creates viem clients and derives wallet address.
|
|
150
|
+
* In Mode 2 (Privy): Creates/loads Privy wallet with policy, gets address.
|
|
151
|
+
*
|
|
152
|
+
* @param walletPolicy - (Mode 2 only) Policy to apply when creating a new Privy wallet.
|
|
153
|
+
* @throws If configuration is invalid.
|
|
154
|
+
*/
|
|
155
|
+
async initialize(walletPolicy) {
|
|
156
|
+
this.logger.info(`Initializing Q00bs Agent (mode: ${this._walletMode})...`);
|
|
157
|
+
if (this._walletMode === 'privy') {
|
|
158
|
+
// ── MODE 2: Privy server wallet ────────────────────────
|
|
159
|
+
const clients = (0, client_1.createPrivyClients)({
|
|
160
|
+
privy: this.config.privy,
|
|
161
|
+
rpcUrl: this.config.rpcUrl,
|
|
162
|
+
logger: this.logger,
|
|
163
|
+
});
|
|
164
|
+
this.publicClient = clients.publicClient;
|
|
165
|
+
this.privyManager = clients.privyWalletManager;
|
|
166
|
+
// Create or load the Privy wallet
|
|
167
|
+
const defaultPolicy = walletPolicy || privy_1.PrivyWalletManager.buildDefaultPolicy(this.config.maxTransactionValue || '0.1', this.config.dailySpendLimit || '1.0',
|
|
168
|
+
// Whitelist all configured contract addresses
|
|
169
|
+
[
|
|
170
|
+
this.config.registryAddress,
|
|
171
|
+
this.config.escrowAddress,
|
|
172
|
+
this.config.consensusAddress,
|
|
173
|
+
].filter(Boolean));
|
|
174
|
+
const walletInfo = await this.privyManager.initialize(defaultPolicy);
|
|
175
|
+
this.walletAddress = walletInfo.address;
|
|
176
|
+
this.logger.info(`Privy wallet ${walletInfo.isNew ? 'created' : 'loaded'}: ${this.walletAddress}`);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
// ── MODE 1: Raw private key ────────────────────────────
|
|
180
|
+
const clients = (0, client_1.createClients)({
|
|
181
|
+
privateKey: this.config.privateKey,
|
|
182
|
+
rpcUrl: this.config.rpcUrl,
|
|
183
|
+
logger: this.logger,
|
|
184
|
+
});
|
|
185
|
+
this.publicClient = clients.publicClient;
|
|
186
|
+
this.walletClient = clients.walletClient;
|
|
187
|
+
this.walletAddress = clients.account.address;
|
|
188
|
+
}
|
|
189
|
+
// Initialize sub-modules (same for both modes)
|
|
190
|
+
this.trustResolver = new trust_1.TrustResolver(this.publicClient, this.config.registryAddress, this.logger);
|
|
191
|
+
this.agentDiscovery = new discovery_1.AgentDiscovery(this.publicClient, this.config.registryAddress, this.trustResolver, this.logger);
|
|
192
|
+
if (this.config.escrowAddress) {
|
|
193
|
+
if (this._walletMode === 'privateKey' && this.walletClient) {
|
|
194
|
+
this.escrowManager = new escrow_1.EscrowManager(this.publicClient, this.walletClient, this.config.escrowAddress, this.logger);
|
|
195
|
+
}
|
|
196
|
+
// In Privy mode, escrow transactions are routed through PrivyWalletManager
|
|
197
|
+
// instead of the walletClient — the escrow methods handle this internally.
|
|
198
|
+
}
|
|
199
|
+
if (this.config.consensusAddress) {
|
|
200
|
+
if (this._walletMode === 'privateKey' && this.walletClient) {
|
|
201
|
+
this.consensusManager = new consensus_1.ConsensusManager(this.publicClient, this.walletClient, this.config.consensusAddress, this.logger);
|
|
202
|
+
}
|
|
203
|
+
// In Privy mode, consensus transactions are routed through PrivyWalletManager.
|
|
204
|
+
}
|
|
205
|
+
// ── Initialize ERC-8004 (if configured or by default) ──
|
|
206
|
+
// ERC-8004 reads are always available (publicClient only).
|
|
207
|
+
// Writes require walletClient (Mode 1) — in Privy mode, use API.
|
|
208
|
+
this._erc8004Manager = new erc8004_1.ERC8004Manager(this.publicClient, this.logger, this.walletClient, // undefined in Privy mode — write ops go through API
|
|
209
|
+
this.config.erc8004);
|
|
210
|
+
this.logger.info('ERC-8004 Trustless Agents integration enabled');
|
|
211
|
+
// If agentId was provided, verify it exists on-chain
|
|
212
|
+
if (this._agentId) {
|
|
213
|
+
const record = await this.agentDiscovery.getAgent(this._agentId);
|
|
214
|
+
if (!record) {
|
|
215
|
+
this.logger.warn(`Agent ID ${this._agentId} not found on-chain`);
|
|
216
|
+
this._agentId = undefined;
|
|
217
|
+
}
|
|
218
|
+
else if (record.wallet.toLowerCase() !== this.walletAddress.toLowerCase()) {
|
|
219
|
+
this.logger.warn(`Agent ID ${this._agentId} wallet mismatch: ` +
|
|
220
|
+
`expected ${this.walletAddress}, got ${record.wallet}`);
|
|
221
|
+
this._agentId = undefined;
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
this.logger.info(`Loaded agent ID ${this._agentId} (trust: ${record.trustScore / 100}%)`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// Try to find agent by wallet if not set
|
|
228
|
+
if (!this._agentId) {
|
|
229
|
+
const found = await this.agentDiscovery.getAgentByWallet(this.walletAddress);
|
|
230
|
+
if (found) {
|
|
231
|
+
this._agentId = found.id;
|
|
232
|
+
this.logger.info(`Found existing agent ID ${this._agentId} for wallet ${this.walletAddress}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
this._initialized = true;
|
|
236
|
+
this.logger.info(`Q00bs Agent initialized | Mode: ${this._walletMode} | Wallet: ${this.walletAddress}`);
|
|
237
|
+
}
|
|
238
|
+
// ─────────────────────────────────────────────────────────────
|
|
239
|
+
// REGISTRATION
|
|
240
|
+
// ─────────────────────────────────────────────────────────────
|
|
241
|
+
/**
|
|
242
|
+
* Register this agent on-chain on one side of the owner's q00b.
|
|
243
|
+
*
|
|
244
|
+
* @param ownerQ00bAddress - The q00b contract address owned by this agent's human.
|
|
245
|
+
* @param sidePosition - Which side of the q00b (0-5) to occupy.
|
|
246
|
+
* @returns The new agent's on-chain ID.
|
|
247
|
+
*
|
|
248
|
+
* IMPORTANT: The transaction sender must be the q00b OWNER (not the agent wallet).
|
|
249
|
+
* In practice, the owner calls registerAgent() from their wallet, passing
|
|
250
|
+
* the agent's wallet address. This method is for convenience when the owner's
|
|
251
|
+
* private key is used.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```ts
|
|
255
|
+
* const agentId = await agent.register('0xMyQ00bAddress', 0);
|
|
256
|
+
* console.log(`Registered as agent #${agentId}`);
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
async register(ownerQ00bAddress, sidePosition) {
|
|
260
|
+
this.ensureInitialized();
|
|
261
|
+
if (this._agentId) {
|
|
262
|
+
this.logger.warn(`Agent already registered with ID ${this._agentId}`);
|
|
263
|
+
return this._agentId;
|
|
264
|
+
}
|
|
265
|
+
// Hash capabilities for on-chain storage
|
|
266
|
+
const capabilities = this.config.capabilities || [];
|
|
267
|
+
const capabilitiesHash = (0, viem_1.keccak256)((0, viem_1.toHex)(JSON.stringify(capabilities)));
|
|
268
|
+
this.logger.info(`Registering agent on q00b ${ownerQ00bAddress}, side ${sidePosition}`);
|
|
269
|
+
if (!this.walletClient) {
|
|
270
|
+
throw new errors_1.PrivyWalletError('register() requires a viem walletClient (Mode 1). ' +
|
|
271
|
+
'In Privy mode (Mode 2), registration must go through the API or a separate owner transaction.');
|
|
272
|
+
}
|
|
273
|
+
const hash = await this.walletClient.writeContract({
|
|
274
|
+
address: this.config.registryAddress,
|
|
275
|
+
abi: AgentRegistry_1.AGENT_REGISTRY_ABI,
|
|
276
|
+
functionName: 'registerAgent',
|
|
277
|
+
args: [
|
|
278
|
+
this.walletAddress,
|
|
279
|
+
sidePosition,
|
|
280
|
+
capabilitiesHash,
|
|
281
|
+
],
|
|
282
|
+
});
|
|
283
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
284
|
+
this.logger.info(`Registration tx confirmed in block ${receipt.blockNumber}`);
|
|
285
|
+
// Parse agent ID from AgentRegistered event
|
|
286
|
+
for (const log of receipt.logs) {
|
|
287
|
+
if (log.topics && log.topics.length > 1) {
|
|
288
|
+
const id = Number(BigInt(log.topics[1]));
|
|
289
|
+
if (id > 0) {
|
|
290
|
+
this._agentId = id;
|
|
291
|
+
this.logger.info(`Registered as agent #${id}`);
|
|
292
|
+
return id;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
// Fallback: look up by wallet
|
|
297
|
+
const found = await this.agentDiscovery.getAgentByWallet(this.walletAddress);
|
|
298
|
+
if (found) {
|
|
299
|
+
this._agentId = found.id;
|
|
300
|
+
return found.id;
|
|
301
|
+
}
|
|
302
|
+
throw new Error('Registration succeeded but could not determine agent ID');
|
|
303
|
+
}
|
|
304
|
+
// ─────────────────────────────────────────────────────────────
|
|
305
|
+
// TRUST
|
|
306
|
+
// ─────────────────────────────────────────────────────────────
|
|
307
|
+
/**
|
|
308
|
+
* Check the trust path between this agent and another.
|
|
309
|
+
*
|
|
310
|
+
* @param targetAgentId - The other agent's on-chain ID.
|
|
311
|
+
* @returns TrustPath with connection status, hops, and effective trust score.
|
|
312
|
+
*/
|
|
313
|
+
async checkTrust(targetAgentId) {
|
|
314
|
+
this.ensureRegistered();
|
|
315
|
+
return this.trustResolver.resolve(this._agentId, targetAgentId);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Get this agent's on-chain record.
|
|
319
|
+
*/
|
|
320
|
+
async getMyRecord() {
|
|
321
|
+
this.ensureRegistered();
|
|
322
|
+
return this.agentDiscovery.getAgent(this._agentId);
|
|
323
|
+
}
|
|
324
|
+
// ─────────────────────────────────────────────────────────────
|
|
325
|
+
// DISCOVERY
|
|
326
|
+
// ─────────────────────────────────────────────────────────────
|
|
327
|
+
/**
|
|
328
|
+
* Search for agents in the trust network.
|
|
329
|
+
*
|
|
330
|
+
* @param query - Optional filters (minTrustScore, maxHops, limit, sortBy).
|
|
331
|
+
* @returns Array of discovered agents sorted by effective trust.
|
|
332
|
+
*/
|
|
333
|
+
async discoverAgents(query) {
|
|
334
|
+
this.ensureRegistered();
|
|
335
|
+
return this.agentDiscovery.find(this._agentId, query);
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Get any agent's record by ID.
|
|
339
|
+
*/
|
|
340
|
+
async getAgent(agentId) {
|
|
341
|
+
this.ensureInitialized();
|
|
342
|
+
return this.agentDiscovery.getAgent(agentId);
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Get any agent's record by wallet address.
|
|
346
|
+
*/
|
|
347
|
+
async getAgentByWallet(wallet) {
|
|
348
|
+
this.ensureInitialized();
|
|
349
|
+
return this.agentDiscovery.getAgentByWallet(wallet);
|
|
350
|
+
}
|
|
351
|
+
// ─────────────────────────────────────────────────────────────
|
|
352
|
+
// ESCROW (PAYMENTS)
|
|
353
|
+
// ─────────────────────────────────────────────────────────────
|
|
354
|
+
/**
|
|
355
|
+
* Create an escrow to pay another agent for a task.
|
|
356
|
+
*
|
|
357
|
+
* @param params - Service agent ID, task description, payment amount, deadline.
|
|
358
|
+
* @returns The new escrow ID.
|
|
359
|
+
* @throws If escrow module is not configured.
|
|
360
|
+
*/
|
|
361
|
+
async createEscrow(params) {
|
|
362
|
+
this.ensureRegistered();
|
|
363
|
+
this.ensureEscrow();
|
|
364
|
+
return this.escrowManager.create(this._agentId, params);
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Accept an escrow (as the service agent).
|
|
368
|
+
*/
|
|
369
|
+
async acceptEscrow(escrowId) {
|
|
370
|
+
this.ensureInitialized();
|
|
371
|
+
this.ensureEscrow();
|
|
372
|
+
return this.escrowManager.accept(escrowId);
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Mark an escrow complete (as the service agent).
|
|
376
|
+
*/
|
|
377
|
+
async completeEscrow(escrowId, deliverableDescription) {
|
|
378
|
+
this.ensureInitialized();
|
|
379
|
+
this.ensureEscrow();
|
|
380
|
+
return this.escrowManager.markComplete(escrowId, deliverableDescription);
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Release escrowed funds to the service agent (as the client agent).
|
|
384
|
+
*/
|
|
385
|
+
async releaseEscrow(escrowId) {
|
|
386
|
+
this.ensureInitialized();
|
|
387
|
+
this.ensureEscrow();
|
|
388
|
+
return this.escrowManager.release(escrowId);
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Request refund for an expired escrow.
|
|
392
|
+
*/
|
|
393
|
+
async refundEscrow(escrowId) {
|
|
394
|
+
this.ensureInitialized();
|
|
395
|
+
this.ensureEscrow();
|
|
396
|
+
return this.escrowManager.refund(escrowId);
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Get escrow details.
|
|
400
|
+
*/
|
|
401
|
+
async getEscrow(escrowId) {
|
|
402
|
+
this.ensureInitialized();
|
|
403
|
+
this.ensureEscrow();
|
|
404
|
+
return this.escrowManager.get(escrowId);
|
|
405
|
+
}
|
|
406
|
+
// ─────────────────────────────────────────────────────────────
|
|
407
|
+
// CONSENSUS
|
|
408
|
+
// ─────────────────────────────────────────────────────────────
|
|
409
|
+
/**
|
|
410
|
+
* Request consensus from peer agents for a high-stakes action.
|
|
411
|
+
*
|
|
412
|
+
* @param params - Action description, value, and optional timeout.
|
|
413
|
+
* @returns The consensus request ID.
|
|
414
|
+
*/
|
|
415
|
+
async requestConsensus(params) {
|
|
416
|
+
this.ensureRegistered();
|
|
417
|
+
this.ensureConsensus();
|
|
418
|
+
return this.consensusManager.request(this._agentId, params);
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Vote on a peer's consensus request.
|
|
422
|
+
*/
|
|
423
|
+
async voteOnConsensus(requestId, approve) {
|
|
424
|
+
this.ensureRegistered();
|
|
425
|
+
this.ensureConsensus();
|
|
426
|
+
return this.consensusManager.vote(requestId, this._agentId, approve);
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Wait for a consensus request to reach a decision (blocking).
|
|
430
|
+
*/
|
|
431
|
+
async waitForConsensus(requestId, pollIntervalMs, timeoutMs) {
|
|
432
|
+
this.ensureInitialized();
|
|
433
|
+
this.ensureConsensus();
|
|
434
|
+
return this.consensusManager.waitForResult(requestId, pollIntervalMs, timeoutMs);
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Get consensus request details.
|
|
438
|
+
*/
|
|
439
|
+
async getConsensusRequest(requestId) {
|
|
440
|
+
this.ensureInitialized();
|
|
441
|
+
this.ensureConsensus();
|
|
442
|
+
return this.consensusManager.get(requestId);
|
|
443
|
+
}
|
|
444
|
+
// ─────────────────────────────────────────────────────────────
|
|
445
|
+
// PRIVY WALLET MANAGEMENT (MODE 2 ONLY)
|
|
446
|
+
// ─────────────────────────────────────────────────────────────
|
|
447
|
+
/**
|
|
448
|
+
* Get this agent's Privy wallet info (Mode 2 only).
|
|
449
|
+
*
|
|
450
|
+
* @returns The Privy wallet info, or undefined if not in Privy mode.
|
|
451
|
+
*/
|
|
452
|
+
getPrivyWalletInfo() {
|
|
453
|
+
return this.privyManager?.walletInfo;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Update the spending policy on this agent's Privy wallet (Mode 2 only).
|
|
457
|
+
*
|
|
458
|
+
* Use this to dynamically adjust limits — for example, after the agent
|
|
459
|
+
* gains more trust or is granted higher permissions by its owner.
|
|
460
|
+
*
|
|
461
|
+
* @param policy - The new wallet policy to apply.
|
|
462
|
+
* @throws PrivyWalletError if not in Privy mode or update fails.
|
|
463
|
+
*
|
|
464
|
+
* @example
|
|
465
|
+
* ```ts
|
|
466
|
+
* await agent.updatePrivyPolicy({
|
|
467
|
+
* name: 'Elevated Limits',
|
|
468
|
+
* rules: [
|
|
469
|
+
* { type: 'max_transaction_value', value: '0.5' },
|
|
470
|
+
* { type: 'daily_spend_limit', value: '5.0' },
|
|
471
|
+
* ],
|
|
472
|
+
* });
|
|
473
|
+
* ```
|
|
474
|
+
*/
|
|
475
|
+
async updatePrivyPolicy(policy) {
|
|
476
|
+
this.ensureInitialized();
|
|
477
|
+
if (!this.privyManager) {
|
|
478
|
+
throw new errors_1.PrivyWalletError('updatePrivyPolicy() is only available in Privy mode (Mode 2). ' +
|
|
479
|
+
'Set `privy` in AgentConfig to use Privy wallets.');
|
|
480
|
+
}
|
|
481
|
+
const walletInfo = this.privyManager.walletInfo;
|
|
482
|
+
if (!walletInfo) {
|
|
483
|
+
throw new errors_1.PrivyWalletError('Privy wallet not initialized');
|
|
484
|
+
}
|
|
485
|
+
await this.privyManager.setPolicy(walletInfo.walletId, policy);
|
|
486
|
+
this.logger.info(`Privy wallet policy updated: "${policy.name}"`);
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Sign a message with this agent's wallet.
|
|
490
|
+
*
|
|
491
|
+
* Works in both modes:
|
|
492
|
+
* - Mode 1: Uses viem walletClient.signMessage()
|
|
493
|
+
* - Mode 2: Uses Privy's signMessage API
|
|
494
|
+
*
|
|
495
|
+
* @param message - The message to sign.
|
|
496
|
+
* @returns The signature hex string.
|
|
497
|
+
*/
|
|
498
|
+
async signMessage(message) {
|
|
499
|
+
this.ensureInitialized();
|
|
500
|
+
if (this._walletMode === 'privy' && this.privyManager) {
|
|
501
|
+
const walletInfo = this.privyManager.walletInfo;
|
|
502
|
+
if (!walletInfo)
|
|
503
|
+
throw new errors_1.PrivyWalletError('Privy wallet not initialized');
|
|
504
|
+
return this.privyManager.signMessage(walletInfo.walletId, message);
|
|
505
|
+
}
|
|
506
|
+
if (this.walletClient) {
|
|
507
|
+
return this.walletClient.signMessage({
|
|
508
|
+
message,
|
|
509
|
+
account: this.walletClient.account,
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
throw new Error('No wallet available for signing');
|
|
513
|
+
}
|
|
514
|
+
// ─────────────────────────────────────────────────────────────
|
|
515
|
+
// ERC-8004 TRUSTLESS AGENTS
|
|
516
|
+
// ─────────────────────────────────────────────────────────────
|
|
517
|
+
//
|
|
518
|
+
// These methods provide a convenient interface for ERC-8004 operations
|
|
519
|
+
// directly from the Q00bsAgent. For advanced usage, access the
|
|
520
|
+
// underlying ERC8004Manager via `agent.erc8004`.
|
|
521
|
+
//
|
|
522
|
+
// ERC-8004 gives your Q00bs agents interoperable identity and
|
|
523
|
+
// reputation that other agent platforms can read and verify.
|
|
524
|
+
/**
|
|
525
|
+
* Register this agent's ERC-8004 identity in the IdentityRegistry.
|
|
526
|
+
*
|
|
527
|
+
* This creates a portable identity on the canonical ERC-8004 registry
|
|
528
|
+
* that other agent platforms can discover and verify.
|
|
529
|
+
*
|
|
530
|
+
* @param ownerAddress - Address to mint the identity NFT to (usually your wallet).
|
|
531
|
+
* @returns The new ERC-8004 identity.
|
|
532
|
+
*
|
|
533
|
+
* @example
|
|
534
|
+
* ```ts
|
|
535
|
+
* const identity = await agent.registerERC8004Identity(agent.address);
|
|
536
|
+
* console.log(`ERC-8004 ID: ${identity.agentId}`);
|
|
537
|
+
* console.log(`Identifier: ${identity.identifier}`);
|
|
538
|
+
* ```
|
|
539
|
+
*/
|
|
540
|
+
async registerERC8004Identity(ownerAddress) {
|
|
541
|
+
this.ensureInitialized();
|
|
542
|
+
this.ensureERC8004();
|
|
543
|
+
const owner = ownerAddress || this.walletAddress;
|
|
544
|
+
return this._erc8004Manager.registerIdentity(owner);
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Get an ERC-8004 identity by agentId.
|
|
548
|
+
*
|
|
549
|
+
* @param agentId - The ERC-8004 agentId (tokenId in IdentityRegistry).
|
|
550
|
+
* @returns The identity, or null if not found.
|
|
551
|
+
*/
|
|
552
|
+
async getERC8004Identity(agentId) {
|
|
553
|
+
this.ensureInitialized();
|
|
554
|
+
this.ensureERC8004();
|
|
555
|
+
return this._erc8004Manager.getIdentity(agentId);
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Set the agentURI on this agent's ERC-8004 identity.
|
|
559
|
+
*
|
|
560
|
+
* The URI should point to a JSON registration file describing
|
|
561
|
+
* the agent (name, capabilities, endpoints, trust level, etc.).
|
|
562
|
+
*
|
|
563
|
+
* @param erc8004AgentId - The agent's ERC-8004 ID.
|
|
564
|
+
* @param uri - The URI (IPFS, HTTPS, etc.).
|
|
565
|
+
*/
|
|
566
|
+
async setERC8004AgentURI(erc8004AgentId, uri) {
|
|
567
|
+
this.ensureInitialized();
|
|
568
|
+
this.ensureERC8004();
|
|
569
|
+
return this._erc8004Manager.setAgentURI(erc8004AgentId, uri);
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Sync this agent's Q00bs trust score to its ERC-8004 metadata.
|
|
573
|
+
*
|
|
574
|
+
* This makes the Q00bs trust score visible to other agent platforms
|
|
575
|
+
* that read ERC-8004 metadata.
|
|
576
|
+
*
|
|
577
|
+
* @param erc8004AgentId - The agent's ERC-8004 ID.
|
|
578
|
+
*/
|
|
579
|
+
async syncTrustToERC8004(erc8004AgentId) {
|
|
580
|
+
this.ensureRegistered();
|
|
581
|
+
this.ensureERC8004();
|
|
582
|
+
const record = await this.agentDiscovery.getAgent(this._agentId);
|
|
583
|
+
if (!record) {
|
|
584
|
+
throw new Error(`Q00bs agent ${this._agentId} not found on-chain`);
|
|
585
|
+
}
|
|
586
|
+
await this._erc8004Manager.syncTrustToMetadata(erc8004AgentId, this._agentId, record.trustScore);
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Give ERC-8004 feedback to another agent.
|
|
590
|
+
*
|
|
591
|
+
* This publishes a reputation signal on the canonical ReputationRegistry.
|
|
592
|
+
* Other agent platforms can read this feedback to assess your peer's
|
|
593
|
+
* trustworthiness.
|
|
594
|
+
*
|
|
595
|
+
* @param params - Feedback parameters (subject, value, decimals).
|
|
596
|
+
* @param fromERC8004AgentId - Your agent's ERC-8004 ID.
|
|
597
|
+
* @returns The feedback index.
|
|
598
|
+
*
|
|
599
|
+
* @example
|
|
600
|
+
* ```ts
|
|
601
|
+
* await agent.giveERC8004Feedback({
|
|
602
|
+
* subjectAgentId: 7,
|
|
603
|
+
* value: 4.5, // positive feedback
|
|
604
|
+
* decimals: 2,
|
|
605
|
+
* }, myERC8004Id);
|
|
606
|
+
* ```
|
|
607
|
+
*/
|
|
608
|
+
async giveERC8004Feedback(params, fromERC8004AgentId) {
|
|
609
|
+
this.ensureInitialized();
|
|
610
|
+
this.ensureERC8004();
|
|
611
|
+
return this._erc8004Manager.giveFeedback(params, fromERC8004AgentId);
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Get the ERC-8004 reputation summary for an agent.
|
|
615
|
+
*
|
|
616
|
+
* @param erc8004AgentId - The agent's ERC-8004 ID.
|
|
617
|
+
* @returns Aggregate reputation summary.
|
|
618
|
+
*/
|
|
619
|
+
async getERC8004Reputation(erc8004AgentId) {
|
|
620
|
+
this.ensureInitialized();
|
|
621
|
+
this.ensureERC8004();
|
|
622
|
+
return this._erc8004Manager.getReputationSummary(erc8004AgentId);
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* Read all ERC-8004 feedback for an agent.
|
|
626
|
+
*
|
|
627
|
+
* @param erc8004AgentId - The agent's ERC-8004 ID.
|
|
628
|
+
* @returns Array of feedback entries.
|
|
629
|
+
*/
|
|
630
|
+
async getERC8004Feedback(erc8004AgentId) {
|
|
631
|
+
this.ensureInitialized();
|
|
632
|
+
this.ensureERC8004();
|
|
633
|
+
return this._erc8004Manager.readAllFeedback(erc8004AgentId);
|
|
634
|
+
}
|
|
635
|
+
// ─────────────────────────────────────────────────────────────
|
|
636
|
+
// UTILITIES
|
|
637
|
+
// ─────────────────────────────────────────────────────────────
|
|
638
|
+
/**
|
|
639
|
+
* Calculate effective trust locally (no blockchain call).
|
|
640
|
+
* Useful for quick UI previews.
|
|
641
|
+
*/
|
|
642
|
+
calculateTrust(baseTrustScore, hops) {
|
|
643
|
+
return trust_1.TrustResolver.calculateLocally(baseTrustScore, hops);
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Clear the trust cache (call after known on-chain changes).
|
|
647
|
+
*/
|
|
648
|
+
clearTrustCache() {
|
|
649
|
+
this.trustResolver?.clearCache();
|
|
650
|
+
}
|
|
651
|
+
// ─────────────────────────────────────────────────────────────
|
|
652
|
+
// PRIVATE GUARDS
|
|
653
|
+
// ─────────────────────────────────────────────────────────────
|
|
654
|
+
ensureInitialized() {
|
|
655
|
+
if (!this._initialized) {
|
|
656
|
+
throw new Error('Agent not initialized. Call agent.initialize() first.');
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
ensureRegistered() {
|
|
660
|
+
this.ensureInitialized();
|
|
661
|
+
if (!this._agentId) {
|
|
662
|
+
throw new errors_1.AgentNotRegisteredError();
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
ensureEscrow() {
|
|
666
|
+
if (this._walletMode === 'privy') {
|
|
667
|
+
// In Privy mode, escrow doesn't need a walletClient — it uses Privy.
|
|
668
|
+
if (!this.config.escrowAddress) {
|
|
669
|
+
throw new Error('Escrow not configured. Pass escrowAddress in AgentConfig to enable payments.');
|
|
670
|
+
}
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
if (!this.escrowManager) {
|
|
674
|
+
throw new Error('Escrow not configured. Pass escrowAddress in AgentConfig to enable payments.');
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
ensureConsensus() {
|
|
678
|
+
if (this._walletMode === 'privy') {
|
|
679
|
+
if (!this.config.consensusAddress) {
|
|
680
|
+
throw new Error('Consensus not configured. Pass consensusAddress in AgentConfig to enable consensus.');
|
|
681
|
+
}
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
if (!this.consensusManager) {
|
|
685
|
+
throw new Error('Consensus not configured. Pass consensusAddress in AgentConfig to enable consensus.');
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
ensureERC8004() {
|
|
689
|
+
if (!this._erc8004Manager) {
|
|
690
|
+
throw new errors_1.ERC8004NotConfiguredError();
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
exports.Q00bsAgent = Q00bsAgent;
|
|
695
|
+
//# sourceMappingURL=Q00bsAgent.js.map
|