@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.mjs CHANGED
@@ -55,38 +55,41 @@ 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 SAFE_AGENT_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
+ "function SENTINEL_OWNER() view returns (address)",
73
+ "event AccountCreated(uint256 indexed agentId, address indexed safeAccount, address indexed owner)"
68
74
  ];
69
- var AGENT_ACCOUNT_ABI = [
70
- "function agentId() view returns (uint256)",
75
+ var ACCOUNT_FACTORY_ABI = SAFE_AGENT_FACTORY_ABI;
76
+ var ERC8004_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 HOOK_MULTIPLEXER_ABI = [
88
+ "function getHooks() view returns (address[])",
89
+ "function hookCount() view returns (uint256)",
90
+ "function owner() view returns (address)",
91
+ "function addHook(address hook)",
92
+ "function removeHook(address hook)"
90
93
  ];
91
94
  var AGENT_REPUTATION_ABI = [
92
95
  "function getCreditScore(uint256 agentId) view returns (uint256)",
@@ -132,57 +135,113 @@ var ERC20_ABI = [
132
135
  "function symbol() view returns (string)",
133
136
  "function name() view returns (string)"
134
137
  ];
135
- var KYA_HOOK_ABI = [
136
- "function validationRegistry() view returns (address)",
137
- "function setValidationRegistry(address newRegistry)"
138
+ var ENTRYPOINT_V07_ABI = [
139
+ "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)",
140
+ "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)",
141
+ "function getNonce(address sender, uint192 key) view returns (uint256 nonce)",
142
+ "function balanceOf(address account) view returns (uint256)",
143
+ "function depositTo(address account) payable",
144
+ "event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed)"
145
+ ];
146
+ var SAFE7579_ACCOUNT_ABI = [
147
+ // ERC-7579 execution (called via UserOp through Safe7579 fallback)
148
+ "function execute(bytes32 mode, bytes executionCalldata) payable",
149
+ "function executeFromExecutor(bytes32 mode, bytes executionCalldata) payable returns (bytes[])",
150
+ // ERC-7579 module queries
151
+ "function isModuleInstalled(uint256 moduleTypeId, address module, bytes additionalContext) view returns (bool)",
152
+ // EIP-1271
153
+ "function isValidSignature(bytes32 hash, bytes signature) view returns (bytes4)"
138
154
  ];
139
155
 
140
156
  // src/utils/config.ts
157
+ var ZERO = "0x0000000000000000000000000000000000000000";
158
+ var ENTRYPOINT_V07 = "0x0000000071727De22E5E9d8BAf0edAc6f37da032";
159
+ var ERC8004_IDENTITY_REGISTRY = "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432";
160
+ var ERC8004_IDENTITY_REGISTRY_TESTNET = "0x8004A818BFB912233c491871b3d84c89A494BD9e";
161
+ var MORPHO_BLUE = "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb";
162
+ var SAFE_SINGLETON = "0x41675C099F32341bf84BFc5382aF534df5C7461a";
163
+ var SAFE_PROXY_FACTORY = "0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67";
164
+ var SAFE7579 = "0x7579EE8307284F293B1927136486880611F20002";
141
165
  var CONTRACT_ADDRESSES = {
142
166
  [1 /* Ethereum */]: {
143
- accountFactory: "0x0000000000000000000000000000000000000000",
144
- validationRegistry: "0x0000000000000000000000000000000000000000",
145
- agentReputation: "0x0000000000000000000000000000000000000000",
146
- kyaHook: "0x0000000000000000000000000000000000000000",
167
+ safeSingleton: SAFE_SINGLETON,
168
+ safeProxyFactory: SAFE_PROXY_FACTORY,
169
+ safe7579: SAFE7579,
170
+ entryPoint: ENTRYPOINT_V07,
171
+ safeAgentFactory: ZERO,
172
+ safe7579Bootstrap: ZERO,
173
+ erc8004ValidationModule: ZERO,
174
+ hookMultiplexer: ZERO,
175
+ validationRegistry: ZERO,
176
+ agentReputation: ZERO,
177
+ timelockController: ZERO,
147
178
  usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
148
- identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
149
- morphoBlue: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb"
179
+ identityRegistry: ERC8004_IDENTITY_REGISTRY,
180
+ morphoBlue: MORPHO_BLUE
150
181
  },
151
182
  [8453 /* Base */]: {
152
- accountFactory: "0x89a8758E60A56EcB47247D92E05447eFd450d6Bf",
153
- validationRegistry: "0x6f76cF69B71Dc5F9A414BCEe4583b12738E47985",
154
- agentReputation: "0xe88f3419a2dbac70e3aF6E487b0C63e8301C6A87",
155
- kyaHook: "0x28e50Aa9eD517E369b2806928709B44062aD9821",
183
+ safeSingleton: SAFE_SINGLETON,
184
+ safeProxyFactory: SAFE_PROXY_FACTORY,
185
+ safe7579: SAFE7579,
186
+ entryPoint: ENTRYPOINT_V07,
187
+ safeAgentFactory: "0xB0A88ffe28491E793F7706829278f20d724947d1",
188
+ safe7579Bootstrap: "0x72A636bc23B2644138489c3bBE3B05a0a7184b33",
189
+ erc8004ValidationModule: "0x49e27A6B4d012B87271897b51d0296ABcFCb0BBd",
190
+ hookMultiplexer: "0x12c77f17F91f06a11C2C34C618ce9d78f9a34541",
191
+ validationRegistry: "0x88E21e8883c093E4c8d0d0cE68f1c93Cf6190f51",
192
+ agentReputation: "0x4C2d42cbD35f6541f0902499CFEC27C1Cf5683E3",
193
+ timelockController: "0x0517b4f73b61774C88A2B1c5745141315E831015",
156
194
  usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
157
- identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
158
- morphoBlue: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb"
195
+ identityRegistry: ERC8004_IDENTITY_REGISTRY,
196
+ morphoBlue: MORPHO_BLUE
159
197
  },
160
198
  [84532 /* BaseSepolia */]: {
161
- accountFactory: "0x0000000000000000000000000000000000000000",
162
- validationRegistry: "0x0000000000000000000000000000000000000000",
163
- agentReputation: "0x0000000000000000000000000000000000000000",
164
- kyaHook: "0x0000000000000000000000000000000000000000",
199
+ safeSingleton: SAFE_SINGLETON,
200
+ safeProxyFactory: SAFE_PROXY_FACTORY,
201
+ safe7579: SAFE7579,
202
+ entryPoint: ENTRYPOINT_V07,
203
+ safeAgentFactory: ZERO,
204
+ safe7579Bootstrap: ZERO,
205
+ erc8004ValidationModule: ZERO,
206
+ hookMultiplexer: ZERO,
207
+ validationRegistry: ZERO,
208
+ agentReputation: ZERO,
209
+ timelockController: ZERO,
165
210
  usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
166
- identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
167
- morphoBlue: "0x0000000000000000000000000000000000000000"
211
+ identityRegistry: ERC8004_IDENTITY_REGISTRY_TESTNET,
212
+ morphoBlue: ZERO
168
213
  },
169
214
  [11155111 /* Sepolia */]: {
170
- accountFactory: "0x0000000000000000000000000000000000000000",
171
- validationRegistry: "0x0000000000000000000000000000000000000000",
172
- agentReputation: "0x0000000000000000000000000000000000000000",
173
- kyaHook: "0x0000000000000000000000000000000000000000",
215
+ safeSingleton: SAFE_SINGLETON,
216
+ safeProxyFactory: SAFE_PROXY_FACTORY,
217
+ safe7579: SAFE7579,
218
+ entryPoint: ENTRYPOINT_V07,
219
+ safeAgentFactory: ZERO,
220
+ safe7579Bootstrap: ZERO,
221
+ erc8004ValidationModule: ZERO,
222
+ hookMultiplexer: ZERO,
223
+ validationRegistry: ZERO,
224
+ agentReputation: ZERO,
225
+ timelockController: ZERO,
174
226
  usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
175
- identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
176
- morphoBlue: "0x0000000000000000000000000000000000000000"
227
+ identityRegistry: ERC8004_IDENTITY_REGISTRY_TESTNET,
228
+ morphoBlue: ZERO
177
229
  },
178
230
  [31337 /* Hardhat */]: {
179
- accountFactory: "0x0000000000000000000000000000000000000000",
180
- validationRegistry: "0x0000000000000000000000000000000000000000",
181
- agentReputation: "0x0000000000000000000000000000000000000000",
182
- kyaHook: "0x0000000000000000000000000000000000000000",
231
+ safeSingleton: SAFE_SINGLETON,
232
+ safeProxyFactory: SAFE_PROXY_FACTORY,
233
+ safe7579: SAFE7579,
234
+ entryPoint: ENTRYPOINT_V07,
235
+ safeAgentFactory: ZERO,
236
+ safe7579Bootstrap: ZERO,
237
+ erc8004ValidationModule: ZERO,
238
+ hookMultiplexer: ZERO,
239
+ validationRegistry: ZERO,
240
+ agentReputation: ZERO,
241
+ timelockController: ZERO,
183
242
  usdc: "0x56d4d6aEe0278c5Df2FA23Ecb32eC146C9446FDf",
184
- identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
185
- morphoBlue: "0x0000000000000000000000000000000000000000"
243
+ identityRegistry: ERC8004_IDENTITY_REGISTRY,
244
+ morphoBlue: ZERO
186
245
  }
187
246
  };
188
247
  var RPC_URLS = {
@@ -227,9 +286,9 @@ var AgetherClient = class _AgetherClient {
227
286
  this.agentId = options.agentId;
228
287
  const provider = options.signer.provider;
229
288
  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,
289
+ this.safeAgentFactory = new Contract(
290
+ options.config.contracts.safeAgentFactory,
291
+ SAFE_AGENT_FACTORY_ABI,
233
292
  options.signer
234
293
  );
235
294
  this.identityRegistry = new Contract(
@@ -237,16 +296,16 @@ var AgetherClient = class _AgetherClient {
237
296
  IDENTITY_REGISTRY_ABI,
238
297
  provider
239
298
  );
240
- this.validationRegistry = new Contract(
241
- options.config.contracts.validationRegistry,
242
- VALIDATION_REGISTRY_ABI,
243
- provider
244
- );
245
299
  this.agentReputation = new Contract(
246
300
  options.config.contracts.agentReputation,
247
301
  AGENT_REPUTATION_ABI,
248
302
  provider
249
303
  );
304
+ this.validationModule = new Contract(
305
+ options.config.contracts.erc8004ValidationModule,
306
+ ERC8004_VALIDATION_MODULE_ABI,
307
+ provider
308
+ );
250
309
  }
251
310
  // Static Factory
252
311
  static fromPrivateKey(privateKey, agentId, chainIdOrConfig) {
@@ -257,26 +316,26 @@ var AgetherClient = class _AgetherClient {
257
316
  }
258
317
  // Account Management
259
318
  async createAccount() {
260
- const tx = await this.accountFactory.createAccount(this.agentId);
319
+ const tx = await this.safeAgentFactory.createAccount(this.agentId);
261
320
  const receipt = await tx.wait();
262
321
  const event = receipt.logs.map((log) => {
263
322
  try {
264
- return this.accountFactory.interface.parseLog(log);
323
+ return this.safeAgentFactory.interface.parseLog(log);
265
324
  } catch (e) {
266
325
  console.warn("[agether] createAccount parseLog skip:", e instanceof Error ? e.message : e);
267
326
  return null;
268
327
  }
269
328
  }).find((e) => e?.name === "AccountCreated");
270
329
  if (event) {
271
- this.accountAddress = event.args.account;
330
+ this.accountAddress = event.args.safeAccount;
272
331
  } else {
273
- this.accountAddress = await this.accountFactory.getAccount(this.agentId);
332
+ this.accountAddress = await this.safeAgentFactory.getAccount(this.agentId);
274
333
  }
275
334
  return this.accountAddress;
276
335
  }
277
336
  async getAccountAddress() {
278
337
  if (this.accountAddress) return this.accountAddress;
279
- const addr = await this.accountFactory.getAccount(this.agentId);
338
+ const addr = await this.safeAgentFactory.getAccount(this.agentId);
280
339
  if (addr === ethers.ZeroAddress) {
281
340
  throw new AgetherError("No account found. Create one with createAccount().", "NO_ACCOUNT");
282
341
  }
@@ -284,10 +343,7 @@ var AgetherClient = class _AgetherClient {
284
343
  return addr;
285
344
  }
286
345
  async accountExists() {
287
- return this.accountFactory.accountExists(this.agentId);
288
- }
289
- async predictAddress() {
290
- return this.accountFactory.predictAddress(this.agentId);
346
+ return this.safeAgentFactory.accountExists(this.agentId);
291
347
  }
292
348
  // Balances
293
349
  async getBalances() {
@@ -309,10 +365,14 @@ var AgetherClient = class _AgetherClient {
309
365
  usdc: ethers.formatUnits(acctUsdc, 6)
310
366
  };
311
367
  } catch (e) {
312
- console.warn("[agether] getBalances: no AgentAccount or fetch failed:", e instanceof Error ? e.message : e);
368
+ console.warn("[agether] getBalances: no Safe account or fetch failed:", e instanceof Error ? e.message : e);
313
369
  }
314
370
  return result;
315
371
  }
372
+ /**
373
+ * Fund the Safe account with USDC from EOA.
374
+ * This is a simple ERC-20 transfer (does NOT require a UserOp).
375
+ */
316
376
  async fundAccount(usdcAmount) {
317
377
  const acctAddr = await this.getAccountAddress();
318
378
  const usdc = new Contract(this.config.contracts.usdc, ERC20_ABI, this.signer);
@@ -326,37 +386,30 @@ var AgetherClient = class _AgetherClient {
326
386
  gasUsed: receipt.gasUsed
327
387
  };
328
388
  }
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
389
  // Identity & Validation
390
+ /**
391
+ * Check if the KYA gate is active on the validation module.
392
+ * If validationRegistry is not set, all txs pass (KYA disabled).
393
+ */
394
+ async isKyaRequired() {
395
+ try {
396
+ const registryAddr = await this.validationModule.validationRegistry();
397
+ return registryAddr !== ethers.ZeroAddress;
398
+ } catch {
399
+ return false;
400
+ }
401
+ }
402
+ /**
403
+ * Check if this agent's code is KYA-approved.
404
+ * Uses the ERC8004ValidationModule.isKYAApproved(account) view.
405
+ */
358
406
  async isKyaApproved() {
359
- return this.validationRegistry.isAgentCodeApproved(this.agentId);
407
+ try {
408
+ const acctAddr = await this.getAccountAddress();
409
+ return this.validationModule.isKYAApproved(acctAddr);
410
+ } catch {
411
+ return false;
412
+ }
360
413
  }
361
414
  async identityExists() {
362
415
  try {
@@ -444,27 +497,24 @@ var MorphoClient = class {
444
497
  this._eoaAddress = wallet.address;
445
498
  }
446
499
  const addrs = { ...defaultCfg.contracts, ...config.contracts };
447
- this.accountFactory = new Contract2(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this._signer);
500
+ this.safeAgentFactory = new Contract2(addrs.safeAgentFactory, ACCOUNT_FACTORY_ABI, this._signer);
448
501
  this.morphoBlue = new Contract2(addrs.morphoBlue, MORPHO_BLUE_ABI, this.provider);
449
502
  this.agentReputation = new Contract2(addrs.agentReputation, AGENT_REPUTATION_ABI, this._signer);
450
503
  this.identityRegistry = new Contract2(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this._signer);
504
+ this.entryPoint = new Contract2(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
505
+ this.validationModule = new Contract2(addrs.erc8004ValidationModule, ERC8004_VALIDATION_MODULE_ABI, this.provider);
451
506
  }
452
507
  // ════════════════════════════════════════════════════════
453
508
  // KYA Gate Check
454
509
  // ════════════════════════════════════════════════════════
455
510
  /**
456
511
  * 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.
512
+ * Reads the ERC8004ValidationModule's validationRegistry when set to
513
+ * a non-zero address, the module enforces KYA code approval.
459
514
  */
460
515
  async isKyaRequired() {
461
516
  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();
517
+ const registryAddr = await this.validationModule.validationRegistry();
468
518
  return registryAddr !== ethers2.ZeroAddress;
469
519
  } catch {
470
520
  return false;
@@ -481,7 +531,7 @@ var MorphoClient = class {
481
531
  let lastErr;
482
532
  for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
483
533
  try {
484
- const addr = await this.accountFactory.getAccount(BigInt(this.agentId));
534
+ const addr = await this.safeAgentFactory.getAccount(BigInt(this.agentId));
485
535
  if (addr === ethers2.ZeroAddress) {
486
536
  throw new AgetherError("No AgentAccount found. Call register() first.", "NO_ACCOUNT");
487
537
  }
@@ -559,9 +609,9 @@ var MorphoClient = class {
559
609
  async register(_name) {
560
610
  const eoaAddr = await this.getSignerAddress();
561
611
  if (this.agentId) {
562
- const exists = await this.accountFactory.accountExists(BigInt(this.agentId));
612
+ const exists = await this.safeAgentFactory.accountExists(BigInt(this.agentId));
563
613
  if (exists) {
564
- const acct = await this.accountFactory.getAccount(BigInt(this.agentId));
614
+ const acct = await this.safeAgentFactory.getAccount(BigInt(this.agentId));
565
615
  this._accountAddress = acct;
566
616
  const kyaRequired2 = await this.isKyaRequired();
567
617
  return { agentId: this.agentId, address: eoaAddr, agentAccount: acct, alreadyRegistered: true, kyaRequired: kyaRequired2 };
@@ -579,15 +629,15 @@ var MorphoClient = class {
579
629
  agentId = await this._mintNewIdentity();
580
630
  }
581
631
  this.agentId = agentId.toString();
582
- const acctExists = await this.accountFactory.accountExists(agentId);
632
+ const acctExists = await this.safeAgentFactory.accountExists(agentId);
583
633
  let txHash;
584
634
  if (!acctExists) {
585
- const tx = await this.accountFactory.createAccount(agentId);
635
+ const tx = await this.safeAgentFactory.createAccount(agentId);
586
636
  const receipt = await tx.wait();
587
637
  this._refreshSigner();
588
638
  txHash = receipt.hash;
589
639
  }
590
- const acctAddr = await this.accountFactory.getAccount(agentId);
640
+ const acctAddr = await this.safeAgentFactory.getAccount(agentId);
591
641
  this._accountAddress = acctAddr;
592
642
  const kyaRequired = await this.isKyaRequired();
593
643
  return {
@@ -1314,7 +1364,7 @@ var MorphoClient = class {
1314
1364
  if (target.address) {
1315
1365
  targetAddr = target.address;
1316
1366
  } else if (target.agentId) {
1317
- targetAddr = await this.accountFactory.getAccount(BigInt(target.agentId));
1367
+ targetAddr = await this.safeAgentFactory.getAccount(BigInt(target.agentId));
1318
1368
  if (targetAddr === ethers2.ZeroAddress) throw new AgetherError("Target agent has no account", "NO_ACCOUNT");
1319
1369
  } else {
1320
1370
  throw new AgetherError("Provide agentId or address", "INVALID_TARGET");
@@ -1367,7 +1417,9 @@ var MorphoClient = class {
1367
1417
  _refreshSigner() {
1368
1418
  if (this._useExternalSigner) {
1369
1419
  const addrs = this.config.contracts;
1370
- this.accountFactory = new Contract2(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this._signer);
1420
+ this.safeAgentFactory = new Contract2(addrs.safeAgentFactory, ACCOUNT_FACTORY_ABI, this._signer);
1421
+ this.entryPoint = new Contract2(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
1422
+ this.validationModule = new Contract2(addrs.erc8004ValidationModule, ERC8004_VALIDATION_MODULE_ABI, this.provider);
1371
1423
  this.agentReputation = new Contract2(addrs.agentReputation, AGENT_REPUTATION_ABI, this._signer);
1372
1424
  this.identityRegistry = new Contract2(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this._signer);
1373
1425
  } else {
@@ -1376,57 +1428,87 @@ var MorphoClient = class {
1376
1428
  this._signer = wallet;
1377
1429
  this._eoaAddress = wallet.address;
1378
1430
  const addrs = this.config.contracts;
1379
- this.accountFactory = new Contract2(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this._signer);
1431
+ this.safeAgentFactory = new Contract2(addrs.safeAgentFactory, ACCOUNT_FACTORY_ABI, this._signer);
1432
+ this.entryPoint = new Contract2(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
1433
+ this.validationModule = new Contract2(addrs.erc8004ValidationModule, ERC8004_VALIDATION_MODULE_ABI, this.provider);
1380
1434
  this.agentReputation = new Contract2(addrs.agentReputation, AGENT_REPUTATION_ABI, this._signer);
1381
1435
  this.identityRegistry = new Contract2(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this._signer);
1382
1436
  }
1383
1437
  }
1438
+ // ────────────────────────────────────────────────────────────
1439
+ // ERC-4337 UserOp helpers (Safe + Safe7579 + EntryPoint v0.7)
1440
+ // ────────────────────────────────────────────────────────────
1384
1441
  /**
1385
- * Execute a single call via AgentAccount.execute (ERC-7579 single mode).
1442
+ * Pack two uint128 values into a single bytes32:
1443
+ * bytes32 = (hi << 128) | lo
1444
+ */
1445
+ _packUint128(hi, lo) {
1446
+ return ethers2.zeroPadValue(ethers2.toBeHex(hi << 128n | lo), 32);
1447
+ }
1448
+ /**
1449
+ * Build, sign and submit a PackedUserOperation through EntryPoint.handleOps.
1450
+ *
1451
+ * @param callData – the ABI-encoded calldata for the Safe7579 account
1452
+ * (e.g. `execute(mode, executionCalldata)`)
1453
+ * @returns the transaction receipt of the handleOps call
1454
+ */
1455
+ async _submitUserOp(callData) {
1456
+ const sender = await this.getAccountAddress();
1457
+ const nonce = await this.entryPoint.getNonce(sender, 0);
1458
+ const feeData = await this.provider.getFeeData();
1459
+ const maxFeePerGas = feeData.maxFeePerGas ?? ethers2.parseUnits("0.5", "gwei");
1460
+ const maxPriorityFeePerGas = feeData.maxPriorityFeePerGas ?? ethers2.parseUnits("0.1", "gwei");
1461
+ const verificationGasLimit = 500000n;
1462
+ const callGasLimit = 800000n;
1463
+ const preVerificationGas = 100000n;
1464
+ const accountGasLimits = this._packUint128(verificationGasLimit, callGasLimit);
1465
+ const gasFees = this._packUint128(maxPriorityFeePerGas, maxFeePerGas);
1466
+ const userOp = {
1467
+ sender,
1468
+ nonce,
1469
+ initCode: "0x",
1470
+ callData,
1471
+ accountGasLimits,
1472
+ preVerificationGas,
1473
+ gasFees,
1474
+ paymasterAndData: "0x",
1475
+ signature: "0x"
1476
+ // placeholder — replaced after signing
1477
+ };
1478
+ const userOpHash = await this.entryPoint.getUserOpHash(userOp);
1479
+ const signature = await this._signer.signMessage(ethers2.getBytes(userOpHash));
1480
+ userOp.signature = signature;
1481
+ const tx = await this.entryPoint.handleOps([userOp], await this.getSignerAddress());
1482
+ const receipt = await tx.wait();
1483
+ this._refreshSigner();
1484
+ return receipt;
1485
+ }
1486
+ /**
1487
+ * Execute a single call via Safe7579 account (ERC-7579 single mode)
1488
+ * through an ERC-4337 UserOperation.
1386
1489
  */
1387
1490
  async exec(target, data, value = 0n) {
1388
- const acctAddr = await this.getAccountAddress();
1389
- const account = new Contract2(acctAddr, AGENT_ACCOUNT_ABI, this._signer);
1390
1491
  const executionCalldata = ethers2.AbiCoder.defaultAbiCoder().encode(
1391
1492
  ["address", "uint256", "bytes"],
1392
1493
  [target, value, data]
1393
1494
  );
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;
1495
+ const safe7579Iface = new ethers2.Interface(SAFE7579_ACCOUNT_ABI);
1496
+ const callData = safe7579Iface.encodeFunctionData("execute", [MODE_SINGLE, executionCalldata]);
1497
+ return this._submitUserOp(callData);
1406
1498
  }
1407
1499
  /**
1408
- * Execute multiple calls via AgentAccount.execute (ERC-7579 batch mode).
1500
+ * Execute multiple calls via Safe7579 account (ERC-7579 batch mode)
1501
+ * through an ERC-4337 UserOperation.
1409
1502
  */
1410
1503
  async batch(targets, values, datas) {
1411
- const acctAddr = await this.getAccountAddress();
1412
- const account = new Contract2(acctAddr, AGENT_ACCOUNT_ABI, this._signer);
1413
1504
  const executions = targets.map((t, i) => [t, values[i], datas[i]]);
1414
1505
  const executionCalldata = ethers2.AbiCoder.defaultAbiCoder().encode(
1415
1506
  ["(address,uint256,bytes)[]"],
1416
1507
  [executions]
1417
1508
  );
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;
1509
+ const safe7579Iface = new ethers2.Interface(SAFE7579_ACCOUNT_ABI);
1510
+ const callData = safe7579Iface.encodeFunctionData("execute", [MODE_BATCH, executionCalldata]);
1511
+ return this._submitUserOp(callData);
1430
1512
  }
1431
1513
  /** Convert MorphoMarketParams to Solidity tuple. */
1432
1514
  _toTuple(p) {
@@ -2252,19 +2334,22 @@ function rateToBps(rate) {
2252
2334
  }
2253
2335
  export {
2254
2336
  ACCOUNT_FACTORY_ABI,
2255
- AGENT_ACCOUNT_ABI,
2256
2337
  AGENT_REPUTATION_ABI,
2257
2338
  AgentIdentityClient,
2258
2339
  AgentNotApprovedError,
2259
2340
  AgetherClient,
2260
2341
  AgetherError,
2261
2342
  ChainId,
2343
+ ENTRYPOINT_V07_ABI,
2262
2344
  ERC20_ABI,
2345
+ ERC8004_VALIDATION_MODULE_ABI,
2346
+ HOOK_MULTIPLEXER_ABI,
2263
2347
  IDENTITY_REGISTRY_ABI,
2264
2348
  InsufficientBalanceError,
2265
- KYA_HOOK_ABI,
2266
2349
  MORPHO_BLUE_ABI,
2267
2350
  MorphoClient,
2351
+ SAFE7579_ACCOUNT_ABI,
2352
+ SAFE_AGENT_FACTORY_ABI,
2268
2353
  ScoringClient,
2269
2354
  ScoringRejectedError,
2270
2355
  VALIDATION_REGISTRY_ABI,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agether/sdk",
3
- "version": "1.11.2",
3
+ "version": "2.0.0",
4
4
  "description": "TypeScript SDK for Agether - autonomous credit for AI agents on Base",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",