@agether/sdk 1.11.2 → 2.1.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/index.mjs CHANGED
@@ -55,40 +55,45 @@ var IDENTITY_REGISTRY_ABI = [
55
55
  "function register() returns (uint256 agentId)",
56
56
  "event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)"
57
57
  ];
58
- var ACCOUNT_FACTORY_ABI = [
58
+ var AGETHER_4337_FACTORY_ABI = [
59
59
  "function getAccount(uint256 agentId) view returns (address)",
60
60
  "function accountExists(uint256 agentId) view returns (bool)",
61
- "function predictAddress(uint256 agentId) view returns (address)",
62
61
  "function totalAccounts() view returns (uint256)",
63
62
  "function getAgentId(address account) view returns (uint256)",
64
- "function createAccount(uint256 agentId) returns (address account)",
65
- "function protocolHook() view returns (address)",
63
+ "function getAgentIdByIndex(uint256 index) view returns (uint256)",
64
+ "function getAllAgentIds() view returns (uint256[])",
65
+ "function createAccount(uint256 agentId) returns (address safeAccount)",
66
66
  "function identityRegistry() view returns (address)",
67
- "event AccountCreated(uint256 indexed agentId, address indexed account, address indexed owner)"
67
+ "function validationModule() view returns (address)",
68
+ "function hookMultiplexer() view returns (address)",
69
+ "function safeSingleton() view returns (address)",
70
+ "function safe7579() view returns (address)",
71
+ "function bootstrap() view returns (address)",
72
+ "event AccountCreated(uint256 indexed agentId, address indexed safeAccount, address indexed owner)"
68
73
  ];
69
- var AGENT_ACCOUNT_ABI = [
70
- "function agentId() view returns (uint256)",
74
+ var SAFE_AGENT_FACTORY_ABI = AGETHER_4337_FACTORY_ABI;
75
+ var ACCOUNT_FACTORY_ABI = AGETHER_4337_FACTORY_ABI;
76
+ var AGETHER_8004_VALIDATION_MODULE_ABI = [
77
+ // View
78
+ "function getConfig(address account) view returns (address registry, uint256 agentId)",
79
+ "function getOwner(address account) view returns (address)",
80
+ "function isInstalled(address account) view returns (bool)",
81
+ "function isKYAApproved(address account) view returns (bool)",
82
+ "function validationRegistry() view returns (address)",
71
83
  "function owner() view returns (address)",
72
- "function factory() view returns (address)",
73
- "function identityRegistry() view returns (address)",
74
- "function balanceOf(address token) view returns (uint256)",
75
- "function ethBalance() view returns (uint256)",
76
- // ERC-7579 execution
77
- "function execute(bytes32 mode, bytes executionCalldata) payable",
78
- "function executeFromExecutor(bytes32 mode, bytes executionCalldata) payable returns (bytes[])",
79
- // ERC-7579 module management
80
- "function installModule(uint256 moduleTypeId, address module, bytes initData) payable",
81
- "function uninstallModule(uint256 moduleTypeId, address module, bytes deInitData) payable",
82
- "function isModuleInstalled(uint256 moduleTypeId, address module, bytes additionalContext) view returns (bool)",
83
- "function hook() view returns (address)",
84
- // Funding (direct, no execution needed)
85
- "function fund(address token, uint256 amount)",
86
- "function withdraw(address token, uint256 amount, address to)",
87
- "function withdrawETH(uint256 amount, address to)",
88
- // EIP-1271
89
- "function isValidSignature(bytes32 hash, bytes signature) view returns (bytes4)"
84
+ // Admin (via TimelockController)
85
+ "function setValidationRegistry(address registry_)"
86
+ ];
87
+ var ERC8004_VALIDATION_MODULE_ABI = AGETHER_8004_VALIDATION_MODULE_ABI;
88
+ var AGETHER_HOOK_MULTIPLEXER_ABI = [
89
+ "function getHooks() view returns (address[])",
90
+ "function hookCount() view returns (uint256)",
91
+ "function owner() view returns (address)",
92
+ "function addHook(address hook)",
93
+ "function removeHook(address hook)"
90
94
  ];
91
- var AGENT_REPUTATION_ABI = [
95
+ var HOOK_MULTIPLEXER_ABI = AGETHER_HOOK_MULTIPLEXER_ABI;
96
+ var AGETHER_8004_SCORER_ABI = [
92
97
  "function getCreditScore(uint256 agentId) view returns (uint256)",
93
98
  "function getAttestation(uint256 agentId) view returns (tuple(uint256 score, uint256 timestamp, address signer))",
94
99
  "function isScoreFresh(uint256 agentId) view returns (bool fresh, uint256 age)",
@@ -98,6 +103,7 @@ var AGENT_REPUTATION_ABI = [
98
103
  "function setOracleSigner(address signer_)",
99
104
  "event ScoreUpdated(uint256 indexed agentId, uint256 score, uint256 timestamp, address signer)"
100
105
  ];
106
+ var AGENT_REPUTATION_ABI = AGETHER_8004_SCORER_ABI;
101
107
  var VALIDATION_REGISTRY_ABI = [
102
108
  "function isAgentCodeApproved(uint256 agentId) view returns (bool)",
103
109
  "function isAgentCodeApprovedForTag(uint256 agentId, string tag) view returns (bool)",
@@ -132,57 +138,113 @@ var ERC20_ABI = [
132
138
  "function symbol() view returns (string)",
133
139
  "function name() view returns (string)"
134
140
  ];
135
- var KYA_HOOK_ABI = [
136
- "function validationRegistry() view returns (address)",
137
- "function setValidationRegistry(address newRegistry)"
141
+ var ENTRYPOINT_V07_ABI = [
142
+ "function handleOps(tuple(address sender, uint256 nonce, bytes initCode, bytes callData, bytes32 accountGasLimits, uint256 preVerificationGas, bytes32 gasFees, bytes paymasterAndData, bytes signature)[] ops, address payable beneficiary)",
143
+ "function getUserOpHash(tuple(address sender, uint256 nonce, bytes initCode, bytes callData, bytes32 accountGasLimits, uint256 preVerificationGas, bytes32 gasFees, bytes paymasterAndData, bytes signature) userOp) view returns (bytes32)",
144
+ "function getNonce(address sender, uint192 key) view returns (uint256 nonce)",
145
+ "function balanceOf(address account) view returns (uint256)",
146
+ "function depositTo(address account) payable",
147
+ "event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed)"
148
+ ];
149
+ var SAFE7579_ACCOUNT_ABI = [
150
+ // ERC-7579 execution (called via UserOp through Safe7579 fallback)
151
+ "function execute(bytes32 mode, bytes executionCalldata) payable",
152
+ "function executeFromExecutor(bytes32 mode, bytes executionCalldata) payable returns (bytes[])",
153
+ // ERC-7579 module queries
154
+ "function isModuleInstalled(uint256 moduleTypeId, address module, bytes additionalContext) view returns (bool)",
155
+ // EIP-1271
156
+ "function isValidSignature(bytes32 hash, bytes signature) view returns (bytes4)"
138
157
  ];
139
158
 
140
159
  // src/utils/config.ts
160
+ var ZERO = "0x0000000000000000000000000000000000000000";
161
+ var ENTRYPOINT_V07 = "0x0000000071727De22E5E9d8BAf0edAc6f37da032";
162
+ var ERC8004_IDENTITY_REGISTRY = "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432";
163
+ var ERC8004_IDENTITY_REGISTRY_TESTNET = "0x8004A818BFB912233c491871b3d84c89A494BD9e";
164
+ var MORPHO_BLUE = "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb";
165
+ var SAFE_SINGLETON = "0x41675C099F32341bf84BFc5382aF534df5C7461a";
166
+ var SAFE_PROXY_FACTORY = "0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67";
167
+ var SAFE7579 = "0x7579EE8307284F293B1927136486880611F20002";
141
168
  var CONTRACT_ADDRESSES = {
142
169
  [1 /* Ethereum */]: {
143
- accountFactory: "0x0000000000000000000000000000000000000000",
144
- validationRegistry: "0x0000000000000000000000000000000000000000",
145
- agentReputation: "0x0000000000000000000000000000000000000000",
146
- kyaHook: "0x0000000000000000000000000000000000000000",
170
+ safeSingleton: SAFE_SINGLETON,
171
+ safeProxyFactory: SAFE_PROXY_FACTORY,
172
+ safe7579: SAFE7579,
173
+ entryPoint: ENTRYPOINT_V07,
174
+ agether4337Factory: ZERO,
175
+ agether7579Bootstrap: ZERO,
176
+ erc8004ValidationModule: ZERO,
177
+ agetherHookMultiplexer: ZERO,
178
+ validationRegistry: ZERO,
179
+ agether8004Scorer: ZERO,
180
+ timelockController: ZERO,
147
181
  usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
148
- identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
149
- morphoBlue: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb"
182
+ identityRegistry: ERC8004_IDENTITY_REGISTRY,
183
+ morphoBlue: MORPHO_BLUE
150
184
  },
151
185
  [8453 /* Base */]: {
152
- accountFactory: "0x89a8758E60A56EcB47247D92E05447eFd450d6Bf",
153
- validationRegistry: "0x6f76cF69B71Dc5F9A414BCEe4583b12738E47985",
154
- agentReputation: "0xe88f3419a2dbac70e3aF6E487b0C63e8301C6A87",
155
- kyaHook: "0x28e50Aa9eD517E369b2806928709B44062aD9821",
186
+ safeSingleton: SAFE_SINGLETON,
187
+ safeProxyFactory: SAFE_PROXY_FACTORY,
188
+ safe7579: SAFE7579,
189
+ entryPoint: ENTRYPOINT_V07,
190
+ agether4337Factory: "0x7B23470dCD65b8fEA3Bf49466860b3A55D56268C",
191
+ agether7579Bootstrap: "0x62d34D22D379367EEDcb7D1E4dE899A654E982D0",
192
+ erc8004ValidationModule: "0xfC6ccFd12e163460C7Ef92d38DC0be6C6cA10f6C",
193
+ agetherHookMultiplexer: "0x094FE93a8b733a97a6945530cA83058CaCbf5278",
194
+ validationRegistry: ZERO,
195
+ agether8004Scorer: "0x9f0084E5c941365149c8953133cF062E33a19b8d",
196
+ timelockController: "0x2807912DA2a7278AF883a376bE15bBBf3ab99f52",
156
197
  usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
157
- identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
158
- morphoBlue: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb"
198
+ identityRegistry: ERC8004_IDENTITY_REGISTRY,
199
+ morphoBlue: MORPHO_BLUE
159
200
  },
160
201
  [84532 /* BaseSepolia */]: {
161
- accountFactory: "0x0000000000000000000000000000000000000000",
162
- validationRegistry: "0x0000000000000000000000000000000000000000",
163
- agentReputation: "0x0000000000000000000000000000000000000000",
164
- kyaHook: "0x0000000000000000000000000000000000000000",
202
+ safeSingleton: SAFE_SINGLETON,
203
+ safeProxyFactory: SAFE_PROXY_FACTORY,
204
+ safe7579: SAFE7579,
205
+ entryPoint: ENTRYPOINT_V07,
206
+ agether4337Factory: ZERO,
207
+ agether7579Bootstrap: ZERO,
208
+ erc8004ValidationModule: ZERO,
209
+ agetherHookMultiplexer: ZERO,
210
+ validationRegistry: ZERO,
211
+ agether8004Scorer: ZERO,
212
+ timelockController: ZERO,
165
213
  usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
166
- identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
167
- morphoBlue: "0x0000000000000000000000000000000000000000"
214
+ identityRegistry: ERC8004_IDENTITY_REGISTRY_TESTNET,
215
+ morphoBlue: ZERO
168
216
  },
169
217
  [11155111 /* Sepolia */]: {
170
- accountFactory: "0x0000000000000000000000000000000000000000",
171
- validationRegistry: "0x0000000000000000000000000000000000000000",
172
- agentReputation: "0x0000000000000000000000000000000000000000",
173
- kyaHook: "0x0000000000000000000000000000000000000000",
218
+ safeSingleton: SAFE_SINGLETON,
219
+ safeProxyFactory: SAFE_PROXY_FACTORY,
220
+ safe7579: SAFE7579,
221
+ entryPoint: ENTRYPOINT_V07,
222
+ agether4337Factory: ZERO,
223
+ agether7579Bootstrap: ZERO,
224
+ erc8004ValidationModule: ZERO,
225
+ agetherHookMultiplexer: ZERO,
226
+ validationRegistry: ZERO,
227
+ agether8004Scorer: ZERO,
228
+ timelockController: ZERO,
174
229
  usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
175
- identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
176
- morphoBlue: "0x0000000000000000000000000000000000000000"
230
+ identityRegistry: ERC8004_IDENTITY_REGISTRY_TESTNET,
231
+ morphoBlue: ZERO
177
232
  },
178
233
  [31337 /* Hardhat */]: {
179
- accountFactory: "0x0000000000000000000000000000000000000000",
180
- validationRegistry: "0x0000000000000000000000000000000000000000",
181
- agentReputation: "0x0000000000000000000000000000000000000000",
182
- kyaHook: "0x0000000000000000000000000000000000000000",
234
+ safeSingleton: SAFE_SINGLETON,
235
+ safeProxyFactory: SAFE_PROXY_FACTORY,
236
+ safe7579: SAFE7579,
237
+ entryPoint: ENTRYPOINT_V07,
238
+ agether4337Factory: ZERO,
239
+ agether7579Bootstrap: ZERO,
240
+ erc8004ValidationModule: ZERO,
241
+ agetherHookMultiplexer: ZERO,
242
+ validationRegistry: ZERO,
243
+ agether8004Scorer: ZERO,
244
+ timelockController: ZERO,
183
245
  usdc: "0x56d4d6aEe0278c5Df2FA23Ecb32eC146C9446FDf",
184
- identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
185
- morphoBlue: "0x0000000000000000000000000000000000000000"
246
+ identityRegistry: ERC8004_IDENTITY_REGISTRY,
247
+ morphoBlue: ZERO
186
248
  }
187
249
  };
188
250
  var RPC_URLS = {
@@ -227,9 +289,9 @@ var AgetherClient = class _AgetherClient {
227
289
  this.agentId = options.agentId;
228
290
  const provider = options.signer.provider;
229
291
  if (!provider) throw new AgetherError("Signer must have a provider", "NO_PROVIDER");
230
- this.accountFactory = new Contract(
231
- options.config.contracts.accountFactory,
232
- ACCOUNT_FACTORY_ABI,
292
+ this.agether4337Factory = new Contract(
293
+ options.config.contracts.agether4337Factory,
294
+ AGETHER_4337_FACTORY_ABI,
233
295
  options.signer
234
296
  );
235
297
  this.identityRegistry = new Contract(
@@ -237,14 +299,14 @@ var AgetherClient = class _AgetherClient {
237
299
  IDENTITY_REGISTRY_ABI,
238
300
  provider
239
301
  );
240
- this.validationRegistry = new Contract(
241
- options.config.contracts.validationRegistry,
242
- VALIDATION_REGISTRY_ABI,
302
+ this.agether8004Scorer = new Contract(
303
+ options.config.contracts.agether8004Scorer,
304
+ AGETHER_8004_SCORER_ABI,
243
305
  provider
244
306
  );
245
- this.agentReputation = new Contract(
246
- options.config.contracts.agentReputation,
247
- AGENT_REPUTATION_ABI,
307
+ this.validationModule = new Contract(
308
+ options.config.contracts.erc8004ValidationModule,
309
+ AGETHER_8004_VALIDATION_MODULE_ABI,
248
310
  provider
249
311
  );
250
312
  }
@@ -257,26 +319,26 @@ var AgetherClient = class _AgetherClient {
257
319
  }
258
320
  // Account Management
259
321
  async createAccount() {
260
- const tx = await this.accountFactory.createAccount(this.agentId);
322
+ const tx = await this.agether4337Factory.createAccount(this.agentId);
261
323
  const receipt = await tx.wait();
262
324
  const event = receipt.logs.map((log) => {
263
325
  try {
264
- return this.accountFactory.interface.parseLog(log);
326
+ return this.agether4337Factory.interface.parseLog(log);
265
327
  } catch (e) {
266
328
  console.warn("[agether] createAccount parseLog skip:", e instanceof Error ? e.message : e);
267
329
  return null;
268
330
  }
269
331
  }).find((e) => e?.name === "AccountCreated");
270
332
  if (event) {
271
- this.accountAddress = event.args.account;
333
+ this.accountAddress = event.args.safeAccount;
272
334
  } else {
273
- this.accountAddress = await this.accountFactory.getAccount(this.agentId);
335
+ this.accountAddress = await this.agether4337Factory.getAccount(this.agentId);
274
336
  }
275
337
  return this.accountAddress;
276
338
  }
277
339
  async getAccountAddress() {
278
340
  if (this.accountAddress) return this.accountAddress;
279
- const addr = await this.accountFactory.getAccount(this.agentId);
341
+ const addr = await this.agether4337Factory.getAccount(this.agentId);
280
342
  if (addr === ethers.ZeroAddress) {
281
343
  throw new AgetherError("No account found. Create one with createAccount().", "NO_ACCOUNT");
282
344
  }
@@ -284,10 +346,7 @@ var AgetherClient = class _AgetherClient {
284
346
  return addr;
285
347
  }
286
348
  async accountExists() {
287
- return this.accountFactory.accountExists(this.agentId);
288
- }
289
- async predictAddress() {
290
- return this.accountFactory.predictAddress(this.agentId);
349
+ return this.agether4337Factory.accountExists(this.agentId);
291
350
  }
292
351
  // Balances
293
352
  async getBalances() {
@@ -309,10 +368,14 @@ var AgetherClient = class _AgetherClient {
309
368
  usdc: ethers.formatUnits(acctUsdc, 6)
310
369
  };
311
370
  } catch (e) {
312
- console.warn("[agether] getBalances: no AgentAccount or fetch failed:", e instanceof Error ? e.message : e);
371
+ console.warn("[agether] getBalances: no Safe account or fetch failed:", e instanceof Error ? e.message : e);
313
372
  }
314
373
  return result;
315
374
  }
375
+ /**
376
+ * Fund the Safe account with USDC from EOA.
377
+ * This is a simple ERC-20 transfer (does NOT require a UserOp).
378
+ */
316
379
  async fundAccount(usdcAmount) {
317
380
  const acctAddr = await this.getAccountAddress();
318
381
  const usdc = new Contract(this.config.contracts.usdc, ERC20_ABI, this.signer);
@@ -326,37 +389,30 @@ var AgetherClient = class _AgetherClient {
326
389
  gasUsed: receipt.gasUsed
327
390
  };
328
391
  }
329
- async withdrawUsdc(usdcAmount) {
330
- const acctAddr = await this.getAccountAddress();
331
- const account = new Contract(acctAddr, AGENT_ACCOUNT_ABI, this.signer);
332
- const amount = ethers.parseUnits(usdcAmount, 6);
333
- const eoaAddr = await this.signer.getAddress();
334
- const tx = await account.withdraw(this.config.contracts.usdc, amount, eoaAddr);
335
- const receipt = await tx.wait();
336
- return {
337
- txHash: receipt.hash,
338
- blockNumber: receipt.blockNumber,
339
- status: receipt.status === 1 ? "success" : "failed",
340
- gasUsed: receipt.gasUsed
341
- };
342
- }
343
- async withdrawEth(ethAmount) {
344
- const acctAddr = await this.getAccountAddress();
345
- const account = new Contract(acctAddr, AGENT_ACCOUNT_ABI, this.signer);
346
- const amount = ethers.parseEther(ethAmount);
347
- const eoaAddr = await this.signer.getAddress();
348
- const tx = await account.withdrawETH(amount, eoaAddr);
349
- const receipt = await tx.wait();
350
- return {
351
- txHash: receipt.hash,
352
- blockNumber: receipt.blockNumber,
353
- status: receipt.status === 1 ? "success" : "failed",
354
- gasUsed: receipt.gasUsed
355
- };
356
- }
357
392
  // Identity & Validation
393
+ /**
394
+ * Check if the KYA gate is active on the validation module.
395
+ * If validationRegistry is not set, all txs pass (KYA disabled).
396
+ */
397
+ async isKyaRequired() {
398
+ try {
399
+ const registryAddr = await this.validationModule.validationRegistry();
400
+ return registryAddr !== ethers.ZeroAddress;
401
+ } catch {
402
+ return false;
403
+ }
404
+ }
405
+ /**
406
+ * Check if this agent's code is KYA-approved.
407
+ * Uses the ERC8004ValidationModule.isKYAApproved(account) view.
408
+ */
358
409
  async isKyaApproved() {
359
- return this.validationRegistry.isAgentCodeApproved(this.agentId);
410
+ try {
411
+ const acctAddr = await this.getAccountAddress();
412
+ return this.validationModule.isKYAApproved(acctAddr);
413
+ } catch {
414
+ return false;
415
+ }
360
416
  }
361
417
  async identityExists() {
362
418
  try {
@@ -372,14 +428,14 @@ var AgetherClient = class _AgetherClient {
372
428
  }
373
429
  // Reputation
374
430
  async getCreditScore() {
375
- return this.agentReputation.getCreditScore(this.agentId);
431
+ return this.agether8004Scorer.getCreditScore(this.agentId);
376
432
  }
377
433
  async isScoreFresh() {
378
- const [fresh, age] = await this.agentReputation.isScoreFresh(this.agentId);
434
+ const [fresh, age] = await this.agether8004Scorer.isScoreFresh(this.agentId);
379
435
  return { fresh, age };
380
436
  }
381
437
  async isEligible(minScore = 500n) {
382
- const [eligible, currentScore] = await this.agentReputation.isEligible(this.agentId, minScore);
438
+ const [eligible, currentScore] = await this.agether8004Scorer.isEligible(this.agentId, minScore);
383
439
  return { eligible, currentScore };
384
440
  }
385
441
  // Getters
@@ -444,27 +500,24 @@ var MorphoClient = class {
444
500
  this._eoaAddress = wallet.address;
445
501
  }
446
502
  const addrs = { ...defaultCfg.contracts, ...config.contracts };
447
- this.accountFactory = new Contract2(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this._signer);
503
+ this.agether4337Factory = new Contract2(addrs.agether4337Factory, ACCOUNT_FACTORY_ABI, this._signer);
448
504
  this.morphoBlue = new Contract2(addrs.morphoBlue, MORPHO_BLUE_ABI, this.provider);
449
- this.agentReputation = new Contract2(addrs.agentReputation, AGENT_REPUTATION_ABI, this._signer);
505
+ this.agether8004Scorer = new Contract2(addrs.agether8004Scorer, AGENT_REPUTATION_ABI, this._signer);
450
506
  this.identityRegistry = new Contract2(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this._signer);
507
+ this.entryPoint = new Contract2(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
508
+ this.validationModule = new Contract2(addrs.erc8004ValidationModule, ERC8004_VALIDATION_MODULE_ABI, this.provider);
451
509
  }
452
510
  // ════════════════════════════════════════════════════════
453
511
  // KYA Gate Check
454
512
  // ════════════════════════════════════════════════════════
455
513
  /**
456
514
  * Check whether the KYA (Know Your Agent) code verification gate is active.
457
- * Reads the account's installed hook and checks if it has a non-zero
458
- * validationRegistry when set, the hook enforces KYA code approval.
515
+ * Reads the ERC8004ValidationModule's validationRegistry when set to
516
+ * a non-zero address, the module enforces KYA code approval.
459
517
  */
460
518
  async isKyaRequired() {
461
519
  try {
462
- const acctAddr = await this.getAccountAddress();
463
- const account = new Contract2(acctAddr, AGENT_ACCOUNT_ABI, this.provider);
464
- const hookAddr = await account.hook();
465
- if (hookAddr === ethers2.ZeroAddress) return false;
466
- const hook = new Contract2(hookAddr, KYA_HOOK_ABI, this.provider);
467
- const registryAddr = await hook.validationRegistry();
520
+ const registryAddr = await this.validationModule.validationRegistry();
468
521
  return registryAddr !== ethers2.ZeroAddress;
469
522
  } catch {
470
523
  return false;
@@ -481,7 +534,7 @@ var MorphoClient = class {
481
534
  let lastErr;
482
535
  for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
483
536
  try {
484
- const addr = await this.accountFactory.getAccount(BigInt(this.agentId));
537
+ const addr = await this.agether4337Factory.getAccount(BigInt(this.agentId));
485
538
  if (addr === ethers2.ZeroAddress) {
486
539
  throw new AgetherError("No AgentAccount found. Call register() first.", "NO_ACCOUNT");
487
540
  }
@@ -559,9 +612,9 @@ var MorphoClient = class {
559
612
  async register(_name) {
560
613
  const eoaAddr = await this.getSignerAddress();
561
614
  if (this.agentId) {
562
- const exists = await this.accountFactory.accountExists(BigInt(this.agentId));
615
+ const exists = await this.agether4337Factory.accountExists(BigInt(this.agentId));
563
616
  if (exists) {
564
- const acct = await this.accountFactory.getAccount(BigInt(this.agentId));
617
+ const acct = await this.agether4337Factory.getAccount(BigInt(this.agentId));
565
618
  this._accountAddress = acct;
566
619
  const kyaRequired2 = await this.isKyaRequired();
567
620
  return { agentId: this.agentId, address: eoaAddr, agentAccount: acct, alreadyRegistered: true, kyaRequired: kyaRequired2 };
@@ -579,15 +632,15 @@ var MorphoClient = class {
579
632
  agentId = await this._mintNewIdentity();
580
633
  }
581
634
  this.agentId = agentId.toString();
582
- const acctExists = await this.accountFactory.accountExists(agentId);
635
+ const acctExists = await this.agether4337Factory.accountExists(agentId);
583
636
  let txHash;
584
637
  if (!acctExists) {
585
- const tx = await this.accountFactory.createAccount(agentId);
638
+ const tx = await this.agether4337Factory.createAccount(agentId);
586
639
  const receipt = await tx.wait();
587
640
  this._refreshSigner();
588
641
  txHash = receipt.hash;
589
642
  }
590
- const acctAddr = await this.accountFactory.getAccount(agentId);
643
+ const acctAddr = await this.agether4337Factory.getAccount(agentId);
591
644
  this._accountAddress = acctAddr;
592
645
  const kyaRequired = await this.isKyaRequired();
593
646
  return {
@@ -731,7 +784,7 @@ var MorphoClient = class {
731
784
  }
732
785
  /**
733
786
  * Get MarketParams for a collateral token.
734
- * Tries cache → API → on-chain idToMarketParams.
787
+ * Tries cache → API → onchain idToMarketParams.
735
788
  */
736
789
  async findMarketForCollateral(collateralSymbolOrAddress) {
737
790
  const colInfo = BASE_COLLATERALS[collateralSymbolOrAddress];
@@ -746,7 +799,7 @@ var MorphoClient = class {
746
799
  "MARKET_NOT_FOUND"
747
800
  );
748
801
  }
749
- /** Read MarketParams on-chain by market ID (bytes32). */
802
+ /** Read MarketParams onchain by market ID (bytes32). */
750
803
  async getMarketParams(marketId) {
751
804
  const result = await this.morphoBlue.idToMarketParams(marketId);
752
805
  return {
@@ -760,7 +813,7 @@ var MorphoClient = class {
760
813
  // ════════════════════════════════════════════════════════
761
814
  // Position Reads
762
815
  // ════════════════════════════════════════════════════════
763
- /** Read on-chain position for a specific market. */
816
+ /** Read onchain position for a specific market. */
764
817
  async getPosition(marketId) {
765
818
  const acctAddr = await this.getAccountAddress();
766
819
  const pos = await this.morphoBlue.position(marketId, acctAddr);
@@ -1314,7 +1367,7 @@ var MorphoClient = class {
1314
1367
  if (target.address) {
1315
1368
  targetAddr = target.address;
1316
1369
  } else if (target.agentId) {
1317
- targetAddr = await this.accountFactory.getAccount(BigInt(target.agentId));
1370
+ targetAddr = await this.agether4337Factory.getAccount(BigInt(target.agentId));
1318
1371
  if (targetAddr === ethers2.ZeroAddress) throw new AgetherError("Target agent has no account", "NO_ACCOUNT");
1319
1372
  } else {
1320
1373
  throw new AgetherError("Provide agentId or address", "INVALID_TARGET");
@@ -1327,25 +1380,25 @@ var MorphoClient = class {
1327
1380
  return { tx: receipt.hash, targetAccount: targetAddr, targetAgentId: target.agentId };
1328
1381
  }
1329
1382
  // ════════════════════════════════════════════════════════
1330
- // Reputation (AgentReputation contract)
1383
+ // Reputation (Agether8004Scorer contract)
1331
1384
  // ════════════════════════════════════════════════════════
1332
1385
  async getCreditScore() {
1333
1386
  if (!this.agentId) throw new AgetherError("agentId not set", "NO_AGENT_ID");
1334
- return this.agentReputation.getCreditScore(BigInt(this.agentId));
1387
+ return this.agether8004Scorer.getCreditScore(BigInt(this.agentId));
1335
1388
  }
1336
1389
  async getAttestation() {
1337
1390
  if (!this.agentId) throw new AgetherError("agentId not set", "NO_AGENT_ID");
1338
- const att = await this.agentReputation.getAttestation(BigInt(this.agentId));
1391
+ const att = await this.agether8004Scorer.getAttestation(BigInt(this.agentId));
1339
1392
  return { score: att.score, timestamp: att.timestamp, signer: att.signer };
1340
1393
  }
1341
1394
  async isEligible(minScore = 500n) {
1342
1395
  if (!this.agentId) throw new AgetherError("agentId not set", "NO_AGENT_ID");
1343
- const [eligible, currentScore] = await this.agentReputation.isEligible(BigInt(this.agentId), minScore);
1396
+ const [eligible, currentScore] = await this.agether8004Scorer.isEligible(BigInt(this.agentId), minScore);
1344
1397
  return { eligible, currentScore };
1345
1398
  }
1346
1399
  async isScoreFresh() {
1347
1400
  if (!this.agentId) throw new AgetherError("agentId not set", "NO_AGENT_ID");
1348
- const [fresh, age] = await this.agentReputation.isScoreFresh(BigInt(this.agentId));
1401
+ const [fresh, age] = await this.agether8004Scorer.isScoreFresh(BigInt(this.agentId));
1349
1402
  return { fresh, age };
1350
1403
  }
1351
1404
  // ════════════════════════════════════════════════════════
@@ -1367,8 +1420,10 @@ var MorphoClient = class {
1367
1420
  _refreshSigner() {
1368
1421
  if (this._useExternalSigner) {
1369
1422
  const addrs = this.config.contracts;
1370
- this.accountFactory = new Contract2(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this._signer);
1371
- this.agentReputation = new Contract2(addrs.agentReputation, AGENT_REPUTATION_ABI, this._signer);
1423
+ this.agether4337Factory = new Contract2(addrs.agether4337Factory, ACCOUNT_FACTORY_ABI, this._signer);
1424
+ this.entryPoint = new Contract2(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
1425
+ this.validationModule = new Contract2(addrs.erc8004ValidationModule, ERC8004_VALIDATION_MODULE_ABI, this.provider);
1426
+ this.agether8004Scorer = new Contract2(addrs.agether8004Scorer, AGENT_REPUTATION_ABI, this._signer);
1372
1427
  this.identityRegistry = new Contract2(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this._signer);
1373
1428
  } else {
1374
1429
  this.provider = new ethers2.JsonRpcProvider(this._rpcUrl);
@@ -1376,57 +1431,87 @@ var MorphoClient = class {
1376
1431
  this._signer = wallet;
1377
1432
  this._eoaAddress = wallet.address;
1378
1433
  const addrs = this.config.contracts;
1379
- this.accountFactory = new Contract2(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this._signer);
1380
- this.agentReputation = new Contract2(addrs.agentReputation, AGENT_REPUTATION_ABI, this._signer);
1434
+ this.agether4337Factory = new Contract2(addrs.agether4337Factory, ACCOUNT_FACTORY_ABI, this._signer);
1435
+ this.entryPoint = new Contract2(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
1436
+ this.validationModule = new Contract2(addrs.erc8004ValidationModule, ERC8004_VALIDATION_MODULE_ABI, this.provider);
1437
+ this.agether8004Scorer = new Contract2(addrs.agether8004Scorer, AGENT_REPUTATION_ABI, this._signer);
1381
1438
  this.identityRegistry = new Contract2(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this._signer);
1382
1439
  }
1383
1440
  }
1441
+ // ────────────────────────────────────────────────────────────
1442
+ // ERC-4337 UserOp helpers (Safe + Safe7579 + EntryPoint v0.7)
1443
+ // ────────────────────────────────────────────────────────────
1384
1444
  /**
1385
- * Execute a single call via AgentAccount.execute (ERC-7579 single mode).
1445
+ * Pack two uint128 values into a single bytes32:
1446
+ * bytes32 = (hi << 128) | lo
1447
+ */
1448
+ _packUint128(hi, lo) {
1449
+ return ethers2.zeroPadValue(ethers2.toBeHex(hi << 128n | lo), 32);
1450
+ }
1451
+ /**
1452
+ * Build, sign and submit a PackedUserOperation through EntryPoint.handleOps.
1453
+ *
1454
+ * @param callData – the ABI-encoded calldata for the Safe7579 account
1455
+ * (e.g. `execute(mode, executionCalldata)`)
1456
+ * @returns the transaction receipt of the handleOps call
1457
+ */
1458
+ async _submitUserOp(callData) {
1459
+ const sender = await this.getAccountAddress();
1460
+ const nonce = await this.entryPoint.getNonce(sender, 0);
1461
+ const feeData = await this.provider.getFeeData();
1462
+ const maxFeePerGas = feeData.maxFeePerGas ?? ethers2.parseUnits("0.5", "gwei");
1463
+ const maxPriorityFeePerGas = feeData.maxPriorityFeePerGas ?? ethers2.parseUnits("0.1", "gwei");
1464
+ const verificationGasLimit = 500000n;
1465
+ const callGasLimit = 800000n;
1466
+ const preVerificationGas = 100000n;
1467
+ const accountGasLimits = this._packUint128(verificationGasLimit, callGasLimit);
1468
+ const gasFees = this._packUint128(maxPriorityFeePerGas, maxFeePerGas);
1469
+ const userOp = {
1470
+ sender,
1471
+ nonce,
1472
+ initCode: "0x",
1473
+ callData,
1474
+ accountGasLimits,
1475
+ preVerificationGas,
1476
+ gasFees,
1477
+ paymasterAndData: "0x",
1478
+ signature: "0x"
1479
+ // placeholder — replaced after signing
1480
+ };
1481
+ const userOpHash = await this.entryPoint.getUserOpHash(userOp);
1482
+ const signature = await this._signer.signMessage(ethers2.getBytes(userOpHash));
1483
+ userOp.signature = signature;
1484
+ const tx = await this.entryPoint.handleOps([userOp], await this.getSignerAddress());
1485
+ const receipt = await tx.wait();
1486
+ this._refreshSigner();
1487
+ return receipt;
1488
+ }
1489
+ /**
1490
+ * Execute a single call via Safe7579 account (ERC-7579 single mode)
1491
+ * through an ERC-4337 UserOperation.
1386
1492
  */
1387
1493
  async exec(target, data, value = 0n) {
1388
- const acctAddr = await this.getAccountAddress();
1389
- const account = new Contract2(acctAddr, AGENT_ACCOUNT_ABI, this._signer);
1390
1494
  const executionCalldata = ethers2.AbiCoder.defaultAbiCoder().encode(
1391
1495
  ["address", "uint256", "bytes"],
1392
1496
  [target, value, data]
1393
1497
  );
1394
- let gasLimit;
1395
- try {
1396
- const estimate = await account.execute.estimateGas(MODE_SINGLE, executionCalldata);
1397
- gasLimit = estimate * 130n / 100n;
1398
- } catch (e) {
1399
- console.warn("[agether] exec gas estimation failed, using default 500k:", e instanceof Error ? e.message : e);
1400
- gasLimit = 500000n;
1401
- }
1402
- const tx = await account.execute(MODE_SINGLE, executionCalldata, { gasLimit });
1403
- const receipt = await tx.wait();
1404
- this._refreshSigner();
1405
- return receipt;
1498
+ const safe7579Iface = new ethers2.Interface(SAFE7579_ACCOUNT_ABI);
1499
+ const callData = safe7579Iface.encodeFunctionData("execute", [MODE_SINGLE, executionCalldata]);
1500
+ return this._submitUserOp(callData);
1406
1501
  }
1407
1502
  /**
1408
- * Execute multiple calls via AgentAccount.execute (ERC-7579 batch mode).
1503
+ * Execute multiple calls via Safe7579 account (ERC-7579 batch mode)
1504
+ * through an ERC-4337 UserOperation.
1409
1505
  */
1410
1506
  async batch(targets, values, datas) {
1411
- const acctAddr = await this.getAccountAddress();
1412
- const account = new Contract2(acctAddr, AGENT_ACCOUNT_ABI, this._signer);
1413
1507
  const executions = targets.map((t, i) => [t, values[i], datas[i]]);
1414
1508
  const executionCalldata = ethers2.AbiCoder.defaultAbiCoder().encode(
1415
1509
  ["(address,uint256,bytes)[]"],
1416
1510
  [executions]
1417
1511
  );
1418
- let gasLimit;
1419
- try {
1420
- const estimate = await account.execute.estimateGas(MODE_BATCH, executionCalldata);
1421
- gasLimit = estimate * 130n / 100n;
1422
- } catch (e) {
1423
- console.warn("[agether] batch gas estimation failed, using default 800k:", e instanceof Error ? e.message : e);
1424
- gasLimit = 800000n;
1425
- }
1426
- const tx = await account.execute(MODE_BATCH, executionCalldata, { gasLimit });
1427
- const receipt = await tx.wait();
1428
- this._refreshSigner();
1429
- return receipt;
1512
+ const safe7579Iface = new ethers2.Interface(SAFE7579_ACCOUNT_ABI);
1513
+ const callData = safe7579Iface.encodeFunctionData("execute", [MODE_BATCH, executionCalldata]);
1514
+ return this._submitUserOp(callData);
1430
1515
  }
1431
1516
  /** Convert MorphoMarketParams to Solidity tuple. */
1432
1517
  _toTuple(p) {
@@ -1793,14 +1878,14 @@ var ScoringClient = class {
1793
1878
  }
1794
1879
  }
1795
1880
  // ════════════════════════════════════════════════════════
1796
- // Score (x402-gated — computes & submits on-chain)
1881
+ // Score (x402-gated — computes & submits onchain)
1797
1882
  // ════════════════════════════════════════════════════════
1798
1883
  /**
1799
1884
  * Request a fresh score computation.
1800
1885
  *
1801
1886
  * This is x402-gated: the backend returns 402, the X402Client
1802
1887
  * signs an EIP-3009 payment, and the backend computes + submits
1803
- * the score on-chain via AgentReputation.submitScore().
1888
+ * the score onchain via AgentReputation.submitScore().
1804
1889
  *
1805
1890
  * Returns the ScoreResult with breakdown and txHash.
1806
1891
  */
@@ -1824,10 +1909,10 @@ var ScoringClient = class {
1824
1909
  return result.data;
1825
1910
  }
1826
1911
  // ════════════════════════════════════════════════════════
1827
- // Current Score (free — reads on-chain)
1912
+ // Current Score (free — reads onchain)
1828
1913
  // ════════════════════════════════════════════════════════
1829
1914
  /**
1830
- * Get the current on-chain score (free, no payment required).
1915
+ * Get the current onchain score (free, no payment required).
1831
1916
  */
1832
1917
  async getCurrentScore(agentId) {
1833
1918
  const response = await this.client.get(`/score/${agentId.toString()}/current`);
@@ -1976,7 +2061,7 @@ var AgentIdentityClient = class {
1976
2061
  return { ...result, existing: false };
1977
2062
  }
1978
2063
  /**
1979
- * Register agent with URI and on-chain metadata
2064
+ * Register agent with URI and onchain metadata
1980
2065
  */
1981
2066
  async registerWithMetadata(agentURI, metadata) {
1982
2067
  const metadataEntries = metadata.map((m) => ({
@@ -2012,7 +2097,7 @@ var AgentIdentityClient = class {
2012
2097
  return receipt.hash;
2013
2098
  }
2014
2099
  /**
2015
- * Set on-chain metadata (key-value)
2100
+ * Set onchain metadata (key-value)
2016
2101
  */
2017
2102
  async setMetadata(agentId, key, value) {
2018
2103
  const tx = await this.identityRegistry.setMetadata(
@@ -2024,7 +2109,7 @@ var AgentIdentityClient = class {
2024
2109
  return receipt.hash;
2025
2110
  }
2026
2111
  /**
2027
- * Get on-chain metadata
2112
+ * Get onchain metadata
2028
2113
  */
2029
2114
  async getMetadata(agentId, key) {
2030
2115
  const value = await this.identityRegistry.getMetadata(agentId, key);
@@ -2252,19 +2337,26 @@ function rateToBps(rate) {
2252
2337
  }
2253
2338
  export {
2254
2339
  ACCOUNT_FACTORY_ABI,
2255
- AGENT_ACCOUNT_ABI,
2256
2340
  AGENT_REPUTATION_ABI,
2341
+ AGETHER_4337_FACTORY_ABI,
2342
+ AGETHER_8004_SCORER_ABI,
2343
+ AGETHER_8004_VALIDATION_MODULE_ABI,
2344
+ AGETHER_HOOK_MULTIPLEXER_ABI,
2257
2345
  AgentIdentityClient,
2258
2346
  AgentNotApprovedError,
2259
2347
  AgetherClient,
2260
2348
  AgetherError,
2261
2349
  ChainId,
2350
+ ENTRYPOINT_V07_ABI,
2262
2351
  ERC20_ABI,
2352
+ ERC8004_VALIDATION_MODULE_ABI,
2353
+ HOOK_MULTIPLEXER_ABI,
2263
2354
  IDENTITY_REGISTRY_ABI,
2264
2355
  InsufficientBalanceError,
2265
- KYA_HOOK_ABI,
2266
2356
  MORPHO_BLUE_ABI,
2267
2357
  MorphoClient,
2358
+ SAFE7579_ACCOUNT_ABI,
2359
+ SAFE_AGENT_FACTORY_ABI,
2268
2360
  ScoringClient,
2269
2361
  ScoringRejectedError,
2270
2362
  VALIDATION_REGISTRY_ABI,