@agether/sdk 1.11.2 → 2.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/index.js CHANGED
@@ -31,19 +31,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  ACCOUNT_FACTORY_ABI: () => ACCOUNT_FACTORY_ABI,
34
- AGENT_ACCOUNT_ABI: () => AGENT_ACCOUNT_ABI,
35
34
  AGENT_REPUTATION_ABI: () => AGENT_REPUTATION_ABI,
36
35
  AgentIdentityClient: () => AgentIdentityClient,
37
36
  AgentNotApprovedError: () => AgentNotApprovedError,
38
37
  AgetherClient: () => AgetherClient,
39
38
  AgetherError: () => AgetherError,
40
39
  ChainId: () => ChainId,
40
+ ENTRYPOINT_V07_ABI: () => ENTRYPOINT_V07_ABI,
41
41
  ERC20_ABI: () => ERC20_ABI,
42
+ ERC8004_VALIDATION_MODULE_ABI: () => ERC8004_VALIDATION_MODULE_ABI,
43
+ HOOK_MULTIPLEXER_ABI: () => HOOK_MULTIPLEXER_ABI,
42
44
  IDENTITY_REGISTRY_ABI: () => IDENTITY_REGISTRY_ABI,
43
45
  InsufficientBalanceError: () => InsufficientBalanceError,
44
- KYA_HOOK_ABI: () => KYA_HOOK_ABI,
45
46
  MORPHO_BLUE_ABI: () => MORPHO_BLUE_ABI,
46
47
  MorphoClient: () => MorphoClient,
48
+ SAFE7579_ACCOUNT_ABI: () => SAFE7579_ACCOUNT_ABI,
49
+ SAFE_AGENT_FACTORY_ABI: () => SAFE_AGENT_FACTORY_ABI,
47
50
  ScoringClient: () => ScoringClient,
48
51
  ScoringRejectedError: () => ScoringRejectedError,
49
52
  VALIDATION_REGISTRY_ABI: () => VALIDATION_REGISTRY_ABI,
@@ -120,38 +123,41 @@ var IDENTITY_REGISTRY_ABI = [
120
123
  "function register() returns (uint256 agentId)",
121
124
  "event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)"
122
125
  ];
