@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/cli.js CHANGED
@@ -47,7 +47,7 @@ var init_types = __esm({
47
47
  });
48
48
 
49
49
  // src/utils/abis.ts
50
- var IDENTITY_REGISTRY_ABI, ACCOUNT_FACTORY_ABI, AGENT_ACCOUNT_ABI, AGENT_REPUTATION_ABI, MORPHO_BLUE_ABI, ERC20_ABI, KYA_HOOK_ABI;
50
+ var IDENTITY_REGISTRY_ABI, SAFE_AGENT_FACTORY_ABI, ACCOUNT_FACTORY_ABI, ERC8004_VALIDATION_MODULE_ABI, AGENT_REPUTATION_ABI, MORPHO_BLUE_ABI, ERC20_ABI, ENTRYPOINT_V07_ABI, SAFE7579_ACCOUNT_ABI;
51
51
  var init_abis = __esm({
52
52
  "src/utils/abis.ts"() {
53
53
  "use strict";
@@ -59,38 +59,34 @@ var init_abis = __esm({
59
59
  "function register() returns (uint256 agentId)",
60
60
  "event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)"
61
61
  ];
62
- ACCOUNT_FACTORY_ABI = [
62
+ SAFE_AGENT_FACTORY_ABI = [
63
63
  "function getAccount(uint256 agentId) view returns (address)",
64
64
  "function accountExists(uint256 agentId) view returns (bool)",
65
- "function predictAddress(uint256 agentId) view returns (address)",
66
65
  "function totalAccounts() view returns (uint256)",
67
66
  "function getAgentId(address account) view returns (uint256)",
68
- "function createAccount(uint256 agentId) returns (address account)",
69
- "function protocolHook() view returns (address)",
67
+ "function getAgentIdByIndex(uint256 index) view returns (uint256)",
68
+ "function getAllAgentIds() view returns (uint256[])",
69
+ "function createAccount(uint256 agentId) returns (address safeAccount)",
70
70
  "function identityRegistry() view returns (address)",
71
- "event AccountCreated(uint256 indexed agentId, address indexed account, address indexed owner)"
71
+ "function validationModule() view returns (address)",
72
+ "function hookMultiplexer() view returns (address)",
73
+ "function safeSingleton() view returns (address)",
74
+ "function safe7579() view returns (address)",
75
+ "function bootstrap() view returns (address)",
76
+ "function SENTINEL_OWNER() view returns (address)",
77
+ "event AccountCreated(uint256 indexed agentId, address indexed safeAccount, address indexed owner)"
72
78
  ];
73
- AGENT_ACCOUNT_ABI = [
74
- "function agentId() view returns (uint256)",
79
+ ACCOUNT_FACTORY_ABI = SAFE_AGENT_FACTORY_ABI;
80
+ ERC8004_VALIDATION_MODULE_ABI = [
81
+ // View
82
+ "function getConfig(address account) view returns (address registry, uint256 agentId)",
83
+ "function getOwner(address account) view returns (address)",
84
+ "function isInstalled(address account) view returns (bool)",
85
+ "function isKYAApproved(address account) view returns (bool)",
86
+ "function validationRegistry() view returns (address)",
75
87
  "function owner() view returns (address)",
76
- "function factory() view returns (address)",
77
- "function identityRegistry() view returns (address)",
78
- "function balanceOf(address token) view returns (uint256)",
79
- "function ethBalance() view returns (uint256)",
80
- // ERC-7579 execution
81
- "function execute(bytes32 mode, bytes executionCalldata) payable",
82
- "function executeFromExecutor(bytes32 mode, bytes executionCalldata) payable returns (bytes[])",
83
- // ERC-7579 module management
84
- "function installModule(uint256 moduleTypeId, address module, bytes initData) payable",
85
- "function uninstallModule(uint256 moduleTypeId, address module, bytes deInitData) payable",
86
- "function isModuleInstalled(uint256 moduleTypeId, address module, bytes additionalContext) view returns (bool)",
87
- "function hook() view returns (address)",
88
- // Funding (direct, no execution needed)
89
- "function fund(address token, uint256 amount)",
90
- "function withdraw(address token, uint256 amount, address to)",
91
- "function withdrawETH(uint256 amount, address to)",
92
- // EIP-1271
93
- "function isValidSignature(bytes32 hash, bytes signature) view returns (bytes4)"
88
+ // Admin (via TimelockController)
89
+ "function setValidationRegistry(address registry_)"
94
90
  ];
95
91
  AGENT_REPUTATION_ABI = [
96
92
  "function getCreditScore(uint256 agentId) view returns (uint256)",
@@ -130,9 +126,22 @@ var init_abis = __esm({
130
126
  "function symbol() view returns (string)",
131
127
  "function name() view returns (string)"
132
128
  ];
133
- KYA_HOOK_ABI = [
134
- "function validationRegistry() view returns (address)",
135
- "function setValidationRegistry(address newRegistry)"
129
+ ENTRYPOINT_V07_ABI = [
130
+ "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)",
131
+ "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)",
132
+ "function getNonce(address sender, uint192 key) view returns (uint256 nonce)",
133
+ "function balanceOf(address account) view returns (uint256)",
134
+ "function depositTo(address account) payable",
135
+ "event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed)"
136
+ ];
137
+ SAFE7579_ACCOUNT_ABI = [
138
+ // ERC-7579 execution (called via UserOp through Safe7579 fallback)
139
+ "function execute(bytes32 mode, bytes executionCalldata) payable",
140
+ "function executeFromExecutor(bytes32 mode, bytes executionCalldata) payable returns (bytes[])",
141
+ // ERC-7579 module queries
142
+ "function isModuleInstalled(uint256 moduleTypeId, address module, bytes additionalContext) view returns (bool)",
143
+ // EIP-1271
144
+ "function isValidSignature(bytes32 hash, bytes signature) view returns (bytes4)"
136
145
  ];
137
146
  }
138
147
  });
@@ -146,56 +155,99 @@ function getDefaultConfig(chainId) {
146
155
  scoringEndpoint: SCORING_ENDPOINTS[chainId]
147
156
  };
148
157
  }
149
- var CONTRACT_ADDRESSES, RPC_URLS, SCORING_ENDPOINTS;
158
+ var ZERO, ENTRYPOINT_V07, ERC8004_IDENTITY_REGISTRY, ERC8004_IDENTITY_REGISTRY_TESTNET, MORPHO_BLUE, SAFE_SINGLETON, SAFE_PROXY_FACTORY, SAFE7579, CONTRACT_ADDRESSES, RPC_URLS, SCORING_ENDPOINTS;
150
159
  var init_config = __esm({
151
160
  "src/utils/config.ts"() {
152
161
  "use strict";
153
162
  init_types();
163
+ ZERO = "0x0000000000000000000000000000000000000000";
164
+ ENTRYPOINT_V07 = "0x0000000071727De22E5E9d8BAf0edAc6f37da032";
165
+ ERC8004_IDENTITY_REGISTRY = "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432";
166
+ ERC8004_IDENTITY_REGISTRY_TESTNET = "0x8004A818BFB912233c491871b3d84c89A494BD9e";
167
+ MORPHO_BLUE = "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb";
168
+ SAFE_SINGLETON = "0x41675C099F32341bf84BFc5382aF534df5C7461a";
169
+ SAFE_PROXY_FACTORY = "0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67";
170
+ SAFE7579 = "0x7579EE8307284F293B1927136486880611F20002";
154
171
  CONTRACT_ADDRESSES = {
155
172
  [1 /* Ethereum */]: {
156
- accountFactory: "0x0000000000000000000000000000000000000000",
157
- validationRegistry: "0x0000000000000000000000000000000000000000",
158
- agentReputation: "0x0000000000000000000000000000000000000000",
159
- kyaHook: "0x0000000000000000000000000000000000000000",
173
+ safeSingleton: SAFE_SINGLETON,
174
+ safeProxyFactory: SAFE_PROXY_FACTORY,
175
+ safe7579: SAFE7579,
176
+ entryPoint: ENTRYPOINT_V07,
177
+ safeAgentFactory: ZERO,
178
+ safe7579Bootstrap: ZERO,
179
+ erc8004ValidationModule: ZERO,
180
+ hookMultiplexer: ZERO,
181
+ validationRegistry: ZERO,
182
+ agentReputation: ZERO,
183
+ timelockController: ZERO,
160
184
  usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
161
- identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
162
- morphoBlue: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb"
185
+ identityRegistry: ERC8004_IDENTITY_REGISTRY,
186
+ morphoBlue: MORPHO_BLUE
163
187
  },
164
188
  [8453 /* Base */]: {
165
- accountFactory: "0x89a8758E60A56EcB47247D92E05447eFd450d6Bf",
166
- validationRegistry: "0x6f76cF69B71Dc5F9A414BCEe4583b12738E47985",
167
- agentReputation: "0xe88f3419a2dbac70e3aF6E487b0C63e8301C6A87",
168
- kyaHook: "0x28e50Aa9eD517E369b2806928709B44062aD9821",
189
+ safeSingleton: SAFE_SINGLETON,
190
+ safeProxyFactory: SAFE_PROXY_FACTORY,
191
+ safe7579: SAFE7579,
192
+ entryPoint: ENTRYPOINT_V07,
193
+ safeAgentFactory: "0xB0A88ffe28491E793F7706829278f20d724947d1",
194
+ safe7579Bootstrap: "0x72A636bc23B2644138489c3bBE3B05a0a7184b33",
195
+ erc8004ValidationModule: "0x49e27A6B4d012B87271897b51d0296ABcFCb0BBd",
196
+ hookMultiplexer: "0x12c77f17F91f06a11C2C34C618ce9d78f9a34541",
197
+ validationRegistry: "0x88E21e8883c093E4c8d0d0cE68f1c93Cf6190f51",
198
+ agentReputation: "0x4C2d42cbD35f6541f0902499CFEC27C1Cf5683E3",
199
+ timelockController: "0x0517b4f73b61774C88A2B1c5745141315E831015",
169
200
  usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
170
- identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
171
- morphoBlue: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb"
201
+ identityRegistry: ERC8004_IDENTITY_REGISTRY,
202
+ morphoBlue: MORPHO_BLUE
172
203
  },
173
204
  [84532 /* BaseSepolia */]: {
174
- accountFactory: "0x0000000000000000000000000000000000000000",
175
- validationRegistry: "0x0000000000000000000000000000000000000000",
176
- agentReputation: "0x0000000000000000000000000000000000000000",
177
- kyaHook: "0x0000000000000000000000000000000000000000",
205
+ safeSingleton: SAFE_SINGLETON,
206
+ safeProxyFactory: SAFE_PROXY_FACTORY,
207
+ safe7579: SAFE7579,
208
+ entryPoint: ENTRYPOINT_V07,
209
+ safeAgentFactory: ZERO,
210
+ safe7579Bootstrap: ZERO,
211
+ erc8004ValidationModule: ZERO,
212
+ hookMultiplexer: ZERO,
213
+ validationRegistry: ZERO,
214
+ agentReputation: ZERO,
215
+ timelockController: ZERO,
178
216
  usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
179
- identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
180
- morphoBlue: "0x0000000000000000000000000000000000000000"
217
+ identityRegistry: ERC8004_IDENTITY_REGISTRY_TESTNET,
218
+ morphoBlue: ZERO
181
219
  },
182
220
  [11155111 /* Sepolia */]: {
183
- accountFactory: "0x0000000000000000000000000000000000000000",
184
- validationRegistry: "0x0000000000000000000000000000000000000000",
185
- agentReputation: "0x0000000000000000000000000000000000000000",
186
- kyaHook: "0x0000000000000000000000000000000000000000",
221
+ safeSingleton: SAFE_SINGLETON,
222
+ safeProxyFactory: SAFE_PROXY_FACTORY,
223
+ safe7579: SAFE7579,
224
+ entryPoint: ENTRYPOINT_V07,
225
+ safeAgentFactory: ZERO,
226
+ safe7579Bootstrap: ZERO,
227
+ erc8004ValidationModule: ZERO,
228
+ hookMultiplexer: ZERO,
229
+ validationRegistry: ZERO,
230
+ agentReputation: ZERO,
231
+ timelockController: ZERO,
187
232
  usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
188
- identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
189
- morphoBlue: "0x0000000000000000000000000000000000000000"
233
+ identityRegistry: ERC8004_IDENTITY_REGISTRY_TESTNET,
234
+ morphoBlue: ZERO
190
235
  },
191
236
  [31337 /* Hardhat */]: {
192
- accountFactory: "0x0000000000000000000000000000000000000000",
193
- validationRegistry: "0x0000000000000000000000000000000000000000",
194
- agentReputation: "0x0000000000000000000000000000000000000000",
195
- kyaHook: "0x0000000000000000000000000000000000000000",
237
+ safeSingleton: SAFE_SINGLETON,
238
+ safeProxyFactory: SAFE_PROXY_FACTORY,
239
+ safe7579: SAFE7579,
240
+ entryPoint: ENTRYPOINT_V07,
241
+ safeAgentFactory: ZERO,
242
+ safe7579Bootstrap: ZERO,
243
+ erc8004ValidationModule: ZERO,
244
+ hookMultiplexer: ZERO,
245
+ validationRegistry: ZERO,
246
+ agentReputation: ZERO,
247
+ timelockController: ZERO,
196
248
  usdc: "0x56d4d6aEe0278c5Df2FA23Ecb32eC146C9446FDf",
197
- identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
198
- morphoBlue: "0x0000000000000000000000000000000000000000"
249
+ identityRegistry: ERC8004_IDENTITY_REGISTRY,
250
+ morphoBlue: ZERO
199
251
  }
200
252
  };
201
253
  RPC_URLS = {
@@ -270,27 +322,24 @@ var init_MorphoClient = __esm({
270
322
  this._eoaAddress = wallet.address;
271
323
  }
272
324
  const addrs = { ...defaultCfg.contracts, ...config.contracts };
273
- this.accountFactory = new import_ethers.Contract(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this._signer);
325
+ this.safeAgentFactory = new import_ethers.Contract(addrs.safeAgentFactory, ACCOUNT_FACTORY_ABI, this._signer);
274
326
  this.morphoBlue = new import_ethers.Contract(addrs.morphoBlue, MORPHO_BLUE_ABI, this.provider);
275
327
  this.agentReputation = new import_ethers.Contract(addrs.agentReputation, AGENT_REPUTATION_ABI, this._signer);
276
328
  this.identityRegistry = new import_ethers.Contract(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this._signer);
329
+ this.entryPoint = new import_ethers.Contract(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
330
+ this.validationModule = new import_ethers.Contract(addrs.erc8004ValidationModule, ERC8004_VALIDATION_MODULE_ABI, this.provider);
277
331
  }
278
332
  // ════════════════════════════════════════════════════════
279
333
  // KYA Gate Check
280
334
  // ════════════════════════════════════════════════════════
281
335
  /**
282
336
  * Check whether the KYA (Know Your Agent) code verification gate is active.
283
- * Reads the account's installed hook and checks if it has a non-zero
284
- * validationRegistry when set, the hook enforces KYA code approval.
337
+ * Reads the ERC8004ValidationModule's validationRegistry when set to
338
+ * a non-zero address, the module enforces KYA code approval.
285
339
  */
286
340
  async isKyaRequired() {
287
341
  try {
288
- const acctAddr = await this.getAccountAddress();
289
- const account = new import_ethers.Contract(acctAddr, AGENT_ACCOUNT_ABI, this.provider);
290
- const hookAddr = await account.hook();
291
- if (hookAddr === import_ethers.ethers.ZeroAddress) return false;
292
- const hook = new import_ethers.Contract(hookAddr, KYA_HOOK_ABI, this.provider);
293
- const registryAddr = await hook.validationRegistry();
342
+ const registryAddr = await this.validationModule.validationRegistry();
294
343
  return registryAddr !== import_ethers.ethers.ZeroAddress;
295
344
  } catch {
296
345
  return false;
@@ -307,7 +356,7 @@ var init_MorphoClient = __esm({
307
356
  let lastErr;
308
357
  for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
309
358
  try {
310
- const addr = await this.accountFactory.getAccount(BigInt(this.agentId));
359
+ const addr = await this.safeAgentFactory.getAccount(BigInt(this.agentId));
311
360
  if (addr === import_ethers.ethers.ZeroAddress) {
312
361
  throw new AgetherError("No AgentAccount found. Call register() first.", "NO_ACCOUNT");
313
362
  }
@@ -385,9 +434,9 @@ var init_MorphoClient = __esm({
385
434
  async register(_name) {
386
435
  const eoaAddr = await this.getSignerAddress();
387
436
  if (this.agentId) {
388
- const exists = await this.accountFactory.accountExists(BigInt(this.agentId));
437
+ const exists = await this.safeAgentFactory.accountExists(BigInt(this.agentId));
389
438
  if (exists) {
390
- const acct = await this.accountFactory.getAccount(BigInt(this.agentId));
439
+ const acct = await this.safeAgentFactory.getAccount(BigInt(this.agentId));
391
440
  this._accountAddress = acct;
392
441
  const kyaRequired2 = await this.isKyaRequired();
393
442
  return { agentId: this.agentId, address: eoaAddr, agentAccount: acct, alreadyRegistered: true, kyaRequired: kyaRequired2 };
@@ -405,15 +454,15 @@ var init_MorphoClient = __esm({
405
454
  agentId = await this._mintNewIdentity();
406
455
  }
407
456
  this.agentId = agentId.toString();
408
- const acctExists = await this.accountFactory.accountExists(agentId);
457
+ const acctExists = await this.safeAgentFactory.accountExists(agentId);
409
458
  let txHash;
410
459
  if (!acctExists) {
411
- const tx = await this.accountFactory.createAccount(agentId);
460
+ const tx = await this.safeAgentFactory.createAccount(agentId);
412
461
  const receipt = await tx.wait();
413
462
  this._refreshSigner();
414
463
  txHash = receipt.hash;
415
464
  }
416
- const acctAddr = await this.accountFactory.getAccount(agentId);
465
+ const acctAddr = await this.safeAgentFactory.getAccount(agentId);
417
466
  this._accountAddress = acctAddr;
418
467
  const kyaRequired = await this.isKyaRequired();
419
468
  return {
@@ -1140,7 +1189,7 @@ var init_MorphoClient = __esm({
1140
1189
  if (target.address) {
1141
1190
  targetAddr = target.address;
1142
1191
  } else if (target.agentId) {
1143
- targetAddr = await this.accountFactory.getAccount(BigInt(target.agentId));
1192
+ targetAddr = await this.safeAgentFactory.getAccount(BigInt(target.agentId));
1144
1193
  if (targetAddr === import_ethers.ethers.ZeroAddress) throw new AgetherError("Target agent has no account", "NO_ACCOUNT");
1145
1194
  } else {
1146
1195
  throw new AgetherError("Provide agentId or address", "INVALID_TARGET");
@@ -1193,7 +1242,9 @@ var init_MorphoClient = __esm({
1193
1242
  _refreshSigner() {
1194
1243
  if (this._useExternalSigner) {
1195
1244
  const addrs = this.config.contracts;
1196
- this.accountFactory = new import_ethers.Contract(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this._signer);
1245
+ this.safeAgentFactory = new import_ethers.Contract(addrs.safeAgentFactory, ACCOUNT_FACTORY_ABI, this._signer);
1246
+ this.entryPoint = new import_ethers.Contract(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
1247
+ this.validationModule = new import_ethers.Contract(addrs.erc8004ValidationModule, ERC8004_VALIDATION_MODULE_ABI, this.provider);
1197
1248
  this.agentReputation = new import_ethers.Contract(addrs.agentReputation, AGENT_REPUTATION_ABI, this._signer);
1198
1249
  this.identityRegistry = new import_ethers.Contract(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this._signer);
1199
1250
  } else {
@@ -1202,57 +1253,87 @@ var init_MorphoClient = __esm({
1202
1253
  this._signer = wallet;
1203
1254
  this._eoaAddress = wallet.address;
1204
1255
  const addrs = this.config.contracts;
1205
- this.accountFactory = new import_ethers.Contract(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this._signer);
1256
+ this.safeAgentFactory = new import_ethers.Contract(addrs.safeAgentFactory, ACCOUNT_FACTORY_ABI, this._signer);
1257
+ this.entryPoint = new import_ethers.Contract(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
1258
+ this.validationModule = new import_ethers.Contract(addrs.erc8004ValidationModule, ERC8004_VALIDATION_MODULE_ABI, this.provider);
1206
1259
  this.agentReputation = new import_ethers.Contract(addrs.agentReputation, AGENT_REPUTATION_ABI, this._signer);
1207
1260
  this.identityRegistry = new import_ethers.Contract(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this._signer);
1208
1261
  }
1209
1262
  }
1263
+ // ────────────────────────────────────────────────────────────
1264
+ // ERC-4337 UserOp helpers (Safe + Safe7579 + EntryPoint v0.7)
1265
+ // ────────────────────────────────────────────────────────────
1210
1266
  /**
1211
- * Execute a single call via AgentAccount.execute (ERC-7579 single mode).
1267
+ * Pack two uint128 values into a single bytes32:
1268
+ * bytes32 = (hi << 128) | lo
1269
+ */
1270
+ _packUint128(hi, lo) {
1271
+ return import_ethers.ethers.zeroPadValue(import_ethers.ethers.toBeHex(hi << 128n | lo), 32);
1272
+ }
1273
+ /**
1274
+ * Build, sign and submit a PackedUserOperation through EntryPoint.handleOps.
1275
+ *
1276
+ * @param callData – the ABI-encoded calldata for the Safe7579 account
1277
+ * (e.g. `execute(mode, executionCalldata)`)
1278
+ * @returns the transaction receipt of the handleOps call
1279
+ */
1280
+ async _submitUserOp(callData) {
1281
+ const sender = await this.getAccountAddress();
1282
+ const nonce = await this.entryPoint.getNonce(sender, 0);
1283
+ const feeData = await this.provider.getFeeData();
1284
+ const maxFeePerGas = feeData.maxFeePerGas ?? import_ethers.ethers.parseUnits("0.5", "gwei");
1285
+ const maxPriorityFeePerGas = feeData.maxPriorityFeePerGas ?? import_ethers.ethers.parseUnits("0.1", "gwei");
1286
+ const verificationGasLimit = 500000n;
1287
+ const callGasLimit = 800000n;
1288
+ const preVerificationGas = 100000n;
1289
+ const accountGasLimits = this._packUint128(verificationGasLimit, callGasLimit);
1290
+ const gasFees = this._packUint128(maxPriorityFeePerGas, maxFeePerGas);
1291
+ const userOp = {
1292
+ sender,
1293
+ nonce,
1294
+ initCode: "0x",
1295
+ callData,
1296
+ accountGasLimits,
1297
+ preVerificationGas,
1298
+ gasFees,
1299
+ paymasterAndData: "0x",
1300
+ signature: "0x"
1301
+ // placeholder — replaced after signing
1302
+ };
1303
+ const userOpHash = await this.entryPoint.getUserOpHash(userOp);
1304
+ const signature = await this._signer.signMessage(import_ethers.ethers.getBytes(userOpHash));
1305
+ userOp.signature = signature;
1306
+ const tx = await this.entryPoint.handleOps([userOp], await this.getSignerAddress());
1307
+ const receipt = await tx.wait();
1308
+ this._refreshSigner();
1309
+ return receipt;
1310
+ }
1311
+ /**
1312
+ * Execute a single call via Safe7579 account (ERC-7579 single mode)
1313
+ * through an ERC-4337 UserOperation.
1212
1314
  */
1213
1315
  async exec(target, data, value = 0n) {
1214
- const acctAddr = await this.getAccountAddress();
1215
- const account = new import_ethers.Contract(acctAddr, AGENT_ACCOUNT_ABI, this._signer);
1216
1316
  const executionCalldata = import_ethers.ethers.AbiCoder.defaultAbiCoder().encode(
1217
1317
  ["address", "uint256", "bytes"],
1218
1318
  [target, value, data]
1219
1319
  );
1220
- let gasLimit;
1221
- try {
1222
- const estimate = await account.execute.estimateGas(MODE_SINGLE, executionCalldata);
1223
- gasLimit = estimate * 130n / 100n;
1224
- } catch (e) {
1225
- console.warn("[agether] exec gas estimation failed, using default 500k:", e instanceof Error ? e.message : e);
1226
- gasLimit = 500000n;
1227
- }
1228
- const tx = await account.execute(MODE_SINGLE, executionCalldata, { gasLimit });
1229
- const receipt = await tx.wait();
1230
- this._refreshSigner();
1231
- return receipt;
1320
+ const safe7579Iface = new import_ethers.ethers.Interface(SAFE7579_ACCOUNT_ABI);
1321
+ const callData = safe7579Iface.encodeFunctionData("execute", [MODE_SINGLE, executionCalldata]);
1322
+ return this._submitUserOp(callData);
1232
1323
  }
1233
1324
  /**
1234
- * Execute multiple calls via AgentAccount.execute (ERC-7579 batch mode).
1325
+ * Execute multiple calls via Safe7579 account (ERC-7579 batch mode)
1326
+ * through an ERC-4337 UserOperation.
1235
1327
  */
1236
1328
  async batch(targets, values, datas) {
1237
- const acctAddr = await this.getAccountAddress();
1238
- const account = new import_ethers.Contract(acctAddr, AGENT_ACCOUNT_ABI, this._signer);
1239
1329
  const executions = targets.map((t, i) => [t, values[i], datas[i]]);
1240
1330
  const executionCalldata = import_ethers.ethers.AbiCoder.defaultAbiCoder().encode(
1241
1331
  ["(address,uint256,bytes)[]"],
1242
1332
  [executions]
1243
1333
  );
1244
- let gasLimit;
1245
- try {
1246
- const estimate = await account.execute.estimateGas(MODE_BATCH, executionCalldata);
1247
- gasLimit = estimate * 130n / 100n;
1248
- } catch (e) {
1249
- console.warn("[agether] batch gas estimation failed, using default 800k:", e instanceof Error ? e.message : e);
1250
- gasLimit = 800000n;
1251
- }
1252
- const tx = await account.execute(MODE_BATCH, executionCalldata, { gasLimit });
1253
- const receipt = await tx.wait();
1254
- this._refreshSigner();
1255
- return receipt;
1334
+ const safe7579Iface = new import_ethers.ethers.Interface(SAFE7579_ACCOUNT_ABI);
1335
+ const callData = safe7579Iface.encodeFunctionData("execute", [MODE_BATCH, executionCalldata]);
1336
+ return this._submitUserOp(callData);
1256
1337
  }
1257
1338
  /** Convert MorphoMarketParams to Solidity tuple. */
1258
1339
  _toTuple(p) {
@@ -1753,10 +1834,10 @@ async function cmdRegister(name) {
1753
1834
  process.exit(1);
1754
1835
  }
1755
1836
  const registryAddr = contracts.agentRegistry || contracts.identityRegistry;
1756
- const factoryAddr = contracts.accountFactory;
1837
+ const factoryAddr = contracts.safeAgentFactory || contracts.accountFactory;
1757
1838
  const validationAddr = contracts.validationRegistry;
1758
1839
  if (!registryAddr || !factoryAddr) {
1759
- console.error(" \u274C Backend missing agentRegistry or accountFactory");
1840
+ console.error(" \u274C Backend missing agentRegistry or safeAgentFactory");
1760
1841
  process.exit(1);
1761
1842
  }
1762
1843
  console.log(" [2/4] Registering on ERC-8004 IdentityRegistry...");
@@ -1839,7 +1920,7 @@ async function cmdRegister(name) {
1839
1920
  } else {
1840
1921
  console.log(" [3/4] Skipping USDC mint (real network)");
1841
1922
  }
1842
- console.log(" [4/4] Creating AgentAccount...");
1923
+ console.log(" [4/4] Creating Safe account...");
1843
1924
  if (factoryAddr) {
1844
1925
  const factory = new import_ethers2.ethers.Contract(factoryAddr, ACCOUNT_FACTORY_ABI2, signer);
1845
1926
  try {
@@ -2109,14 +2190,14 @@ async function cmdX402Call(url, method = "GET", body) {
2109
2190
  }
2110
2191
  function cmdHelp() {
2111
2192
  console.log(`
2112
- \u{1F3E6} Agether CLI \u2014 Direct Morpho Blue Credit for AI Agents
2193
+ \u{1F3E6} Agether CLI \u2014 Direct Morpho Blue Credit for AI Agents (Safe + Safe7579)
2113
2194
 
2114
2195
  USAGE:
2115
2196
  agether <command> [options]
2116
2197
 
2117
2198
  SETUP:
2118
2199
  init <private-key> [--agent-id <id>] Initialize with private key
2119
- register [--name <n>] Register ERC-8004 + create AgentAccount
2200
+ register [--name <n>] Register ERC-8004 + create Safe account
2120
2201
 
2121
2202
  INFO:
2122
2203
  balance Check ETH + USDC balances
@@ -2132,7 +2213,7 @@ MORPHO LENDING:
2132
2213
  repay --amount <usd> [--token <t>] Repay borrowed USDC
2133
2214
  withdraw --amount <n> --token <t> Withdraw collateral (use 'all' for max)
2134
2215
  sponsor --amount <n> --token <t> --agent-id <id> Send collateral to another agent
2135
- fund --amount <usd> Transfer USDC from EOA to AgentAccount
2216
+ fund --amount <usd> Transfer USDC from EOA to Safe account
2136
2217
 
2137
2218
  x402 PAYMENTS:
2138
2219
  x402 <url> [--method GET|POST] [--body <json>] Make a paid API call