123
- var ACCOUNT_FACTORY_ABI = [
126
+ var SAFE_AGENT_FACTORY_ABI = [
124
127
  "function getAccount(uint256 agentId) view returns (address)",
125
128
  "function accountExists(uint256 agentId) view returns (bool)",
126
- "function predictAddress(uint256 agentId) view returns (address)",
127
129
  "function totalAccounts() view returns (uint256)",
128
130
  "function getAgentId(address account) view returns (uint256)",
129
- "function createAccount(uint256 agentId) returns (address account)",
130
- "function protocolHook() view returns (address)",
131
+ "function getAgentIdByIndex(uint256 index) view returns (uint256)",
132
+ "function getAllAgentIds() view returns (uint256[])",
133
+ "function createAccount(uint256 agentId) returns (address safeAccount)",
131
134
  "function identityRegistry() view returns (address)",
132
- "event AccountCreated(uint256 indexed agentId, address indexed account, address indexed owner)"
135
+ "function validationModule() view returns (address)",
136
+ "function hookMultiplexer() view returns (address)",
137
+ "function safeSingleton() view returns (address)",
138
+ "function safe7579() view returns (address)",
139
+ "function bootstrap() view returns (address)",
140
+ "function SENTINEL_OWNER() view returns (address)",
141
+ "event AccountCreated(uint256 indexed agentId, address indexed safeAccount, address indexed owner)"
133
142
  ];
134
- var AGENT_ACCOUNT_ABI = [
135
- "function agentId() view returns (uint256)",
143
+ var ACCOUNT_FACTORY_ABI = SAFE_AGENT_FACTORY_ABI;
144
+ var ERC8004_VALIDATION_MODULE_ABI = [
145
+ // View
146
+ "function getConfig(address account) view returns (address registry, uint256 agentId)",
147
+ "function getOwner(address account) view returns (address)",
148
+ "function isInstalled(address account) view returns (bool)",
149
+ "function isKYAApproved(address account) view returns (bool)",
150
+ "function validationRegistry() view returns (address)",
136
151
  "function owner() view returns (address)",
137
- "function factory() view returns (address)",
138
- "function identityRegistry() view returns (address)",
139
- "function balanceOf(address token) view returns (uint256)",
140
- "function ethBalance() view returns (uint256)",
141
- // ERC-7579 execution
142
- "function execute(bytes32 mode, bytes executionCalldata) payable",
143
- "function executeFromExecutor(bytes32 mode, bytes executionCalldata) payable returns (bytes[])",
144
- // ERC-7579 module management
145
- "function installModule(uint256 moduleTypeId, address module, bytes initData) payable",
146
- "function uninstallModule(uint256 moduleTypeId, address module, bytes deInitData) payable",
147
- "function isModuleInstalled(uint256 moduleTypeId, address module, bytes additionalContext) view returns (bool)",
148
- "function hook() view returns (address)",
149
- // Funding (direct, no execution needed)
150
- "function fund(address token, uint256 amount)",
151
- "function withdraw(address token, uint256 amount, address to)",
152
- "function withdrawETH(uint256 amount, address to)",
153
- // EIP-1271
154
- "function isValidSignature(bytes32 hash, bytes signature) view returns (bytes4)"
152
+ // Admin (via TimelockController)
153
+ "function setValidationRegistry(address registry_)"
154
+ ];
155
+ var HOOK_MULTIPLEXER_ABI = [
156
+ "function getHooks() view returns (address[])",
157
+ "function hookCount() view returns (uint256)",
158
+ "function owner() view returns (address)",
159
+ "function addHook(address hook)",
160
+ "function removeHook(address hook)"
155
161
  ];
156
162
  var AGENT_REPUTATION_ABI = [
157
163
  "function getCreditScore(uint256 agentId) view returns (uint256)",
@@ -197,57 +203,113 @@ var ERC20_ABI = [
197
203
  "function symbol() view returns (string)",
198
204
  "function name() view returns (string)"
199
205
  ];
200
- var KYA_HOOK_ABI = [
201
- "function validationRegistry() view returns (address)",
202
- "function setValidationRegistry(address newRegistry)"
206
+ var ENTRYPOINT_V07_ABI = [
207
+ "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)",
208
+ "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)",
209
+ "function getNonce(address sender, uint192 key) view returns (uint256 nonce)",
210
+ "function balanceOf(address account) view returns (uint256)",
211
+ "function depositTo(address account) payable",
212
+ "event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed)"
213
+ ];
214
+ var SAFE7579_ACCOUNT_ABI = [
215
+ // ERC-7579 execution (called via UserOp through Safe7579 fallback)
216
+ "function execute(bytes32 mode, bytes executionCalldata) payable",
217
+ "function executeFromExecutor(bytes32 mode, bytes executionCalldata) payable returns (bytes[])",
218
+ // ERC-7579 module queries
219
+ "function isModuleInstalled(uint256 moduleTypeId, address module, bytes additionalContext) view returns (bool)",
220
+ // EIP-1271
221
+ "function isValidSignature(bytes32 hash, bytes signature) view returns (bytes4)"
203
222
  ];
204
223
 
205
224
  // src/utils/config.ts
225
+ var ZERO = "0x0000000000000000000000000000000000000000";
226
+ var ENTRYPOINT_V07 = "0x0000000071727De22E5E9d8BAf0edAc6f37da032";
227
+ var ERC8004_IDENTITY_REGISTRY = "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432";
228
+ var ERC8004_IDENTITY_REGISTRY_TESTNET = "0x8004A818BFB912233c491871b3d84c89A494BD9e";
229
+ var MORPHO_BLUE = "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb";
230
+ var SAFE_SINGLETON = "0x41675C099F32341bf84BFc5382aF534df5C7461a";
231
+ var SAFE_PROXY_FACTORY = "0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67";
232
+ var SAFE7579 = "0x7579EE8307284F293B1927136486880611F20002";
206
233
  var CONTRACT_ADDRESSES = {
207
234
  [1 /* Ethereum */]: {
208
- accountFactory: "0x0000000000000000000000000000000000000000",
209
- validationRegistry: "0x0000000000000000000000000000000000000000",
210
- agentReputation: "0x0000000000000000000000000000000000000000",
211
- kyaHook: "0x0000000000000000000000000000000000000000",
235
+ safeSingleton: SAFE_SINGLETON,
236
+ safeProxyFactory: SAFE_PROXY_FACTORY,
237
+ safe7579: SAFE7579,
238
+ entryPoint: ENTRYPOINT_V07,
239
+ safeAgentFactory: ZERO,
240
+ safe7579Bootstrap: ZERO,
241
+ erc8004ValidationModule: ZERO,
242
+ hookMultiplexer: ZERO,
243
+ validationRegistry: ZERO,
244
+ agentReputation: ZERO,
245
+ timelockController: ZERO,
212
246
  usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
213
- identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
214
- morphoBlue: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb"
247
+ identityRegistry: ERC8004_IDENTITY_REGISTRY,
248
+ morphoBlue: MORPHO_BLUE
215
249
  },
216
250
  [8453 /* Base */]: {
217
- accountFactory: "0x89a8758E60A56EcB47247D92E05447eFd450d6Bf",
218
- validationRegistry: "0x6f76cF69B71Dc5F9A414BCEe4583b12738E47985",
219
- agentReputation: "0xe88f3419a2dbac70e3aF6E487b0C63e8301C6A87",
220
- kyaHook: "0x28e50Aa9eD517E369b2806928709B44062aD9821",
251
+ safeSingleton: SAFE_SINGLETON,
252
+ safeProxyFactory: SAFE_PROXY_FACTORY,
253
+ safe7579: SAFE7579,
254
+ entryPoint: ENTRYPOINT_V07,
255
+ safeAgentFactory: "0xB0A88ffe28491E793F7706829278f20d724947d1",
256
+ safe7579Bootstrap: "0x72A636bc23B2644138489c3bBE3B05a0a7184b33",
257
+ erc8004ValidationModule: "0x49e27A6B4d012B87271897b51d0296ABcFCb0BBd",
258
+ hookMultiplexer: "0x12c77f17F91f06a11C2C34C618ce9d78f9a34541",
259
+ validationRegistry: "0x88E21e8883c093E4c8d0d0cE68f1c93Cf6190f51",
260
+ agentReputation: "0x4C2d42cbD35f6541f0902499CFEC27C1Cf5683E3",
261
+ timelockController: "0x0517b4f73b61774C88A2B1c5745141315E831015",
221
262
  usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
222
- identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
223
- morphoBlue: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb"
263
+ identityRegistry: ERC8004_IDENTITY_REGISTRY,
264
+ morphoBlue: MORPHO_BLUE
224
265
  },
225
266
  [84532 /* BaseSepolia */]: {
226
- accountFactory: "0x0000000000000000000000000000000000000000",
227
- validationRegistry: "0x0000000000000000000000000000000000000000",
228
- agentReputation: "0x0000000000000000000000000000000000000000",
229
- kyaHook: "0x0000000000000000000000000000000000000000",
267
+ safeSingleton: SAFE_SINGLETON,
268
+ safeProxyFactory: SAFE_PROXY_FACTORY,
269
+ safe7579: SAFE7579,
270
+ entryPoint: ENTRYPOINT_V07,
271
+ safeAgentFactory: ZERO,
272
+ safe7579Bootstrap: ZERO,
273
+ erc8004ValidationModule: ZERO,
274
+ hookMultiplexer: ZERO,
275
+ validationRegistry: ZERO,
276
+ agentReputation: ZERO,
277
+ timelockController: ZERO,
230
278
  usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
231
- identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
232
- morphoBlue: "0x0000000000000000000000000000000000000000"
279
+ identityRegistry: ERC8004_IDENTITY_REGISTRY_TESTNET,
280
+ morphoBlue: ZERO
233
281
  },
234
282
  [11155111 /* Sepolia */]: {
235
- accountFactory: "0x0000000000000000000000000000000000000000",
236
- validationRegistry: "0x0000000000000000000000000000000000000000",
237
- agentReputation: "0x0000000000000000000000000000000000000000",
238
- kyaHook: "0x0000000000000000000000000000000000000000",
283
+ safeSingleton: SAFE_SINGLETON,
284
+ safeProxyFactory: SAFE_PROXY_FACTORY,
285
+ safe7579: SAFE7579,
286
+ entryPoint: ENTRYPOINT_V07,
287
+ safeAgentFactory: ZERO,
288
+ safe7579Bootstrap: ZERO,
289
+ erc8004ValidationModule: ZERO,
290
+ hookMultiplexer: ZERO,
291
+ validationRegistry: ZERO,
292
+ agentReputation: ZERO,
293
+ timelockController: ZERO,
239
294
  usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
240
- identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
241
- morphoBlue: "0x0000000000000000000000000000000000000000"
295
+ identityRegistry: ERC8004_IDENTITY_REGISTRY_TESTNET,
296
+ morphoBlue: ZERO
242
297
  },
243
298
  [31337 /* Hardhat */]: {
244
- accountFactory: "0x0000000000000000000000000000000000000000",
245
- validationRegistry: "0x0000000000000000000000000000000000000000",
246
- agentReputation: "0x0000000000000000000000000000000000000000",
247
- kyaHook: "0x0000000000000000000000000000000000000000",
299
+ safeSingleton: SAFE_SINGLETON,
300
+ safeProxyFactory: SAFE_PROXY_FACTORY,
301
+ safe7579: SAFE7579,
302
+ entryPoint: ENTRYPOINT_V07,
303
+ safeAgentFactory: ZERO,
304
+ safe7579Bootstrap: ZERO,
305
+ erc8004ValidationModule: ZERO,
306
+ hookMultiplexer: ZERO,
307
+ validationRegistry: ZERO,
308
+ agentReputation: ZERO,
309
+ timelockController: ZERO,
248
310
  usdc: "0x56d4d6aEe0278c5Df2FA23Ecb32eC146C9446FDf",
249
- identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
250
- morphoBlue: "0x0000000000000000000000000000000000000000"
311
+ identityRegistry: ERC8004_IDENTITY_REGISTRY,
312
+ morphoBlue: ZERO
251
313
  }
252
314
  };
253
315
  var RPC_URLS = {
@@ -292,9 +354,9 @@ var AgetherClient = class _AgetherClient {
292
354
  this.agentId = options.agentId;
293
355
  const provider = options.signer.provider;
294
356
  if (!provider) throw new AgetherError("Signer must have a provider", "NO_PROVIDER");
295
- this.accountFactory = new import_ethers.Contract(
296
- options.config.contracts.accountFactory,
297
- ACCOUNT_FACTORY_ABI,
357
+ this.safeAgentFactory = new import_ethers.Contract(
358
+ options.config.contracts.safeAgentFactory,
359
+ SAFE_AGENT_FACTORY_ABI,
298
360
  options.signer
299
361
  );
300
362
  this.identityRegistry = new import_ethers.Contract(
@@ -302,16 +364,16 @@ var AgetherClient = class _AgetherClient {
302
364
  IDENTITY_REGISTRY_ABI,
303
365
  provider
304
366
  );
305
- this.validationRegistry = new import_ethers.Contract(
306
- options.config.contracts.validationRegistry,
307
- VALIDATION_REGISTRY_ABI,
308
- provider
309
- );
310
367
  this.agentReputation = new import_ethers.Contract(
311
368
  options.config.contracts.agentReputation,
312
369
  AGENT_REPUTATION_ABI,
313
370
  provider
314
371
  );
372
+ this.validationModule = new import_ethers.Contract(
373
+ options.config.contracts.erc8004ValidationModule,
374
+ ERC8004_VALIDATION_MODULE_ABI,
375
+ provider
376
+ );
315
377
  }
316
378
  // Static Factory
317
379
  static fromPrivateKey(privateKey, agentId, chainIdOrConfig) {
@@ -322,26 +384,26 @@ var AgetherClient = class _AgetherClient {
322
384
  }
323
385
  // Account Management
324
386
  async createAccount() {
325
- const tx = await this.accountFactory.createAccount(this.agentId);
387
+ const tx = await this.safeAgentFactory.createAccount(this.agentId);
326
388
  const receipt = await tx.wait();
327
389
  const event = receipt.logs.map((log) => {
328
390
  try {
329
- return this.accountFactory.interface.parseLog(log);
391
+ return this.safeAgentFactory.interface.parseLog(log);
330
392
  } catch (e) {
331
393
  console.warn("[agether] createAccount parseLog skip:", e instanceof Error ? e.message : e);
332
394
  return null;
333
395
  }
334
396
  }).find((e) => e?.name === "AccountCreated");
335
397
  if (event) {
336
- this.accountAddress = event.args.account;
398
+ this.accountAddress = event.args.safeAccount;
337
399
  } else {
338
- this.accountAddress = await this.accountFactory.getAccount(this.agentId);
400
+ this.accountAddress = await this.safeAgentFactory.getAccount(this.agentId);
339
401
  }
340
402
  return this.accountAddress;
341
403
  }
342
404
  async getAccountAddress() {
343
405
  if (this.accountAddress) return this.accountAddress;
344
- const addr = await this.accountFactory.getAccount(this.agentId);
406
+ const addr = await this.safeAgentFactory.getAccount(this.agentId);
345
407
  if (addr === import_ethers.ethers.ZeroAddress) {
346
408
  throw new AgetherError("No account found. Create one with createAccount().", "NO_ACCOUNT");
347
409
  }
@@ -349,10 +411,7 @@ var AgetherClient = class _AgetherClient {
349
411
  return addr;
350
412
  }
351
413
  async accountExists() {
352
- return this.accountFactory.accountExists(this.agentId);
353
- }
354
- async predictAddress() {
355
- return this.accountFactory.predictAddress(this.agentId);
414
+ return this.safeAgentFactory.accountExists(this.agentId);
356
415
  }
357
416
  // Balances
358
417
  async getBalances() {
@@ -374,10 +433,14 @@ var AgetherClient = class _AgetherClient {
374
433
  usdc: import_ethers.ethers.formatUnits(acctUsdc, 6)
375
434
  };
376
435
  } catch (e) {
377
- console.warn("[agether] getBalances: no AgentAccount or fetch failed:", e instanceof Error ? e.message : e);
436
+ console.warn("[agether] getBalances: no Safe account or fetch failed:", e instanceof Error ? e.message : e);
378
437
  }
379
438
  return result;
380
439
  }
440
+ /**
441
+ * Fund the Safe account with USDC from EOA.
442
+ * This is a simple ERC-20 transfer (does NOT require a UserOp).
443
+ */
381
444
  async fundAccount(usdcAmount) {
382
445
  const acctAddr = await this.getAccountAddress();
383
446
  const usdc = new import_ethers.Contract(this.config.contracts.usdc, ERC20_ABI, this.signer);
@@ -391,37 +454,30 @@ var AgetherClient = class _AgetherClient {
391
454
  gasUsed: receipt.gasUsed
392
455
  };
393
456
  }
394
- async withdrawUsdc(usdcAmount) {
395
- const acctAddr = await this.getAccountAddress();
396
- const account = new import_ethers.Contract(acctAddr, AGENT_ACCOUNT_ABI, this.signer);
397
- const amount = import_ethers.ethers.parseUnits(usdcAmount, 6);
398
- const eoaAddr = await this.signer.getAddress();
399
- const tx = await account.withdraw(this.config.contracts.usdc, amount, eoaAddr);
400
- const receipt = await tx.wait();
401
- return {
402
- txHash: receipt.hash,
403
- blockNumber: receipt.blockNumber,
404
- status: receipt.status === 1 ? "success" : "failed",
405
- gasUsed: receipt.gasUsed
406
- };
407
- }
408
- async withdrawEth(ethAmount) {
409
- const acctAddr = await this.getAccountAddress();
410
- const account = new import_ethers.Contract(acctAddr, AGENT_ACCOUNT_ABI, this.signer);
411
- const amount = import_ethers.ethers.parseEther(ethAmount);
412
- const eoaAddr = await this.signer.getAddress();
413
- const tx = await account.withdrawETH(amount, eoaAddr);
414
- const receipt = await tx.wait();
415
- return {
416
- txHash: receipt.hash,
417
- blockNumber: receipt.blockNumber,
418
- status: receipt.status === 1 ? "success" : "failed",
419
- gasUsed: receipt.gasUsed
420
- };
421
- }
422
457
  // Identity & Validation
458
+ /**
459
+ * Check if the KYA gate is active on the validation module.
460
+ * If validationRegistry is not set, all txs pass (KYA disabled).
461
+ */
462
+ async isKyaRequired() {
463
+ try {
464
+ const registryAddr = await this.validationModule.validationRegistry();
465
+ return registryAddr !== import_ethers.ethers.ZeroAddress;
466
+ } catch {
467
+ return false;
468
+ }
469
+ }
470
+ /**
471
+ * Check if this agent's code is KYA-approved.
472
+ * Uses the ERC8004ValidationModule.isKYAApproved(account) view.
473
+ */
423
474
  async isKyaApproved() {
424
- return this.validationRegistry.isAgentCodeApproved(this.agentId);
475
+ try {
476
+ const acctAddr = await this.getAccountAddress();
477
+ return this.validationModule.isKYAApproved(acctAddr);
478
+ } catch {
479
+ return false;
480
+ }
425
481
  }
426
482
  async identityExists() {
427
483
  try {
@@ -509,27 +565,24 @@ var MorphoClient = class {
509
565
  this._eoaAddress = wallet.address;
510
566
  }
511
567
  const addrs = { ...defaultCfg.contracts, ...config.contracts };
512
- this.accountFactory = new import_ethers2.Contract(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this._signer);
568
+ this.safeAgentFactory = new import_ethers2.Contract(addrs.safeAgentFactory, ACCOUNT_FACTORY_ABI, this._signer);
513
569
  this.morphoBlue = new import_ethers2.Contract(addrs.morphoBlue, MORPHO_BLUE_ABI, this.provider);
514
570
  this.agentReputation = new import_ethers2.Contract(addrs.agentReputation, AGENT_REPUTATION_ABI, this._signer);
515
571
  this.identityRegistry = new import_ethers2.Contract(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this._signer);
572
+ this.entryPoint = new import_ethers2.Contract(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
573
+ this.validationModule = new import_ethers2.Contract(addrs.erc8004ValidationModule, ERC8004_VALIDATION_MODULE_ABI, this.provider);
516
574
  }
517
575
  // ════════════════════════════════════════════════════════
518
576
  // KYA Gate Check
519
577
  // ════════════════════════════════════════════════════════
520
578
  /**
521
579
  * Check whether the KYA (Know Your Agent) code verification gate is active.
522
- * Reads the account's installed hook and checks if it has a non-zero
523
- * validationRegistry when set, the hook enforces KYA code approval.
580
+ * Reads the ERC8004ValidationModule's validationRegistry when set to
581
+ * a non-zero address, the module enforces KYA code approval.
524
582
  */
525
583
  async isKyaRequired() {
526
584
  try {
527
- const acctAddr = await this.getAccountAddress();
528
- const account = new import_ethers2.Contract(acctAddr, AGENT_ACCOUNT_ABI, this.provider);
529
- const hookAddr = await account.hook();
530
- if (hookAddr === import_ethers2.ethers.ZeroAddress) return false;
531
- const hook = new import_ethers2.Contract(hookAddr, KYA_HOOK_ABI, this.provider);
532
- const registryAddr = await hook.validationRegistry();
585
+ const registryAddr = await this.validationModule.validationRegistry();
533
586
  return registryAddr !== import_ethers2.ethers.ZeroAddress;
534
587
  } catch {
535
588
  return false;
@@ -546,7 +599,7 @@ var MorphoClient = class {
546
599
  let lastErr;
547
600
  for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
548
601
  try {
549
- const addr = await this.accountFactory.getAccount(BigInt(this.agentId));
602
+ const addr = await this.safeAgentFactory.getAccount(BigInt(this.agentId));
550
603
  if (addr === import_ethers2.ethers.ZeroAddress) {
551
604
  throw new AgetherError("No AgentAccount found. Call register() first.", "NO_ACCOUNT");
552
605
  }
@@ -624,9 +677,9 @@ var MorphoClient = class {
624
677
  async register(_name) {
625
678
  const eoaAddr = await this.getSignerAddress();
626
679
  if (this.agentId) {
627
- const exists = await this.accountFactory.accountExists(BigInt(this.agentId));
680
+ const exists = await this.safeAgentFactory.accountExists(BigInt(this.agentId));
628
681
  if (exists) {
629
- const acct = await this.accountFactory.getAccount(BigInt(this.agentId));
682
+ const acct = await this.safeAgentFactory.getAccount(BigInt(this.agentId));
630
683
  this._accountAddress = acct;
631
684
  const kyaRequired2 = await this.isKyaRequired();
632
685
  return { agentId: this.agentId, address: eoaAddr, agentAccount: acct, alreadyRegistered: true, kyaRequired: kyaRequired2 };
@@ -644,15 +697,15 @@ var MorphoClient = class {
644
697
  agentId = await this._mintNewIdentity();
645
698
  }
646
699
  this.agentId = agentId.toString();
647
- const acctExists = await this.accountFactory.accountExists(agentId);
700
+ const acctExists = await this.safeAgentFactory.accountExists(agentId);
648
701
  let txHash;
649
702
  if (!acctExists) {
650
- const tx = await this.accountFactory.createAccount(agentId);
703
+ const tx = await this.safeAgentFactory.createAccount(agentId);
651
704
  const receipt = await tx.wait();
652
705
  this._refreshSigner();
653
706
  txHash = receipt.hash;
654
707
  }
655
- const acctAddr = await this.accountFactory.getAccount(agentId);
708
+ const acctAddr = await this.safeAgentFactory.getAccount(agentId);
656
709
  this._accountAddress = acctAddr;
657
710
  const kyaRequired = await this.isKyaRequired();
658
711
  return {
@@ -1379,7 +1432,7 @@ var MorphoClient = class {
1379
1432
  if (target.address) {
1380
1433
  targetAddr = target.address;
1381
1434
  } else if (target.agentId) {
1382
- targetAddr = await this.accountFactory.getAccount(BigInt(target.agentId));
1435
+ targetAddr = await this.safeAgentFactory.getAccount(BigInt(target.agentId));
1383
1436
  if (targetAddr === import_ethers2.ethers.ZeroAddress) throw new AgetherError("Target agent has no account", "NO_ACCOUNT");
1384
1437
  } else {
1385
1438
  throw new AgetherError("Provide agentId or address", "INVALID_TARGET");
@@ -1432,7 +1485,9 @@ var MorphoClient = class {
1432
1485
  _refreshSigner() {
1433
1486
  if (this._useExternalSigner) {
1434
1487
  const addrs = this.config.contracts;
1435
- this.accountFactory = new import_ethers2.Contract(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this._signer);
1488
+ this.safeAgentFactory = new import_ethers2.Contract(addrs.safeAgentFactory, ACCOUNT_FACTORY_ABI, this._signer);
1489
+ this.entryPoint = new import_ethers2.Contract(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
1490
+ this.validationModule = new import_ethers2.Contract(addrs.erc8004ValidationModule, ERC8004_VALIDATION_MODULE_ABI, this.provider);
1436
1491
  this.agentReputation = new import_ethers2.Contract(addrs.agentReputation, AGENT_REPUTATION_ABI, this._signer);
1437
1492
  this.identityRegistry = new import_ethers2.Contract(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this._signer);
1438
1493
  } else {
@@ -1441,57 +1496,87 @@ var MorphoClient = class {
1441
1496
  this._signer = wallet;
1442
1497
  this._eoaAddress = wallet.address;
1443
1498
  const addrs = this.config.contracts;
1444
- this.accountFactory = new import_ethers2.Contract(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this._signer);
1499
+ this.safeAgentFactory = new import_ethers2.Contract(addrs.safeAgentFactory, ACCOUNT_FACTORY_ABI, this._signer);
1500
+ this.entryPoint = new import_ethers2.Contract(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
1501
+ this.validationModule = new import_ethers2.Contract(addrs.erc8004ValidationModule, ERC8004_VALIDATION_MODULE_ABI, this.provider);
1445
1502
  this.agentReputation = new import_ethers2.Contract(addrs.agentReputation, AGENT_REPUTATION_ABI, this._signer);
1446
1503
  this.identityRegistry = new import_ethers2.Contract(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this._signer);
1447
1504
  }
1448
1505
  }
1506
+ // ────────────────────────────────────────────────────────────
1507
+ // ERC-4337 UserOp helpers (Safe + Safe7579 + EntryPoint v0.7)
1508
+ // ────────────────────────────────────────────────────────────
1449
1509
  /**
1450
- * Execute a single call via AgentAccount.execute (ERC-7579 single mode).
1510
+ * Pack two uint128 values into a single bytes32:
1511
+ * bytes32 = (hi << 128) | lo
1512
+ */
1513
+ _packUint128(hi, lo) {
1514
+ return import_ethers2.ethers.zeroPadValue(import_ethers2.ethers.toBeHex(hi << 128n | lo), 32);
1515
+ }
1516
+ /**
1517
+ * Build, sign and submit a PackedUserOperation through EntryPoint.handleOps.
1518
+ *
1519
+ * @param callData – the ABI-encoded calldata for the Safe7579 account
1520
+ * (e.g. `execute(mode, executionCalldata)`)
1521
+ * @returns the transaction receipt of the handleOps call
1522
+ */
1523
+ async _submitUserOp(callData) {
1524
+ const sender = await this.getAccountAddress();
1525
+ const nonce = await this.entryPoint.getNonce(sender, 0);
1526
+ const feeData = await this.provider.getFeeData();
1527
+ const maxFeePerGas = feeData.maxFeePerGas ?? import_ethers2.ethers.parseUnits("0.5", "gwei");
1528
+ const maxPriorityFeePerGas = feeData.maxPriorityFeePerGas ?? import_ethers2.ethers.parseUnits("0.1", "gwei");
1529
+ const verificationGasLimit = 500000n;
1530
+ const callGasLimit = 800000n;
1531
+ const preVerificationGas = 100000n;
1532
+ const accountGasLimits = this._packUint128(verificationGasLimit, callGasLimit);
1533
+ const gasFees = this._packUint128(maxPriorityFeePerGas, maxFeePerGas);
1534
+ const userOp = {
1535
+ sender,
1536
+ nonce,
1537
+ initCode: "0x",
1538
+ callData,
1539
+ accountGasLimits,
1540
+ preVerificationGas,
1541
+ gasFees,
1542
+ paymasterAndData: "0x",
1543
+ signature: "0x"
1544
+ // placeholder — replaced after signing
1545
+ };
1546
+ const userOpHash = await this.entryPoint.getUserOpHash(userOp);
1547
+ const signature = await this._signer.signMessage(import_ethers2.ethers.getBytes(userOpHash));
1548
+ userOp.signature = signature;
1549
+ const tx = await this.entryPoint.handleOps([userOp], await this.getSignerAddress());
1550
+ const receipt = await tx.wait();
1551
+ this._refreshSigner();
1552
+ return receipt;
1553
+ }
1554
+ /**
1555
+ * Execute a single call via Safe7579 account (ERC-7579 single mode)
1556
+ * through an ERC-4337 UserOperation.
1451
1557
  */
1452
1558
  async exec(target, data, value = 0n) {
1453
- const acctAddr = await this.getAccountAddress();
1454
- const account = new import_ethers2.Contract(acctAddr, AGENT_ACCOUNT_ABI, this._signer);
1455
1559
  const executionCalldata = import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
1456
1560
  ["address", "uint256", "bytes"],
1457
1561
  [target, value, data]
1458
1562
  );
1459
- let gasLimit;
1460
- try {
1461
- const estimate = await account.execute.estimateGas(MODE_SINGLE, executionCalldata);
1462
- gasLimit = estimate * 130n / 100n;
1463
- } catch (e) {
1464
- console.warn("[agether] exec gas estimation failed, using default 500k:", e instanceof Error ? e.message : e);
1465
- gasLimit = 500000n;
1466
- }
1467
- const tx = await account.execute(MODE_SINGLE, executionCalldata, { gasLimit });
1468
- const receipt = await tx.wait();
1469
- this._refreshSigner();
1470
- return receipt;
1563
+ const safe7579Iface = new import_ethers2.ethers.Interface(SAFE7579_ACCOUNT_ABI);
1564
+ const callData = safe7579Iface.encodeFunctionData("execute", [MODE_SINGLE, executionCalldata]);
1565
+ return this._submitUserOp(callData);
1471
1566
  }
1472
1567
  /**
1473
- * Execute multiple calls via AgentAccount.execute (ERC-7579 batch mode).
1568
+ * Execute multiple calls via Safe7579 account (ERC-7579 batch mode)
1569
+ * through an ERC-4337 UserOperation.
1474
1570
  */
1475
1571
  async batch(targets, values, datas) {
1476
- const acctAddr = await this.getAccountAddress();
1477
- const account = new import_ethers2.Contract(acctAddr, AGENT_ACCOUNT_ABI, this._signer);
1478
1572
  const executions = targets.map((t, i) => [t, values[i], datas[i]]);
1479
1573
  const executionCalldata = import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
1480
1574
  ["(address,uint256,bytes)[]"],
1481
1575
  [executions]
1482
1576
  );
1483
- let gasLimit;
1484
- try {
1485
- const estimate = await account.execute.estimateGas(MODE_BATCH, executionCalldata);
1486
- gasLimit = estimate * 130n / 100n;
1487
- } catch (e) {
1488
- console.warn("[agether] batch gas estimation failed, using default 800k:", e instanceof Error ? e.message : e);
1489
- gasLimit = 800000n;
1490
- }
1491
- const tx = await account.execute(MODE_BATCH, executionCalldata, { gasLimit });
1492
- const receipt = await tx.wait();
1493
- this._refreshSigner();
1494
- return receipt;
1577
+ const safe7579Iface = new import_ethers2.ethers.Interface(SAFE7579_ACCOUNT_ABI);
1578
+ const callData = safe7579Iface.encodeFunctionData("execute", [MODE_BATCH, executionCalldata]);
1579
+ return this._submitUserOp(callData);
1495
1580
  }
1496
1581
  /** Convert MorphoMarketParams to Solidity tuple. */
1497
1582
  _toTuple(p) {
@@ -2318,19 +2403,22 @@ function rateToBps(rate) {
2318
2403
  // Annotate the CommonJS export names for ESM import in node:
2319
2404
  0 && (module.exports = {
2320
2405
  ACCOUNT_FACTORY_ABI,
2321
- AGENT_ACCOUNT_ABI,
2322
2406
  AGENT_REPUTATION_ABI,
2323
2407
  AgentIdentityClient,
2324
2408
  AgentNotApprovedError,
2325
2409
  AgetherClient,
2326
2410
  AgetherError,
2327
2411
  ChainId,
2412
+ ENTRYPOINT_V07_ABI,
2328
2413
  ERC20_ABI,
2414
+ ERC8004_VALIDATION_MODULE_ABI,
2415
+ HOOK_MULTIPLEXER_ABI,
2329
2416
  IDENTITY_REGISTRY_ABI,
2330
2417
  InsufficientBalanceError,
2331
- KYA_HOOK_ABI,
2332
2418
  MORPHO_BLUE_ABI,
2333
2419
  MorphoClient,
2420
+ SAFE7579_ACCOUNT_ABI,
2421
+ SAFE_AGENT_FACTORY_ABI,
2334
2422
  ScoringClient,
2335
2423
  ScoringRejectedError,
2336
2424
  VALIDATION_REGISTRY_ABI,