@agether/sdk 2.17.3 → 2.18.1
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 +502 -357
- package/dist/index.d.mts +231 -46
- package/dist/index.d.ts +231 -46
- package/dist/index.js +950 -288
- package/dist/index.mjs +948 -288
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -30,57 +30,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
30
|
mod
|
|
31
31
|
));
|
|
32
32
|
|
|
33
|
-
// src/utils/retry.ts
|
|
34
|
-
function isRetriable(error) {
|
|
35
|
-
const msg = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
|
|
36
|
-
return RETRIABLE_PATTERNS.some((p) => msg.includes(p.toLowerCase()));
|
|
37
|
-
}
|
|
38
|
-
async function withRetry(fn, options = {}) {
|
|
39
|
-
const {
|
|
40
|
-
maxRetries = 3,
|
|
41
|
-
baseDelay = 1e3,
|
|
42
|
-
maxDelay = 15e3,
|
|
43
|
-
onRetry
|
|
44
|
-
} = options;
|
|
45
|
-
let lastError;
|
|
46
|
-
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
47
|
-
try {
|
|
48
|
-
return await fn();
|
|
49
|
-
} catch (error) {
|
|
50
|
-
lastError = error instanceof Error ? error : new Error(String(error));
|
|
51
|
-
if (attempt >= maxRetries || !isRetriable(error)) {
|
|
52
|
-
throw lastError;
|
|
53
|
-
}
|
|
54
|
-
const delay = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
|
|
55
|
-
const jitter = delay * (0.5 + Math.random() * 0.5);
|
|
56
|
-
onRetry?.(attempt, lastError);
|
|
57
|
-
await new Promise((resolve) => setTimeout(resolve, jitter));
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
throw lastError;
|
|
61
|
-
}
|
|
62
|
-
var RETRIABLE_PATTERNS;
|
|
63
|
-
var init_retry = __esm({
|
|
64
|
-
"src/utils/retry.ts"() {
|
|
65
|
-
"use strict";
|
|
66
|
-
RETRIABLE_PATTERNS = [
|
|
67
|
-
"ECONNRESET",
|
|
68
|
-
"ECONNREFUSED",
|
|
69
|
-
"ENOTFOUND",
|
|
70
|
-
"ETIMEDOUT",
|
|
71
|
-
"fetch failed",
|
|
72
|
-
"network error",
|
|
73
|
-
"socket hang up",
|
|
74
|
-
"rate limit",
|
|
75
|
-
"429",
|
|
76
|
-
"502",
|
|
77
|
-
"503",
|
|
78
|
-
"504",
|
|
79
|
-
"timeout"
|
|
80
|
-
];
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
|
|
84
33
|
// src/types/index.ts
|
|
85
34
|
var AgetherError;
|
|
86
35
|
var init_types = __esm({
|
|
@@ -320,33 +269,19 @@ var init_config = __esm({
|
|
|
320
269
|
}
|
|
321
270
|
});
|
|
322
271
|
|
|
323
|
-
// src/clients/
|
|
324
|
-
var
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
});
|
|
328
|
-
var import_ethers, import_axios, MORPHO_API_URL, MODE_SINGLE, MODE_BATCH, morphoIface, erc20Iface, MorphoClient;
|
|
329
|
-
var init_MorphoClient = __esm({
|
|
330
|
-
"src/clients/MorphoClient.ts"() {
|
|
272
|
+
// src/clients/AgentAccountClient.ts
|
|
273
|
+
var import_ethers, MODE_SINGLE, MODE_BATCH, AgentAccountClient;
|
|
274
|
+
var init_AgentAccountClient = __esm({
|
|
275
|
+
"src/clients/AgentAccountClient.ts"() {
|
|
331
276
|
"use strict";
|
|
332
277
|
import_ethers = require("ethers");
|
|
333
|
-
import_axios = __toESM(require("axios"));
|
|
334
|
-
init_retry();
|
|
335
278
|
init_types();
|
|
336
279
|
init_abis();
|
|
337
280
|
init_config();
|
|
338
|
-
MORPHO_API_URL = "https://api.morpho.org/graphql";
|
|
339
281
|
MODE_SINGLE = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
340
282
|
MODE_BATCH = "0x0100000000000000000000000000000000000000000000000000000000000000";
|
|
341
|
-
|
|
342
|
-
erc20Iface = new import_ethers.ethers.Interface(ERC20_ABI);
|
|
343
|
-
MorphoClient = class _MorphoClient {
|
|
283
|
+
AgentAccountClient = class {
|
|
344
284
|
constructor(config) {
|
|
345
|
-
/** Market params cache: keyed by market uniqueKey (bytes32 hash) */
|
|
346
|
-
this._marketCache = /* @__PURE__ */ new Map();
|
|
347
|
-
/** Dynamic token registry: symbol (uppercase) or address (lowercase) → { address, symbol, decimals } */
|
|
348
|
-
this._tokenCache = /* @__PURE__ */ new Map();
|
|
349
|
-
this._discoveredAt = 0;
|
|
350
285
|
if (!config.agentId) {
|
|
351
286
|
throw new AgetherError(
|
|
352
287
|
"agentId is required. Use AgetherClient.register() first to get an agentId.",
|
|
@@ -381,13 +316,10 @@ var init_MorphoClient = __esm({
|
|
|
381
316
|
}
|
|
382
317
|
const addrs = { ...defaultCfg.contracts, ...config.contracts };
|
|
383
318
|
this.agether4337Factory = new import_ethers.Contract(addrs.agether4337Factory, ACCOUNT_FACTORY_ABI, this._signer);
|
|
384
|
-
this.morphoBlue = new import_ethers.Contract(addrs.morphoBlue, MORPHO_BLUE_ABI, this.provider);
|
|
385
319
|
this.entryPoint = new import_ethers.Contract(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
|
|
386
320
|
}
|
|
387
|
-
//
|
|
388
|
-
|
|
389
|
-
// ════════════════════════════════════════════════════════
|
|
390
|
-
/** Resolve the AgentAccount address (cached, with retry for flaky RPCs). */
|
|
321
|
+
// ─── Account Management ───────────────────────────────────────────────
|
|
322
|
+
/** Resolve the AgentAccount (Safe) address. Cached after first call. */
|
|
391
323
|
async getAccountAddress() {
|
|
392
324
|
if (this._accountAddress) return this._accountAddress;
|
|
393
325
|
const MAX_RETRIES = 3;
|
|
@@ -413,26 +345,279 @@ var init_MorphoClient = __esm({
|
|
|
413
345
|
getAgentId() {
|
|
414
346
|
return this.agentId;
|
|
415
347
|
}
|
|
416
|
-
/**
|
|
417
|
-
* Get the EOA wallet address (synchronous, best-effort).
|
|
418
|
-
*
|
|
419
|
-
* For the `privateKey` path this always works. For the `signer` path
|
|
420
|
-
* it works if the signer exposes `.address` synchronously (e.g. ethers.Wallet).
|
|
421
|
-
* If the address has not been resolved yet, throws — call `getSignerAddress()` first.
|
|
422
|
-
*/
|
|
348
|
+
/** Get the EOA wallet address (synchronous). */
|
|
423
349
|
getWalletAddress() {
|
|
424
350
|
if (this._eoaAddress) return this._eoaAddress;
|
|
425
351
|
const signer = this._signer;
|
|
426
352
|
if (signer.address && typeof signer.address === "string") {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
return addr;
|
|
353
|
+
this._eoaAddress = signer.address;
|
|
354
|
+
return signer.address;
|
|
430
355
|
}
|
|
431
356
|
throw new AgetherError(
|
|
432
|
-
"EOA address not
|
|
433
|
-
"
|
|
357
|
+
"EOA address not available synchronously. Call getSignerAddress() first.",
|
|
358
|
+
"NO_EOA_ADDRESS"
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
/** Get EOA wallet address (async, works for all signer types). */
|
|
362
|
+
async getSignerAddress() {
|
|
363
|
+
if (this._eoaAddress) return this._eoaAddress;
|
|
364
|
+
const addr = await this._signer.getAddress();
|
|
365
|
+
this._eoaAddress = addr;
|
|
366
|
+
return addr;
|
|
367
|
+
}
|
|
368
|
+
// ─── Safe7579 Execution ───────────────────────────────────────────────
|
|
369
|
+
/** Pack two uint128 values into a single bytes32. */
|
|
370
|
+
_packUint128(hi, lo) {
|
|
371
|
+
return import_ethers.ethers.zeroPadValue(import_ethers.ethers.toBeHex(hi << 128n | lo), 32);
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Build, sign and submit a PackedUserOperation through EntryPoint.handleOps.
|
|
375
|
+
*/
|
|
376
|
+
async _submitUserOp(callData) {
|
|
377
|
+
const sender = await this.getAccountAddress();
|
|
378
|
+
const validatorAddr = this.config.contracts.erc8004ValidationModule;
|
|
379
|
+
const nonceKey = BigInt(validatorAddr) << 32n;
|
|
380
|
+
const nonce = await this.entryPoint.getNonce(sender, nonceKey);
|
|
381
|
+
const feeData = await this.provider.getFeeData();
|
|
382
|
+
const maxFeePerGas = feeData.maxFeePerGas ?? import_ethers.ethers.parseUnits("0.5", "gwei");
|
|
383
|
+
const maxPriorityFeePerGas = feeData.maxPriorityFeePerGas ?? import_ethers.ethers.parseUnits("0.1", "gwei");
|
|
384
|
+
const verificationGasLimit = 500000n;
|
|
385
|
+
const callGasLimit = 800000n;
|
|
386
|
+
const preVerificationGas = 100000n;
|
|
387
|
+
const accountGasLimits = this._packUint128(verificationGasLimit, callGasLimit);
|
|
388
|
+
const gasFees = this._packUint128(maxPriorityFeePerGas, maxFeePerGas);
|
|
389
|
+
const requiredPrefund = (verificationGasLimit + callGasLimit + preVerificationGas) * maxFeePerGas;
|
|
390
|
+
const accountBalance = await this.provider.getBalance(sender);
|
|
391
|
+
if (accountBalance < requiredPrefund) {
|
|
392
|
+
const topUp = requiredPrefund - accountBalance;
|
|
393
|
+
const topUpWithBuffer = topUp * 120n / 100n;
|
|
394
|
+
const eoaBalance = await this.provider.getBalance(
|
|
395
|
+
this._eoaAddress ?? await this._signer.getAddress()
|
|
396
|
+
);
|
|
397
|
+
if (eoaBalance < topUpWithBuffer) {
|
|
398
|
+
const needed = import_ethers.ethers.formatEther(topUpWithBuffer);
|
|
399
|
+
throw new AgetherError(
|
|
400
|
+
`Insufficient ETH for gas. Need ~${needed} ETH in EOA.`,
|
|
401
|
+
"INSUFFICIENT_GAS"
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
const tx = await this._signer.sendTransaction({ to: sender, value: topUpWithBuffer });
|
|
405
|
+
await tx.wait();
|
|
406
|
+
}
|
|
407
|
+
const packedUserOp = {
|
|
408
|
+
sender,
|
|
409
|
+
nonce,
|
|
410
|
+
initCode: "0x",
|
|
411
|
+
callData,
|
|
412
|
+
accountGasLimits,
|
|
413
|
+
preVerificationGas,
|
|
414
|
+
gasFees,
|
|
415
|
+
paymasterAndData: "0x",
|
|
416
|
+
signature: "0x"
|
|
417
|
+
};
|
|
418
|
+
const entryPointAddr = await this.entryPoint.getAddress();
|
|
419
|
+
const chainId = (await this.provider.getNetwork()).chainId;
|
|
420
|
+
const userOpHash = import_ethers.ethers.keccak256(
|
|
421
|
+
import_ethers.ethers.AbiCoder.defaultAbiCoder().encode(
|
|
422
|
+
["bytes32", "address", "uint256"],
|
|
423
|
+
[
|
|
424
|
+
import_ethers.ethers.keccak256(
|
|
425
|
+
import_ethers.ethers.AbiCoder.defaultAbiCoder().encode(
|
|
426
|
+
[
|
|
427
|
+
"address",
|
|
428
|
+
"uint256",
|
|
429
|
+
"bytes32",
|
|
430
|
+
"bytes32",
|
|
431
|
+
"bytes32",
|
|
432
|
+
"uint256",
|
|
433
|
+
"bytes32",
|
|
434
|
+
"bytes32"
|
|
435
|
+
],
|
|
436
|
+
[
|
|
437
|
+
packedUserOp.sender,
|
|
438
|
+
packedUserOp.nonce,
|
|
439
|
+
import_ethers.ethers.keccak256(packedUserOp.initCode),
|
|
440
|
+
import_ethers.ethers.keccak256(packedUserOp.callData),
|
|
441
|
+
packedUserOp.accountGasLimits,
|
|
442
|
+
packedUserOp.preVerificationGas,
|
|
443
|
+
packedUserOp.gasFees,
|
|
444
|
+
import_ethers.ethers.keccak256(packedUserOp.paymasterAndData)
|
|
445
|
+
]
|
|
446
|
+
)
|
|
447
|
+
),
|
|
448
|
+
entryPointAddr,
|
|
449
|
+
chainId
|
|
450
|
+
]
|
|
451
|
+
)
|
|
452
|
+
);
|
|
453
|
+
const signature = await this._signer.signMessage(import_ethers.ethers.getBytes(userOpHash));
|
|
454
|
+
packedUserOp.signature = signature;
|
|
455
|
+
const handleOpsTx = await this.entryPoint.handleOps(
|
|
456
|
+
[
|
|
457
|
+
[
|
|
458
|
+
packedUserOp.sender,
|
|
459
|
+
packedUserOp.nonce,
|
|
460
|
+
packedUserOp.initCode,
|
|
461
|
+
packedUserOp.callData,
|
|
462
|
+
packedUserOp.accountGasLimits,
|
|
463
|
+
packedUserOp.preVerificationGas,
|
|
464
|
+
packedUserOp.gasFees,
|
|
465
|
+
packedUserOp.paymasterAndData,
|
|
466
|
+
packedUserOp.signature
|
|
467
|
+
]
|
|
468
|
+
],
|
|
469
|
+
this._eoaAddress ?? await this._signer.getAddress()
|
|
470
|
+
);
|
|
471
|
+
const receipt = await handleOpsTx.wait();
|
|
472
|
+
const epIface = new import_ethers.ethers.Interface(ENTRYPOINT_V07_ABI);
|
|
473
|
+
for (const log of receipt.logs) {
|
|
474
|
+
try {
|
|
475
|
+
const parsed = epIface.parseLog({ topics: log.topics, data: log.data });
|
|
476
|
+
if (parsed?.name === "UserOperationEvent") {
|
|
477
|
+
if (!parsed.args.success) {
|
|
478
|
+
let revertMsg = "UserOp inner execution reverted";
|
|
479
|
+
for (const rLog of receipt.logs) {
|
|
480
|
+
try {
|
|
481
|
+
const rParsed = epIface.parseLog({ topics: rLog.topics, data: rLog.data });
|
|
482
|
+
if (rParsed?.name === "UserOperationRevertReason") {
|
|
483
|
+
const reason = rParsed.args.revertReason;
|
|
484
|
+
try {
|
|
485
|
+
if (reason.length >= 10 && reason.slice(0, 10) === "0x08c379a0") {
|
|
486
|
+
const decoded = import_ethers.ethers.AbiCoder.defaultAbiCoder().decode(["string"], "0x" + reason.slice(10));
|
|
487
|
+
revertMsg = `UserOp reverted: ${decoded[0]}`;
|
|
488
|
+
} else {
|
|
489
|
+
revertMsg = `UserOp reverted with data: ${reason}`;
|
|
490
|
+
}
|
|
491
|
+
} catch {
|
|
492
|
+
revertMsg = `UserOp reverted with data: ${reason}`;
|
|
493
|
+
}
|
|
494
|
+
break;
|
|
495
|
+
}
|
|
496
|
+
} catch {
|
|
497
|
+
continue;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
throw new AgetherError(revertMsg, "USEROP_EXECUTION_FAILED");
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
} catch (e) {
|
|
504
|
+
if (e instanceof AgetherError) throw e;
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return receipt;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Execute a single call via Safe7579 account through ERC-4337 UserOp.
|
|
512
|
+
*/
|
|
513
|
+
async executeSingle(target, data, value = 0n) {
|
|
514
|
+
const valueHex = import_ethers.ethers.zeroPadValue(import_ethers.ethers.toBeHex(value), 32);
|
|
515
|
+
const executionCalldata = import_ethers.ethers.concat([target, valueHex, data]);
|
|
516
|
+
const safe7579Iface = new import_ethers.ethers.Interface(SAFE7579_ACCOUNT_ABI);
|
|
517
|
+
const callData = safe7579Iface.encodeFunctionData("execute", [MODE_SINGLE, executionCalldata]);
|
|
518
|
+
return this._submitUserOp(callData);
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Execute multiple calls via Safe7579 account in one atomic batch.
|
|
522
|
+
*/
|
|
523
|
+
async executeBatch(targets, values, datas) {
|
|
524
|
+
const executions = targets.map((t, i) => [t, values[i], datas[i]]);
|
|
525
|
+
const executionCalldata = import_ethers.ethers.AbiCoder.defaultAbiCoder().encode(
|
|
526
|
+
["(address,uint256,bytes)[]"],
|
|
527
|
+
[executions]
|
|
434
528
|
);
|
|
529
|
+
const safe7579Iface = new import_ethers.ethers.Interface(SAFE7579_ACCOUNT_ABI);
|
|
530
|
+
const callData = safe7579Iface.encodeFunctionData("execute", [MODE_BATCH, executionCalldata]);
|
|
531
|
+
return this._submitUserOp(callData);
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
// src/utils/retry.ts
|
|
538
|
+
function isRetriable(error) {
|
|
539
|
+
const msg = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
|
|
540
|
+
return RETRIABLE_PATTERNS.some((p) => msg.includes(p.toLowerCase()));
|
|
541
|
+
}
|
|
542
|
+
async function withRetry(fn, options = {}) {
|
|
543
|
+
const {
|
|
544
|
+
maxRetries = 3,
|
|
545
|
+
baseDelay = 1e3,
|
|
546
|
+
maxDelay = 15e3,
|
|
547
|
+
onRetry
|
|
548
|
+
} = options;
|
|
549
|
+
let lastError;
|
|
550
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
551
|
+
try {
|
|
552
|
+
return await fn();
|
|
553
|
+
} catch (error) {
|
|
554
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
555
|
+
if (attempt >= maxRetries || !isRetriable(error)) {
|
|
556
|
+
throw lastError;
|
|
557
|
+
}
|
|
558
|
+
const delay = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
|
|
559
|
+
const jitter = delay * (0.5 + Math.random() * 0.5);
|
|
560
|
+
onRetry?.(attempt, lastError);
|
|
561
|
+
await new Promise((resolve) => setTimeout(resolve, jitter));
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
throw lastError;
|
|
565
|
+
}
|
|
566
|
+
var RETRIABLE_PATTERNS;
|
|
567
|
+
var init_retry = __esm({
|
|
568
|
+
"src/utils/retry.ts"() {
|
|
569
|
+
"use strict";
|
|
570
|
+
RETRIABLE_PATTERNS = [
|
|
571
|
+
"ECONNRESET",
|
|
572
|
+
"ECONNREFUSED",
|
|
573
|
+
"ENOTFOUND",
|
|
574
|
+
"ETIMEDOUT",
|
|
575
|
+
"fetch failed",
|
|
576
|
+
"network error",
|
|
577
|
+
"socket hang up",
|
|
578
|
+
"rate limit",
|
|
579
|
+
"429",
|
|
580
|
+
"502",
|
|
581
|
+
"503",
|
|
582
|
+
"504",
|
|
583
|
+
"timeout"
|
|
584
|
+
];
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
// src/clients/MorphoClient.ts
|
|
589
|
+
var MorphoClient_exports = {};
|
|
590
|
+
__export(MorphoClient_exports, {
|
|
591
|
+
MorphoClient: () => MorphoClient
|
|
592
|
+
});
|
|
593
|
+
var import_ethers2, import_axios, MORPHO_API_URL, morphoIface, erc20Iface, MorphoClient;
|
|
594
|
+
var init_MorphoClient = __esm({
|
|
595
|
+
"src/clients/MorphoClient.ts"() {
|
|
596
|
+
"use strict";
|
|
597
|
+
import_ethers2 = require("ethers");
|
|
598
|
+
init_AgentAccountClient();
|
|
599
|
+
import_axios = __toESM(require("axios"));
|
|
600
|
+
init_retry();
|
|
601
|
+
init_types();
|
|
602
|
+
init_abis();
|
|
603
|
+
MORPHO_API_URL = "https://api.morpho.org/graphql";
|
|
604
|
+
morphoIface = new import_ethers2.ethers.Interface(MORPHO_BLUE_ABI);
|
|
605
|
+
erc20Iface = new import_ethers2.ethers.Interface(ERC20_ABI);
|
|
606
|
+
MorphoClient = class _MorphoClient extends AgentAccountClient {
|
|
607
|
+
constructor(config) {
|
|
608
|
+
super(config);
|
|
609
|
+
// Cached state
|
|
610
|
+
/** Market params cache: keyed by market uniqueKey (bytes32 hash) */
|
|
611
|
+
this._marketCache = /* @__PURE__ */ new Map();
|
|
612
|
+
/** Dynamic token registry: symbol (uppercase) or address (lowercase) → { address, symbol, decimals } */
|
|
613
|
+
this._tokenCache = /* @__PURE__ */ new Map();
|
|
614
|
+
this._discoveredAt = 0;
|
|
615
|
+
const addrs = { ...this.config.contracts, ...config.contracts };
|
|
616
|
+
this.morphoBlue = new import_ethers2.Contract(addrs.morphoBlue, MORPHO_BLUE_ABI, this.provider);
|
|
435
617
|
}
|
|
618
|
+
// ════════════════════════════════════════════════════════
|
|
619
|
+
// Account Management
|
|
620
|
+
// ════════════════════════════════════════════════════════
|
|
436
621
|
/**
|
|
437
622
|
* Resolve the EOA signer address (async, works with all signer types).
|
|
438
623
|
* Result is cached after the first call.
|
|
@@ -489,7 +674,7 @@ var init_MorphoClient = __esm({
|
|
|
489
674
|
this._discoveredMarkets = items.map((m) => ({
|
|
490
675
|
uniqueKey: m.uniqueKey,
|
|
491
676
|
loanAsset: m.loanAsset,
|
|
492
|
-
collateralAsset: m.collateralAsset ?? { address:
|
|
677
|
+
collateralAsset: m.collateralAsset ?? { address: import_ethers2.ethers.ZeroAddress, symbol: "N/A", decimals: 0 },
|
|
493
678
|
oracle: m.oracleAddress,
|
|
494
679
|
irm: m.irmAddress,
|
|
495
680
|
lltv: BigInt(m.lltv),
|
|
@@ -506,7 +691,7 @@ var init_MorphoClient = __esm({
|
|
|
506
691
|
irm: mi.irm,
|
|
507
692
|
lltv: mi.lltv
|
|
508
693
|
});
|
|
509
|
-
if (mi.collateralAsset.address !==
|
|
694
|
+
if (mi.collateralAsset.address !== import_ethers2.ethers.ZeroAddress) {
|
|
510
695
|
this._tokenCache.set(mi.collateralAsset.symbol.toUpperCase(), {
|
|
511
696
|
address: mi.collateralAsset.address,
|
|
512
697
|
symbol: mi.collateralAsset.symbol,
|
|
@@ -518,7 +703,7 @@ var init_MorphoClient = __esm({
|
|
|
518
703
|
decimals: mi.collateralAsset.decimals
|
|
519
704
|
});
|
|
520
705
|
}
|
|
521
|
-
if (mi.loanAsset.address !==
|
|
706
|
+
if (mi.loanAsset.address !== import_ethers2.ethers.ZeroAddress) {
|
|
522
707
|
this._tokenCache.set(mi.loanAsset.symbol.toUpperCase(), {
|
|
523
708
|
address: mi.loanAsset.address,
|
|
524
709
|
symbol: mi.loanAsset.symbol,
|
|
@@ -688,7 +873,7 @@ var init_MorphoClient = __esm({
|
|
|
688
873
|
const totalBorrowShares = BigInt(mkt.totalBorrowShares);
|
|
689
874
|
const totalBorrowAssets = BigInt(mkt.totalBorrowAssets);
|
|
690
875
|
debt = totalBorrowShares > 0n ? (borrowShares * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares : 0n;
|
|
691
|
-
totalDebtFloat += parseFloat(
|
|
876
|
+
totalDebtFloat += parseFloat(import_ethers2.ethers.formatUnits(debt, loanDecimals));
|
|
692
877
|
} catch (e) {
|
|
693
878
|
console.warn(`[agether] debt calc failed for market ${m.uniqueKey}:`, e instanceof Error ? e.message : e);
|
|
694
879
|
}
|
|
@@ -697,17 +882,17 @@ var init_MorphoClient = __esm({
|
|
|
697
882
|
marketId: m.uniqueKey,
|
|
698
883
|
collateralToken: m.collateralAsset.symbol,
|
|
699
884
|
loanToken: m.loanAsset.symbol,
|
|
700
|
-
collateral:
|
|
885
|
+
collateral: import_ethers2.ethers.formatUnits(collateral, m.collateralAsset.decimals),
|
|
701
886
|
borrowShares: borrowShares.toString(),
|
|
702
887
|
supplyShares: supplyShares.toString(),
|
|
703
|
-
debt:
|
|
888
|
+
debt: import_ethers2.ethers.formatUnits(debt, loanDecimals)
|
|
704
889
|
});
|
|
705
890
|
}
|
|
706
891
|
} catch (e) {
|
|
707
892
|
console.warn("[agether] marketPositions API failed, falling back to market scan:", e instanceof Error ? e.message : e);
|
|
708
893
|
const markets = await this.getMarkets();
|
|
709
894
|
for (const m of markets) {
|
|
710
|
-
if (!m.collateralAsset || m.collateralAsset.address ===
|
|
895
|
+
if (!m.collateralAsset || m.collateralAsset.address === import_ethers2.ethers.ZeroAddress) continue;
|
|
711
896
|
try {
|
|
712
897
|
const pos = await this.morphoBlue.position(m.uniqueKey, acctAddr);
|
|
713
898
|
if (pos.collateral === 0n && pos.borrowShares === 0n && pos.supplyShares === 0n) continue;
|
|
@@ -719,7 +904,7 @@ var init_MorphoClient = __esm({
|
|
|
719
904
|
const totalBorrowShares = BigInt(mkt.totalBorrowShares);
|
|
720
905
|
const totalBorrowAssets = BigInt(mkt.totalBorrowAssets);
|
|
721
906
|
debt = totalBorrowShares > 0n ? (BigInt(pos.borrowShares) * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares : 0n;
|
|
722
|
-
totalDebtFloat += parseFloat(
|
|
907
|
+
totalDebtFloat += parseFloat(import_ethers2.ethers.formatUnits(debt, loanDecimals));
|
|
723
908
|
} catch (e2) {
|
|
724
909
|
console.warn(`[agether] debt calc failed:`, e2 instanceof Error ? e2.message : e2);
|
|
725
910
|
}
|
|
@@ -728,10 +913,10 @@ var init_MorphoClient = __esm({
|
|
|
728
913
|
marketId: m.uniqueKey,
|
|
729
914
|
collateralToken: m.collateralAsset.symbol,
|
|
730
915
|
loanToken: m.loanAsset.symbol,
|
|
731
|
-
collateral:
|
|
916
|
+
collateral: import_ethers2.ethers.formatUnits(pos.collateral, m.collateralAsset.decimals),
|
|
732
917
|
borrowShares: pos.borrowShares.toString(),
|
|
733
918
|
supplyShares: pos.supplyShares.toString(),
|
|
734
|
-
debt:
|
|
919
|
+
debt: import_ethers2.ethers.formatUnits(debt, loanDecimals)
|
|
735
920
|
});
|
|
736
921
|
} catch (e2) {
|
|
737
922
|
console.warn(`[agether] position read failed:`, e2 instanceof Error ? e2.message : e2);
|
|
@@ -757,7 +942,7 @@ var init_MorphoClient = __esm({
|
|
|
757
942
|
async getTokenBalance(symbolOrAddress) {
|
|
758
943
|
const acctAddr = await this.getAccountAddress();
|
|
759
944
|
const tokenInfo = await this._resolveToken(symbolOrAddress);
|
|
760
|
-
const token = new
|
|
945
|
+
const token = new import_ethers2.Contract(tokenInfo.address, ERC20_ABI, this.provider);
|
|
761
946
|
return token.balanceOf(acctAddr);
|
|
762
947
|
}
|
|
763
948
|
/**
|
|
@@ -767,7 +952,7 @@ var init_MorphoClient = __esm({
|
|
|
767
952
|
*/
|
|
768
953
|
async getUsdcBalance() {
|
|
769
954
|
const acctAddr = await this.getAccountAddress();
|
|
770
|
-
const usdc = new
|
|
955
|
+
const usdc = new import_ethers2.Contract(this.config.contracts.usdc, ERC20_ABI, this.provider);
|
|
771
956
|
return usdc.balanceOf(acctAddr);
|
|
772
957
|
}
|
|
773
958
|
/**
|
|
@@ -787,7 +972,7 @@ var init_MorphoClient = __esm({
|
|
|
787
972
|
let totalAdditional = 0n;
|
|
788
973
|
const byMarket = [];
|
|
789
974
|
for (const m of markets) {
|
|
790
|
-
if (!m.collateralAsset || m.collateralAsset.address ===
|
|
975
|
+
if (!m.collateralAsset || m.collateralAsset.address === import_ethers2.ethers.ZeroAddress) continue;
|
|
791
976
|
try {
|
|
792
977
|
const pos = await this.morphoBlue.position(m.uniqueKey, acctAddr);
|
|
793
978
|
if (pos.collateral === 0n) continue;
|
|
@@ -797,7 +982,7 @@ var init_MorphoClient = __esm({
|
|
|
797
982
|
const currentDebt = totalBorrowShares > 0n ? (BigInt(pos.borrowShares) * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares : 0n;
|
|
798
983
|
let collateralValueInLoan;
|
|
799
984
|
try {
|
|
800
|
-
const oracleContract = new
|
|
985
|
+
const oracleContract = new import_ethers2.Contract(m.oracle, [
|
|
801
986
|
"function price() view returns (uint256)"
|
|
802
987
|
], this.provider);
|
|
803
988
|
const oraclePrice = await oracleContract.price();
|
|
@@ -903,7 +1088,7 @@ var init_MorphoClient = __esm({
|
|
|
903
1088
|
const sym = loanTokenSymbolOrAddress.toUpperCase();
|
|
904
1089
|
items = items.filter((m) => m.loanAsset?.symbol?.toUpperCase() === sym);
|
|
905
1090
|
}
|
|
906
|
-
return items.filter((m) => m.collateralAsset?.address && m.collateralAsset.address !==
|
|
1091
|
+
return items.filter((m) => m.collateralAsset?.address && m.collateralAsset.address !== import_ethers2.ethers.ZeroAddress).map((m) => {
|
|
907
1092
|
const loanDecimals = m.loanAsset?.decimals ?? 18;
|
|
908
1093
|
return {
|
|
909
1094
|
collateralToken: m.collateralAsset.symbol,
|
|
@@ -964,7 +1149,7 @@ var init_MorphoClient = __esm({
|
|
|
964
1149
|
{ maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho API retry ${n}:`, e.message) }
|
|
965
1150
|
);
|
|
966
1151
|
let items = resp.data?.data?.markets?.items ?? [];
|
|
967
|
-
items = items.filter((m) => m.collateralAsset?.address && m.collateralAsset.address !==
|
|
1152
|
+
items = items.filter((m) => m.collateralAsset?.address && m.collateralAsset.address !== import_ethers2.ethers.ZeroAddress);
|
|
968
1153
|
const searchUpper = search.toUpperCase();
|
|
969
1154
|
if (options?.asCollateral) {
|
|
970
1155
|
items = items.filter((m) => m.collateralAsset?.symbol?.toUpperCase() === searchUpper);
|
|
@@ -1020,10 +1205,10 @@ var init_MorphoClient = __esm({
|
|
|
1020
1205
|
if (ethBalance > 0n) {
|
|
1021
1206
|
results.push({
|
|
1022
1207
|
symbol: "ETH",
|
|
1023
|
-
address:
|
|
1208
|
+
address: import_ethers2.ethers.ZeroAddress,
|
|
1024
1209
|
decimals: 18,
|
|
1025
1210
|
balance: ethBalance,
|
|
1026
|
-
balanceFormatted:
|
|
1211
|
+
balanceFormatted: import_ethers2.ethers.formatEther(ethBalance)
|
|
1027
1212
|
});
|
|
1028
1213
|
}
|
|
1029
1214
|
} catch {
|
|
@@ -1034,7 +1219,7 @@ var init_MorphoClient = __esm({
|
|
|
1034
1219
|
const batch = tokenEntries.slice(i, i + batchSize);
|
|
1035
1220
|
const checks = batch.map(async (info) => {
|
|
1036
1221
|
try {
|
|
1037
|
-
const token = new
|
|
1222
|
+
const token = new import_ethers2.Contract(info.address, ERC20_ABI, this.provider);
|
|
1038
1223
|
const balance = await token.balanceOf(acctAddr);
|
|
1039
1224
|
if (balance > 0n) {
|
|
1040
1225
|
return {
|
|
@@ -1042,7 +1227,7 @@ var init_MorphoClient = __esm({
|
|
|
1042
1227
|
address: info.address,
|
|
1043
1228
|
decimals: info.decimals,
|
|
1044
1229
|
balance,
|
|
1045
|
-
balanceFormatted:
|
|
1230
|
+
balanceFormatted: import_ethers2.ethers.formatUnits(balance, info.decimals)
|
|
1046
1231
|
};
|
|
1047
1232
|
}
|
|
1048
1233
|
} catch {
|
|
@@ -1074,7 +1259,7 @@ var init_MorphoClient = __esm({
|
|
|
1074
1259
|
try {
|
|
1075
1260
|
const balance = await this.getTokenBalance(collateralSymbol);
|
|
1076
1261
|
const info = await this._resolveToken(collateralSymbol);
|
|
1077
|
-
tokensToCheck = [{ symbol: collateralSymbol, balanceFormatted:
|
|
1262
|
+
tokensToCheck = [{ symbol: collateralSymbol, balanceFormatted: import_ethers2.ethers.formatUnits(balance, info.decimals) }];
|
|
1078
1263
|
} catch {
|
|
1079
1264
|
}
|
|
1080
1265
|
} else {
|
|
@@ -1153,13 +1338,13 @@ var init_MorphoClient = __esm({
|
|
|
1153
1338
|
} else {
|
|
1154
1339
|
try {
|
|
1155
1340
|
const params = await this.findMarketForCollateral(collateralSymbol);
|
|
1156
|
-
const loanDecimals =
|
|
1157
|
-
const oracleContract = new
|
|
1341
|
+
const loanDecimals = market.loanDecimals;
|
|
1342
|
+
const oracleContract = new import_ethers2.Contract(params.oracle, [
|
|
1158
1343
|
"function price() view returns (uint256)"
|
|
1159
1344
|
], this.provider);
|
|
1160
1345
|
const oraclePrice = await oracleContract.price();
|
|
1161
1346
|
const ORACLE_PRICE_SCALE = 10n ** 36n;
|
|
1162
|
-
const amountWei =
|
|
1347
|
+
const amountWei = import_ethers2.ethers.parseUnits(amount, colInfo.decimals);
|
|
1163
1348
|
const valueInLoan = amountWei * oraclePrice / ORACLE_PRICE_SCALE;
|
|
1164
1349
|
collateralValueUsd = Number(valueInLoan) / 10 ** loanDecimals;
|
|
1165
1350
|
} catch (e) {
|
|
@@ -1210,14 +1395,14 @@ var init_MorphoClient = __esm({
|
|
|
1210
1395
|
}
|
|
1211
1396
|
const loanDecimals = await this._getLoanTokenDecimals(params);
|
|
1212
1397
|
const loanTokenAddr = params.loanToken;
|
|
1213
|
-
const parsedAmount =
|
|
1214
|
-
const marketId =
|
|
1215
|
-
|
|
1398
|
+
const parsedAmount = import_ethers2.ethers.parseUnits(amount, loanDecimals);
|
|
1399
|
+
const marketId = import_ethers2.ethers.keccak256(
|
|
1400
|
+
import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
|
|
1216
1401
|
["address", "address", "address", "address", "uint256"],
|
|
1217
1402
|
[params.loanToken, params.collateralToken, params.oracle, params.irm, params.lltv]
|
|
1218
1403
|
)
|
|
1219
1404
|
);
|
|
1220
|
-
const loanContract = new
|
|
1405
|
+
const loanContract = new import_ethers2.Contract(loanTokenAddr, ERC20_ABI, this._signer);
|
|
1221
1406
|
const acctBalance = await loanContract.balanceOf(acctAddr);
|
|
1222
1407
|
if (acctBalance < parsedAmount) {
|
|
1223
1408
|
const shortfall = parsedAmount - acctBalance;
|
|
@@ -1226,7 +1411,7 @@ var init_MorphoClient = __esm({
|
|
|
1226
1411
|
const loanInfo = this._tokenCache.get(loanTokenAddr.toLowerCase());
|
|
1227
1412
|
const loanSymbol = loanInfo?.symbol ?? "loan token";
|
|
1228
1413
|
throw new AgetherError(
|
|
1229
|
-
`Insufficient ${loanSymbol}. Need ${amount}, AgentAccount has ${
|
|
1414
|
+
`Insufficient ${loanSymbol}. Need ${amount}, AgentAccount has ${import_ethers2.ethers.formatUnits(acctBalance, loanDecimals)}, EOA has ${import_ethers2.ethers.formatUnits(eoaBalance, loanDecimals)}.`,
|
|
1230
1415
|
"INSUFFICIENT_BALANCE"
|
|
1231
1416
|
);
|
|
1232
1417
|
}
|
|
@@ -1246,7 +1431,7 @@ var init_MorphoClient = __esm({
|
|
|
1246
1431
|
"0x"
|
|
1247
1432
|
])
|
|
1248
1433
|
];
|
|
1249
|
-
const receipt = await this.
|
|
1434
|
+
const receipt = await this.executeBatch(targets, values, datas);
|
|
1250
1435
|
return {
|
|
1251
1436
|
tx: receipt.hash,
|
|
1252
1437
|
amount,
|
|
@@ -1282,8 +1467,8 @@ var init_MorphoClient = __esm({
|
|
|
1282
1467
|
params = p;
|
|
1283
1468
|
}
|
|
1284
1469
|
const loanDecimals = await this._getLoanTokenDecimals(params);
|
|
1285
|
-
const marketId =
|
|
1286
|
-
|
|
1470
|
+
const marketId = import_ethers2.ethers.keccak256(
|
|
1471
|
+
import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
|
|
1287
1472
|
["address", "address", "address", "address", "uint256"],
|
|
1288
1473
|
[params.loanToken, params.collateralToken, params.oracle, params.irm, params.lltv]
|
|
1289
1474
|
)
|
|
@@ -1296,7 +1481,7 @@ var init_MorphoClient = __esm({
|
|
|
1296
1481
|
withdrawAssets = 0n;
|
|
1297
1482
|
if (withdrawShares === 0n) throw new AgetherError("No supply position to withdraw", "NO_SUPPLY");
|
|
1298
1483
|
} else {
|
|
1299
|
-
withdrawAssets =
|
|
1484
|
+
withdrawAssets = import_ethers2.ethers.parseUnits(amount, loanDecimals);
|
|
1300
1485
|
withdrawShares = 0n;
|
|
1301
1486
|
}
|
|
1302
1487
|
const data = morphoIface.encodeFunctionData("withdraw", [
|
|
@@ -1306,7 +1491,7 @@ var init_MorphoClient = __esm({
|
|
|
1306
1491
|
acctAddr,
|
|
1307
1492
|
dest
|
|
1308
1493
|
]);
|
|
1309
|
-
const receipt = await this.
|
|
1494
|
+
const receipt = await this.executeSingle(morphoAddr, data);
|
|
1310
1495
|
let remainingSupply = "0";
|
|
1311
1496
|
try {
|
|
1312
1497
|
const pos = await this.morphoBlue.position(marketId, acctAddr);
|
|
@@ -1314,7 +1499,7 @@ var init_MorphoClient = __esm({
|
|
|
1314
1499
|
const totalSupplyAssets = BigInt(mkt.totalSupplyAssets);
|
|
1315
1500
|
const totalSupplyShares = BigInt(mkt.totalSupplyShares);
|
|
1316
1501
|
const currentAssets = totalSupplyShares > 0n ? BigInt(pos.supplyShares) * totalSupplyAssets / totalSupplyShares : 0n;
|
|
1317
|
-
remainingSupply =
|
|
1502
|
+
remainingSupply = import_ethers2.ethers.formatUnits(currentAssets, loanDecimals);
|
|
1318
1503
|
} catch (e) {
|
|
1319
1504
|
console.warn("[agether] failed to read remaining supply:", e instanceof Error ? e.message : e);
|
|
1320
1505
|
}
|
|
@@ -1379,9 +1564,9 @@ var init_MorphoClient = __esm({
|
|
|
1379
1564
|
loanToken: p.market.loanAsset.symbol,
|
|
1380
1565
|
collateralToken: p.market.collateralAsset?.symbol ?? "none",
|
|
1381
1566
|
supplyShares: p.state.supplyShares,
|
|
1382
|
-
suppliedAssets:
|
|
1383
|
-
netDeposited:
|
|
1384
|
-
earnedYield:
|
|
1567
|
+
suppliedAssets: import_ethers2.ethers.formatUnits(currentAssets, p.market.loanAsset.decimals),
|
|
1568
|
+
netDeposited: import_ethers2.ethers.formatUnits(netDeposited, p.market.loanAsset.decimals),
|
|
1569
|
+
earnedYield: import_ethers2.ethers.formatUnits(earnedYield, p.market.loanAsset.decimals),
|
|
1385
1570
|
supplyApy: p.market.state?.supplyApy ?? 0
|
|
1386
1571
|
});
|
|
1387
1572
|
}
|
|
@@ -1409,8 +1594,8 @@ var init_MorphoClient = __esm({
|
|
|
1409
1594
|
);
|
|
1410
1595
|
const params = await this.findMarketForCollateral(pos.collateralToken, pos.loanToken);
|
|
1411
1596
|
const loanDecimals = await this._getLoanTokenDecimals(params);
|
|
1412
|
-
const parsedAmount =
|
|
1413
|
-
const availableYield =
|
|
1597
|
+
const parsedAmount = import_ethers2.ethers.parseUnits(amount, loanDecimals);
|
|
1598
|
+
const availableYield = import_ethers2.ethers.parseUnits(pos.earnedYield, loanDecimals);
|
|
1414
1599
|
if (parsedAmount > availableYield) {
|
|
1415
1600
|
const loanSymbol = pos.loanToken;
|
|
1416
1601
|
throw new AgetherError(
|
|
@@ -1425,7 +1610,7 @@ var init_MorphoClient = __esm({
|
|
|
1425
1610
|
acctAddr,
|
|
1426
1611
|
recipient
|
|
1427
1612
|
]);
|
|
1428
|
-
const receipt = await this.
|
|
1613
|
+
const receipt = await this.executeSingle(morphoAddr, data);
|
|
1429
1614
|
let remainingYield = "0";
|
|
1430
1615
|
let remainingSupply = "0";
|
|
1431
1616
|
try {
|
|
@@ -1460,16 +1645,16 @@ var init_MorphoClient = __esm({
|
|
|
1460
1645
|
const acctAddr = await this.getAccountAddress();
|
|
1461
1646
|
const colInfo = await this._resolveToken(tokenSymbol);
|
|
1462
1647
|
const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
|
|
1463
|
-
const weiAmount =
|
|
1648
|
+
const weiAmount = import_ethers2.ethers.parseUnits(amount, colInfo.decimals);
|
|
1464
1649
|
const morphoAddr = this.config.contracts.morphoBlue;
|
|
1465
|
-
const colToken = new
|
|
1650
|
+
const colToken = new import_ethers2.Contract(colInfo.address, ERC20_ABI, this._signer);
|
|
1466
1651
|
const acctBalance = await colToken.balanceOf(acctAddr);
|
|
1467
1652
|
if (acctBalance < weiAmount) {
|
|
1468
1653
|
const shortfall = weiAmount - acctBalance;
|
|
1469
1654
|
const eoaBalance = await colToken.balanceOf(await this.getSignerAddress());
|
|
1470
1655
|
if (eoaBalance < shortfall) {
|
|
1471
1656
|
throw new AgetherError(
|
|
1472
|
-
`Insufficient ${tokenSymbol}. Need ${amount}, AgentAccount has ${
|
|
1657
|
+
`Insufficient ${tokenSymbol}. Need ${amount}, AgentAccount has ${import_ethers2.ethers.formatUnits(acctBalance, colInfo.decimals)}, EOA has ${import_ethers2.ethers.formatUnits(eoaBalance, colInfo.decimals)}.`,
|
|
1473
1658
|
"INSUFFICIENT_BALANCE"
|
|
1474
1659
|
);
|
|
1475
1660
|
}
|
|
@@ -1488,7 +1673,7 @@ var init_MorphoClient = __esm({
|
|
|
1488
1673
|
"0x"
|
|
1489
1674
|
])
|
|
1490
1675
|
];
|
|
1491
|
-
const receipt = await this.
|
|
1676
|
+
const receipt = await this.executeBatch(targets, values, datas);
|
|
1492
1677
|
return {
|
|
1493
1678
|
tx: receipt.hash,
|
|
1494
1679
|
collateralToken: tokenSymbol,
|
|
@@ -1521,10 +1706,10 @@ var init_MorphoClient = __esm({
|
|
|
1521
1706
|
usedToken = symbol;
|
|
1522
1707
|
}
|
|
1523
1708
|
const loanDecimals = await this._getLoanTokenDecimals(params);
|
|
1524
|
-
const parsedAmount =
|
|
1709
|
+
const parsedAmount = import_ethers2.ethers.parseUnits(amount, loanDecimals);
|
|
1525
1710
|
try {
|
|
1526
|
-
const marketId =
|
|
1527
|
-
|
|
1711
|
+
const marketId = import_ethers2.ethers.keccak256(
|
|
1712
|
+
import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
|
|
1528
1713
|
["address", "address", "address", "address", "uint256"],
|
|
1529
1714
|
[params.loanToken, params.collateralToken, params.oracle, params.irm, params.lltv]
|
|
1530
1715
|
)
|
|
@@ -1536,7 +1721,7 @@ var init_MorphoClient = __esm({
|
|
|
1536
1721
|
"NO_COLLATERAL"
|
|
1537
1722
|
);
|
|
1538
1723
|
}
|
|
1539
|
-
const oracleContract = new
|
|
1724
|
+
const oracleContract = new import_ethers2.Contract(params.oracle, ["function price() view returns (uint256)"], this.provider);
|
|
1540
1725
|
const oraclePrice = await oracleContract.price();
|
|
1541
1726
|
const collateralValueInLoan = BigInt(pos.collateral) * oraclePrice / 10n ** 36n;
|
|
1542
1727
|
const maxBorrowTotal = collateralValueInLoan * params.lltv / 10n ** 18n;
|
|
@@ -1549,8 +1734,8 @@ var init_MorphoClient = __esm({
|
|
|
1549
1734
|
const loanInfo = this._tokenCache.get(params.loanToken.toLowerCase());
|
|
1550
1735
|
const loanSymbol = loanInfo?.symbol ?? "loan token";
|
|
1551
1736
|
const colInfo = await this._resolveToken(usedToken);
|
|
1552
|
-
const maxFormatted =
|
|
1553
|
-
const colFormatted =
|
|
1737
|
+
const maxFormatted = import_ethers2.ethers.formatUnits(maxAdditional, loanDecimals);
|
|
1738
|
+
const colFormatted = import_ethers2.ethers.formatUnits(pos.collateral, colInfo.decimals);
|
|
1554
1739
|
throw new AgetherError(
|
|
1555
1740
|
`Borrow of ${amount} ${loanSymbol} exceeds max borrowable ${maxFormatted} ${loanSymbol} (collateral: ${colFormatted} ${usedToken}, LLTV: ${Number(params.lltv) / 1e18 * 100}%). Deposit more collateral or reduce borrow amount.`,
|
|
1556
1741
|
"EXCEEDS_MAX_LTV"
|
|
@@ -1567,7 +1752,7 @@ var init_MorphoClient = __esm({
|
|
|
1567
1752
|
acctAddr,
|
|
1568
1753
|
acctAddr
|
|
1569
1754
|
]);
|
|
1570
|
-
const receipt = await this.
|
|
1755
|
+
const receipt = await this.executeSingle(morphoAddr, data);
|
|
1571
1756
|
return {
|
|
1572
1757
|
tx: receipt.hash,
|
|
1573
1758
|
amount,
|
|
@@ -1597,19 +1782,19 @@ var init_MorphoClient = __esm({
|
|
|
1597
1782
|
const colInfo = await this._resolveToken(tokenSymbol);
|
|
1598
1783
|
const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol, loanTokenSymbol);
|
|
1599
1784
|
const loanDecimals = await this._getLoanTokenDecimals(params);
|
|
1600
|
-
const colWei =
|
|
1601
|
-
const borrowWei =
|
|
1785
|
+
const colWei = import_ethers2.ethers.parseUnits(collateralAmount, colInfo.decimals);
|
|
1786
|
+
const borrowWei = import_ethers2.ethers.parseUnits(borrowAmount, loanDecimals);
|
|
1602
1787
|
const morphoAddr = this.config.contracts.morphoBlue;
|
|
1603
1788
|
try {
|
|
1604
|
-
const marketId =
|
|
1605
|
-
|
|
1789
|
+
const marketId = import_ethers2.ethers.keccak256(
|
|
1790
|
+
import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
|
|
1606
1791
|
["address", "address", "address", "address", "uint256"],
|
|
1607
1792
|
[params.loanToken, params.collateralToken, params.oracle, params.irm, params.lltv]
|
|
1608
1793
|
)
|
|
1609
1794
|
);
|
|
1610
1795
|
const pos = await this.morphoBlue.position(marketId, acctAddr);
|
|
1611
1796
|
const totalCollateral = BigInt(pos.collateral) + colWei;
|
|
1612
|
-
const oracleContract = new
|
|
1797
|
+
const oracleContract = new import_ethers2.Contract(params.oracle, ["function price() view returns (uint256)"], this.provider);
|
|
1613
1798
|
const oraclePrice = await oracleContract.price();
|
|
1614
1799
|
const collateralValueInLoan = totalCollateral * oraclePrice / 10n ** 36n;
|
|
1615
1800
|
const maxBorrowTotal = collateralValueInLoan * params.lltv / 10n ** 18n;
|
|
@@ -1621,9 +1806,9 @@ var init_MorphoClient = __esm({
|
|
|
1621
1806
|
if (borrowWei > maxAdditional) {
|
|
1622
1807
|
const loanInfo = this._tokenCache.get(params.loanToken.toLowerCase());
|
|
1623
1808
|
const loanSymbol = loanInfo?.symbol ?? "loan token";
|
|
1624
|
-
const maxFormatted =
|
|
1809
|
+
const maxFormatted = import_ethers2.ethers.formatUnits(maxAdditional, loanDecimals);
|
|
1625
1810
|
throw new AgetherError(
|
|
1626
|
-
`Borrow of ${borrowAmount} ${loanSymbol} exceeds max borrowable ${maxFormatted} ${loanSymbol} (total collateral: ${
|
|
1811
|
+
`Borrow of ${borrowAmount} ${loanSymbol} exceeds max borrowable ${maxFormatted} ${loanSymbol} (total collateral: ${import_ethers2.ethers.formatUnits(totalCollateral, colInfo.decimals)} ${tokenSymbol}, LLTV: ${Number(params.lltv) / 1e18 * 100}%). Reduce borrow or increase collateral.`,
|
|
1627
1812
|
"EXCEEDS_MAX_LTV"
|
|
1628
1813
|
);
|
|
1629
1814
|
}
|
|
@@ -1631,14 +1816,14 @@ var init_MorphoClient = __esm({
|
|
|
1631
1816
|
if (e instanceof AgetherError) throw e;
|
|
1632
1817
|
console.warn("[agether] depositAndBorrow pre-check failed (proceeding anyway):", e instanceof Error ? e.message : e);
|
|
1633
1818
|
}
|
|
1634
|
-
const colToken = new
|
|
1819
|
+
const colToken = new import_ethers2.Contract(colInfo.address, ERC20_ABI, this._signer);
|
|
1635
1820
|
const acctBalance = await colToken.balanceOf(acctAddr);
|
|
1636
1821
|
if (acctBalance < colWei) {
|
|
1637
1822
|
const shortfall = colWei - acctBalance;
|
|
1638
1823
|
const eoaBalance = await colToken.balanceOf(await this.getSignerAddress());
|
|
1639
1824
|
if (eoaBalance < shortfall) {
|
|
1640
1825
|
throw new AgetherError(
|
|
1641
|
-
`Insufficient ${tokenSymbol}. Need ${collateralAmount}, AgentAccount has ${
|
|
1826
|
+
`Insufficient ${tokenSymbol}. Need ${collateralAmount}, AgentAccount has ${import_ethers2.ethers.formatUnits(acctBalance, colInfo.decimals)}, EOA has ${import_ethers2.ethers.formatUnits(eoaBalance, colInfo.decimals)}.`,
|
|
1642
1827
|
"INSUFFICIENT_BALANCE"
|
|
1643
1828
|
);
|
|
1644
1829
|
}
|
|
@@ -1664,7 +1849,7 @@ var init_MorphoClient = __esm({
|
|
|
1664
1849
|
acctAddr
|
|
1665
1850
|
])
|
|
1666
1851
|
];
|
|
1667
|
-
const receipt = await this.
|
|
1852
|
+
const receipt = await this.executeBatch(targets, values, datas);
|
|
1668
1853
|
return {
|
|
1669
1854
|
tx: receipt.hash,
|
|
1670
1855
|
collateralToken: tokenSymbol,
|
|
@@ -1696,8 +1881,8 @@ var init_MorphoClient = __esm({
|
|
|
1696
1881
|
const { params: p } = await this._findActiveMarket();
|
|
1697
1882
|
params = p;
|
|
1698
1883
|
}
|
|
1699
|
-
const loanTokenAddr = params.loanToken;
|
|
1700
1884
|
const loanDecimals = await this._getLoanTokenDecimals(params);
|
|
1885
|
+
const loanTokenAddr = params.loanToken;
|
|
1701
1886
|
let repayAssets;
|
|
1702
1887
|
let repayShares;
|
|
1703
1888
|
let approveAmount;
|
|
@@ -1714,9 +1899,9 @@ var init_MorphoClient = __esm({
|
|
|
1714
1899
|
const totalBorrowAssets = BigInt(onChainMkt.totalBorrowAssets);
|
|
1715
1900
|
const totalBorrowShares = BigInt(onChainMkt.totalBorrowShares);
|
|
1716
1901
|
const estimated = totalBorrowShares > 0n ? repayShares * totalBorrowAssets / totalBorrowShares + 10n : 0n;
|
|
1717
|
-
approveAmount = estimated > 0n ? estimated :
|
|
1902
|
+
approveAmount = estimated > 0n ? estimated : import_ethers2.ethers.parseUnits("1", loanDecimals);
|
|
1718
1903
|
} else {
|
|
1719
|
-
const marketId =
|
|
1904
|
+
const marketId = import_ethers2.ethers.keccak256(import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
|
|
1720
1905
|
["address", "address", "address", "address", "uint256"],
|
|
1721
1906
|
[params.loanToken, params.collateralToken, params.oracle, params.irm, params.lltv]
|
|
1722
1907
|
));
|
|
@@ -1726,14 +1911,14 @@ var init_MorphoClient = __esm({
|
|
|
1726
1911
|
const onChainMkt = await this.morphoBlue.market(marketId);
|
|
1727
1912
|
const totalBorrowAssets = BigInt(onChainMkt.totalBorrowAssets);
|
|
1728
1913
|
const totalBorrowShares = BigInt(onChainMkt.totalBorrowShares);
|
|
1729
|
-
approveAmount = totalBorrowShares > 0n ? repayShares * totalBorrowAssets / totalBorrowShares + 10n :
|
|
1914
|
+
approveAmount = totalBorrowShares > 0n ? repayShares * totalBorrowAssets / totalBorrowShares + 10n : import_ethers2.ethers.parseUnits("1", loanDecimals);
|
|
1730
1915
|
}
|
|
1731
1916
|
} else {
|
|
1732
|
-
repayAssets =
|
|
1917
|
+
repayAssets = import_ethers2.ethers.parseUnits(amount, loanDecimals);
|
|
1733
1918
|
repayShares = 0n;
|
|
1734
1919
|
approveAmount = repayAssets;
|
|
1735
1920
|
}
|
|
1736
|
-
const loanContract = new
|
|
1921
|
+
const loanContract = new import_ethers2.Contract(loanTokenAddr, ERC20_ABI, this._signer);
|
|
1737
1922
|
const acctBalance = await loanContract.balanceOf(acctAddr);
|
|
1738
1923
|
const checkAmount = repayShares > 0n && repayAssets === 0n ? approveAmount * 1005n / 1000n : approveAmount;
|
|
1739
1924
|
if (acctBalance < checkAmount) {
|
|
@@ -1752,7 +1937,7 @@ var init_MorphoClient = __esm({
|
|
|
1752
1937
|
const loanInfo = this._tokenCache.get(loanTokenAddr.toLowerCase());
|
|
1753
1938
|
const loanSymbol = loanInfo?.symbol ?? "loan token";
|
|
1754
1939
|
throw new AgetherError(
|
|
1755
|
-
`Insufficient ${loanSymbol} for repay. Need ~${
|
|
1940
|
+
`Insufficient ${loanSymbol} for repay. Need ~${import_ethers2.ethers.formatUnits(checkAmount, loanDecimals)}, AgentAccount has ${import_ethers2.ethers.formatUnits(acctBalance, loanDecimals)}, EOA has ${import_ethers2.ethers.formatUnits(eoaBalance, loanDecimals)}.`,
|
|
1756
1941
|
"INSUFFICIENT_BALANCE"
|
|
1757
1942
|
);
|
|
1758
1943
|
}
|
|
@@ -1774,7 +1959,7 @@ var init_MorphoClient = __esm({
|
|
|
1774
1959
|
"0x"
|
|
1775
1960
|
])
|
|
1776
1961
|
];
|
|
1777
|
-
const receipt = await this.
|
|
1962
|
+
const receipt = await this.executeBatch(targets, values, datas);
|
|
1778
1963
|
let remainingDebt = "0";
|
|
1779
1964
|
try {
|
|
1780
1965
|
const markets = await this.getMarkets(true);
|
|
@@ -1789,7 +1974,7 @@ var init_MorphoClient = __esm({
|
|
|
1789
1974
|
const totalAssets = BigInt(onChainMkt.totalBorrowAssets);
|
|
1790
1975
|
const totalShares = BigInt(onChainMkt.totalBorrowShares);
|
|
1791
1976
|
const debtWei = totalShares > 0n ? shares * totalAssets / totalShares : 0n;
|
|
1792
|
-
remainingDebt =
|
|
1977
|
+
remainingDebt = import_ethers2.ethers.formatUnits(debtWei, loanDecimals);
|
|
1793
1978
|
}
|
|
1794
1979
|
}
|
|
1795
1980
|
} catch (e) {
|
|
@@ -1961,7 +2146,7 @@ var init_MorphoClient = __esm({
|
|
|
1961
2146
|
weiAmount = pos.collateral;
|
|
1962
2147
|
if (weiAmount === 0n) throw new AgetherError("No collateral to withdraw", "NO_COLLATERAL");
|
|
1963
2148
|
} else {
|
|
1964
|
-
weiAmount =
|
|
2149
|
+
weiAmount = import_ethers2.ethers.parseUnits(amount, colInfo.decimals);
|
|
1965
2150
|
}
|
|
1966
2151
|
let hasDustDebt = false;
|
|
1967
2152
|
let dustBorrowShares = 0n;
|
|
@@ -1976,10 +2161,10 @@ var init_MorphoClient = __esm({
|
|
|
1976
2161
|
const totalBorrowAssets = BigInt(onChainMkt.totalBorrowAssets);
|
|
1977
2162
|
const totalBorrowShares = BigInt(onChainMkt.totalBorrowShares);
|
|
1978
2163
|
const estimated = totalBorrowShares > 0n ? dustBorrowShares * totalBorrowAssets / totalBorrowShares + 10n : 0n;
|
|
1979
|
-
dustApproveAmount = estimated > 0n ? estimated :
|
|
2164
|
+
dustApproveAmount = estimated > 0n ? estimated : import_ethers2.ethers.parseUnits("1", loanDecimals);
|
|
1980
2165
|
const loanInfo = this._tokenCache.get(loanTokenAddr.toLowerCase());
|
|
1981
2166
|
const loanSymbol = loanInfo?.symbol ?? "loan token";
|
|
1982
|
-
console.log(`[agether] dust borrow shares detected: ${dustBorrowShares} shares \u2248 ${
|
|
2167
|
+
console.log(`[agether] dust borrow shares detected: ${dustBorrowShares} shares \u2248 ${import_ethers2.ethers.formatUnits(dustApproveAmount, loanDecimals)} ${loanSymbol} \u2014 auto-repaying before withdraw`);
|
|
1983
2168
|
}
|
|
1984
2169
|
} catch (e) {
|
|
1985
2170
|
console.warn("[agether] failed to check borrow shares before withdraw:", e instanceof Error ? e.message : e);
|
|
@@ -1993,7 +2178,7 @@ var init_MorphoClient = __esm({
|
|
|
1993
2178
|
]);
|
|
1994
2179
|
let receipt;
|
|
1995
2180
|
if (hasDustDebt) {
|
|
1996
|
-
const loanContract = new
|
|
2181
|
+
const loanContract = new import_ethers2.Contract(loanTokenAddr, ERC20_ABI, this._signer);
|
|
1997
2182
|
const acctBalance = await loanContract.balanceOf(acctAddr);
|
|
1998
2183
|
if (acctBalance < dustApproveAmount) {
|
|
1999
2184
|
const shortfall = dustApproveAmount - acctBalance;
|
|
@@ -2001,7 +2186,7 @@ var init_MorphoClient = __esm({
|
|
|
2001
2186
|
if (eoaBalance >= shortfall) {
|
|
2002
2187
|
const loanInfo = this._tokenCache.get(loanTokenAddr.toLowerCase());
|
|
2003
2188
|
const loanSymbol = loanInfo?.symbol ?? "loan token";
|
|
2004
|
-
console.log(`[agether] transferring ${
|
|
2189
|
+
console.log(`[agether] transferring ${import_ethers2.ethers.formatUnits(shortfall, loanDecimals)} ${loanSymbol} from EOA \u2192 AgentAccount for dust repay`);
|
|
2005
2190
|
const transferTx = await loanContract.transfer(acctAddr, shortfall);
|
|
2006
2191
|
await transferTx.wait();
|
|
2007
2192
|
this._refreshSigner();
|
|
@@ -2020,15 +2205,15 @@ var init_MorphoClient = __esm({
|
|
|
2020
2205
|
]),
|
|
2021
2206
|
withdrawData
|
|
2022
2207
|
];
|
|
2023
|
-
receipt = await this.
|
|
2208
|
+
receipt = await this.executeBatch(targets, values, datas);
|
|
2024
2209
|
} else {
|
|
2025
|
-
receipt = await this.
|
|
2210
|
+
receipt = await this.executeSingle(morphoAddr, withdrawData);
|
|
2026
2211
|
}
|
|
2027
2212
|
let remainingCollateral = "0";
|
|
2028
2213
|
try {
|
|
2029
2214
|
if (market) {
|
|
2030
2215
|
const pos = await this.morphoBlue.position(market.uniqueKey, acctAddr);
|
|
2031
|
-
remainingCollateral =
|
|
2216
|
+
remainingCollateral = import_ethers2.ethers.formatUnits(pos.collateral, colInfo.decimals);
|
|
2032
2217
|
}
|
|
2033
2218
|
} catch (e) {
|
|
2034
2219
|
console.warn("[agether] failed to read remaining collateral after withdraw:", e instanceof Error ? e.message : e);
|
|
@@ -2036,7 +2221,7 @@ var init_MorphoClient = __esm({
|
|
|
2036
2221
|
return {
|
|
2037
2222
|
tx: receipt.hash,
|
|
2038
2223
|
token: tokenSymbol,
|
|
2039
|
-
amount: amount === "all" ?
|
|
2224
|
+
amount: amount === "all" ? import_ethers2.ethers.formatUnits(weiAmount, colInfo.decimals) : amount,
|
|
2040
2225
|
remainingCollateral,
|
|
2041
2226
|
destination: dest
|
|
2042
2227
|
};
|
|
@@ -2060,138 +2245,98 @@ var init_MorphoClient = __esm({
|
|
|
2060
2245
|
_refreshSigner() {
|
|
2061
2246
|
if (this._useExternalSigner) {
|
|
2062
2247
|
const addrs = this.config.contracts;
|
|
2063
|
-
this.agether4337Factory = new
|
|
2064
|
-
this.entryPoint = new
|
|
2248
|
+
this.agether4337Factory = new import_ethers2.Contract(addrs.agether4337Factory, ACCOUNT_FACTORY_ABI, this._signer);
|
|
2249
|
+
this.entryPoint = new import_ethers2.Contract(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
|
|
2065
2250
|
} else {
|
|
2066
|
-
this.provider = new
|
|
2067
|
-
const wallet = new
|
|
2251
|
+
this.provider = new import_ethers2.ethers.JsonRpcProvider(this._rpcUrl);
|
|
2252
|
+
const wallet = new import_ethers2.ethers.Wallet(this._privateKey, this.provider);
|
|
2068
2253
|
this._signer = wallet;
|
|
2069
2254
|
this._eoaAddress = wallet.address;
|
|
2070
2255
|
const addrs = this.config.contracts;
|
|
2071
|
-
this.agether4337Factory = new
|
|
2072
|
-
this.entryPoint = new
|
|
2256
|
+
this.agether4337Factory = new import_ethers2.Contract(addrs.agether4337Factory, ACCOUNT_FACTORY_ABI, this._signer);
|
|
2257
|
+
this.entryPoint = new import_ethers2.Contract(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
|
|
2073
2258
|
}
|
|
2074
2259
|
}
|
|
2075
2260
|
// ────────────────────────────────────────────────────────────
|
|
2076
2261
|
// ERC-4337 UserOp helpers (Safe + Safe7579 + EntryPoint v0.7)
|
|
2077
2262
|
// ────────────────────────────────────────────────────────────
|
|
2078
2263
|
/**
|
|
2079
|
-
*
|
|
2080
|
-
*
|
|
2264
|
+
* Repay all debt and withdraw all collateral in one atomic batch.
|
|
2265
|
+
* Full position exit: approve + repay(shares) + withdrawCollateral → 1 UserOp.
|
|
2081
2266
|
*/
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
const
|
|
2096
|
-
const
|
|
2097
|
-
const
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
const
|
|
2102
|
-
const
|
|
2103
|
-
const
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
this.
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
gasFees,
|
|
2125
|
-
paymasterAndData: "0x",
|
|
2126
|
-
signature: "0x"
|
|
2127
|
-
// placeholder — replaced after signing
|
|
2128
|
-
};
|
|
2129
|
-
const userOpHash = await this.entryPoint.getUserOpHash(userOp);
|
|
2130
|
-
const signature = await this._signer.signMessage(import_ethers.ethers.getBytes(userOpHash));
|
|
2131
|
-
userOp.signature = signature;
|
|
2132
|
-
const tx = await this.entryPoint.handleOps([userOp], await this.getSignerAddress());
|
|
2133
|
-
const receipt = await tx.wait();
|
|
2134
|
-
this._refreshSigner();
|
|
2135
|
-
const epIface = new import_ethers.ethers.Interface(ENTRYPOINT_V07_ABI);
|
|
2136
|
-
for (const log of receipt.logs) {
|
|
2137
|
-
try {
|
|
2138
|
-
const parsed = epIface.parseLog({ topics: log.topics, data: log.data });
|
|
2139
|
-
if (parsed?.name === "UserOperationEvent" && !parsed.args.success) {
|
|
2140
|
-
let revertMsg = "UserOp inner execution reverted";
|
|
2141
|
-
for (const rLog of receipt.logs) {
|
|
2142
|
-
try {
|
|
2143
|
-
const rParsed = epIface.parseLog({ topics: rLog.topics, data: rLog.data });
|
|
2144
|
-
if (rParsed?.name === "UserOperationRevertReason") {
|
|
2145
|
-
const reason = rParsed.args.revertReason;
|
|
2146
|
-
try {
|
|
2147
|
-
if (reason.length >= 10 && reason.slice(0, 10) === "0x08c379a0") {
|
|
2148
|
-
const decoded = import_ethers.ethers.AbiCoder.defaultAbiCoder().decode(["string"], "0x" + reason.slice(10));
|
|
2149
|
-
revertMsg = `UserOp reverted: ${decoded[0]}`;
|
|
2150
|
-
} else {
|
|
2151
|
-
revertMsg = `UserOp reverted with data: ${reason}`;
|
|
2152
|
-
}
|
|
2153
|
-
} catch {
|
|
2154
|
-
revertMsg = `UserOp reverted with data: ${reason}`;
|
|
2155
|
-
}
|
|
2156
|
-
break;
|
|
2157
|
-
}
|
|
2158
|
-
} catch {
|
|
2159
|
-
continue;
|
|
2160
|
-
}
|
|
2161
|
-
}
|
|
2162
|
-
throw new AgetherError(revertMsg, "USEROP_EXECUTION_FAILED");
|
|
2267
|
+
async repayAndWithdraw(tokenSymbol, loanTokenSymbol, toEoa = true) {
|
|
2268
|
+
const acctAddr = await this.getAccountAddress();
|
|
2269
|
+
const morphoAddr = this.config.contracts.morphoBlue;
|
|
2270
|
+
let params;
|
|
2271
|
+
let colSymbol;
|
|
2272
|
+
if (tokenSymbol) {
|
|
2273
|
+
params = await this.findMarketForCollateral(tokenSymbol, loanTokenSymbol);
|
|
2274
|
+
colSymbol = tokenSymbol;
|
|
2275
|
+
} else {
|
|
2276
|
+
const active = await this._findActiveMarket();
|
|
2277
|
+
params = active.params;
|
|
2278
|
+
colSymbol = active.symbol;
|
|
2279
|
+
}
|
|
2280
|
+
const colInfo = await this._resolveToken(colSymbol);
|
|
2281
|
+
const dest = toEoa ? await this.getSignerAddress() : acctAddr;
|
|
2282
|
+
const marketId = import_ethers2.ethers.keccak256(import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
|
|
2283
|
+
["address", "address", "address", "address", "uint256"],
|
|
2284
|
+
[params.loanToken, params.collateralToken, params.oracle, params.irm, params.lltv]
|
|
2285
|
+
));
|
|
2286
|
+
const pos = await this.morphoBlue.position(marketId, acctAddr);
|
|
2287
|
+
const borrowShares = BigInt(pos.borrowShares);
|
|
2288
|
+
const collateralAmount = BigInt(pos.collateral);
|
|
2289
|
+
if (collateralAmount === 0n) {
|
|
2290
|
+
throw new AgetherError("No collateral to withdraw", "NO_COLLATERAL");
|
|
2291
|
+
}
|
|
2292
|
+
const targets = [];
|
|
2293
|
+
const values = [];
|
|
2294
|
+
const datas = [];
|
|
2295
|
+
if (borrowShares > 0n) {
|
|
2296
|
+
const onChainMkt = await this.morphoBlue.market(marketId);
|
|
2297
|
+
const totalBorrowAssets = BigInt(onChainMkt.totalBorrowAssets);
|
|
2298
|
+
const totalBorrowShares = BigInt(onChainMkt.totalBorrowShares);
|
|
2299
|
+
const estimatedDebt = totalBorrowShares > 0n ? borrowShares * totalBorrowAssets / totalBorrowShares + 100n : 0n;
|
|
2300
|
+
const loanContract = new import_ethers2.Contract(params.loanToken, ERC20_ABI, this._signer);
|
|
2301
|
+
const acctBalance = await loanContract.balanceOf(acctAddr);
|
|
2302
|
+
if (acctBalance < estimatedDebt) {
|
|
2303
|
+
const shortfall = estimatedDebt - acctBalance;
|
|
2304
|
+
const eoaBalance = await loanContract.balanceOf(await this.getSignerAddress());
|
|
2305
|
+
if (eoaBalance >= shortfall) {
|
|
2306
|
+
const transferTx = await loanContract.transfer(acctAddr, shortfall);
|
|
2307
|
+
await transferTx.wait();
|
|
2308
|
+
this._refreshSigner();
|
|
2163
2309
|
}
|
|
2164
|
-
} catch (e) {
|
|
2165
|
-
if (e instanceof AgetherError) throw e;
|
|
2166
|
-
continue;
|
|
2167
2310
|
}
|
|
2311
|
+
targets.push(params.loanToken);
|
|
2312
|
+
values.push(0n);
|
|
2313
|
+
datas.push(erc20Iface.encodeFunctionData("approve", [morphoAddr, estimatedDebt]));
|
|
2314
|
+
targets.push(morphoAddr);
|
|
2315
|
+
values.push(0n);
|
|
2316
|
+
datas.push(morphoIface.encodeFunctionData("repay", [
|
|
2317
|
+
this._toTuple(params),
|
|
2318
|
+
0n,
|
|
2319
|
+
borrowShares,
|
|
2320
|
+
acctAddr,
|
|
2321
|
+
"0x"
|
|
2322
|
+
]));
|
|
2168
2323
|
}
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
const
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
*/
|
|
2186
|
-
async batch(targets, values, datas) {
|
|
2187
|
-
const executions = targets.map((t, i) => [t, values[i], datas[i]]);
|
|
2188
|
-
const executionCalldata = import_ethers.ethers.AbiCoder.defaultAbiCoder().encode(
|
|
2189
|
-
["(address,uint256,bytes)[]"],
|
|
2190
|
-
[executions]
|
|
2191
|
-
);
|
|
2192
|
-
const safe7579Iface = new import_ethers.ethers.Interface(SAFE7579_ACCOUNT_ABI);
|
|
2193
|
-
const callData = safe7579Iface.encodeFunctionData("execute", [MODE_BATCH, executionCalldata]);
|
|
2194
|
-
return this._submitUserOp(callData);
|
|
2324
|
+
targets.push(morphoAddr);
|
|
2325
|
+
values.push(0n);
|
|
2326
|
+
datas.push(morphoIface.encodeFunctionData("withdrawCollateral", [
|
|
2327
|
+
this._toTuple(params),
|
|
2328
|
+
collateralAmount,
|
|
2329
|
+
acctAddr,
|
|
2330
|
+
dest
|
|
2331
|
+
]));
|
|
2332
|
+
const receipt = await this.executeBatch(targets, values, datas);
|
|
2333
|
+
return {
|
|
2334
|
+
tx: receipt.hash,
|
|
2335
|
+
repaid: borrowShares > 0n ? "all" : "0",
|
|
2336
|
+
withdrawn: import_ethers2.ethers.formatUnits(collateralAmount, colInfo.decimals),
|
|
2337
|
+
collateralToken: colSymbol,
|
|
2338
|
+
loanToken: this._tokenCache.get(params.loanToken.toLowerCase())?.symbol ?? "unknown"
|
|
2339
|
+
};
|
|
2195
2340
|
}
|
|
2196
2341
|
/** Convert MorphoMarketParams to Solidity tuple. */
|
|
2197
2342
|
_toTuple(p) {
|
|
@@ -2242,7 +2387,7 @@ var init_MorphoClient = __esm({
|
|
|
2242
2387
|
}
|
|
2243
2388
|
const markets = await this.getMarkets();
|
|
2244
2389
|
for (const m of markets) {
|
|
2245
|
-
if (!m.collateralAsset || m.collateralAsset.address ===
|
|
2390
|
+
if (!m.collateralAsset || m.collateralAsset.address === import_ethers2.ethers.ZeroAddress) continue;
|
|
2246
2391
|
try {
|
|
2247
2392
|
const pos = await this.morphoBlue.position(m.uniqueKey, acctAddr);
|
|
2248
2393
|
if (pos.collateral > 0n) {
|
|
@@ -2310,7 +2455,7 @@ var init_MorphoClient = __esm({
|
|
|
2310
2455
|
}
|
|
2311
2456
|
const markets = await this.getMarkets();
|
|
2312
2457
|
for (const m of markets) {
|
|
2313
|
-
if (!m.collateralAsset || m.collateralAsset.address ===
|
|
2458
|
+
if (!m.collateralAsset || m.collateralAsset.address === import_ethers2.ethers.ZeroAddress) continue;
|
|
2314
2459
|
try {
|
|
2315
2460
|
const pos = await this.morphoBlue.position(m.uniqueKey, acctAddr);
|
|
2316
2461
|
if (BigInt(pos.supplyShares) > 0n) {
|
|
@@ -2471,17 +2616,17 @@ var AgetherClient_exports = {};
|
|
|
2471
2616
|
__export(AgetherClient_exports, {
|
|
2472
2617
|
AgetherClient: () => AgetherClient
|
|
2473
2618
|
});
|
|
2474
|
-
var
|
|
2619
|
+
var import_ethers3, import_axios2, MODE_SINGLE2, erc20Iface2, MORPHO_API_URL2, KNOWN_TOKENS, AgetherClient;
|
|
2475
2620
|
var init_AgetherClient = __esm({
|
|
2476
2621
|
"src/clients/AgetherClient.ts"() {
|
|
2477
2622
|
"use strict";
|
|
2478
|
-
|
|
2623
|
+
import_ethers3 = require("ethers");
|
|
2479
2624
|
import_axios2 = __toESM(require("axios"));
|
|
2480
2625
|
init_types();
|
|
2481
2626
|
init_abis();
|
|
2482
2627
|
init_config();
|
|
2483
2628
|
MODE_SINGLE2 = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
2484
|
-
erc20Iface2 = new
|
|
2629
|
+
erc20Iface2 = new import_ethers3.ethers.Interface(ERC20_ABI);
|
|
2485
2630
|
MORPHO_API_URL2 = "https://api.morpho.org/graphql";
|
|
2486
2631
|
KNOWN_TOKENS = {
|
|
2487
2632
|
[8453 /* Base */]: {
|
|
@@ -2524,11 +2669,11 @@ var init_AgetherClient = __esm({
|
|
|
2524
2669
|
this._eoaAddress = options.signer.address;
|
|
2525
2670
|
}
|
|
2526
2671
|
const c = options.config.contracts;
|
|
2527
|
-
this.agether4337Factory = new
|
|
2528
|
-
this.identityRegistry = new
|
|
2529
|
-
this.agether8004Scorer = new
|
|
2530
|
-
this.validationModule = new
|
|
2531
|
-
this.entryPoint = new
|
|
2672
|
+
this.agether4337Factory = new import_ethers3.Contract(c.agether4337Factory, AGETHER_4337_FACTORY_ABI, options.signer);
|
|
2673
|
+
this.identityRegistry = new import_ethers3.Contract(c.identityRegistry, IDENTITY_REGISTRY_ABI, options.signer);
|
|
2674
|
+
this.agether8004Scorer = new import_ethers3.Contract(c.agether8004Scorer, AGETHER_8004_SCORER_ABI, provider);
|
|
2675
|
+
this.validationModule = new import_ethers3.Contract(c.erc8004ValidationModule, AGETHER_8004_VALIDATION_MODULE_ABI, provider);
|
|
2676
|
+
this.entryPoint = new import_ethers3.Contract(c.entryPoint, ENTRYPOINT_V07_ABI, options.signer);
|
|
2532
2677
|
}
|
|
2533
2678
|
static fromPrivateKey(privateKey, agentIdOrChain, chainIdOrConfig) {
|
|
2534
2679
|
let agentId;
|
|
@@ -2539,8 +2684,8 @@ var init_AgetherClient = __esm({
|
|
|
2539
2684
|
} else {
|
|
2540
2685
|
config = typeof agentIdOrChain === "number" ? getDefaultConfig(agentIdOrChain) : agentIdOrChain;
|
|
2541
2686
|
}
|
|
2542
|
-
const provider = new
|
|
2543
|
-
const signer = new
|
|
2687
|
+
const provider = new import_ethers3.ethers.JsonRpcProvider(config.rpcUrl);
|
|
2688
|
+
const signer = new import_ethers3.ethers.Wallet(privateKey, provider);
|
|
2544
2689
|
return new _AgetherClient({ config, signer, agentId, _privateKey: privateKey });
|
|
2545
2690
|
}
|
|
2546
2691
|
static async fromSigner(signer, agentIdOrChain, chainIdOrConfig) {
|
|
@@ -2713,7 +2858,7 @@ var init_AgetherClient = __esm({
|
|
|
2713
2858
|
if (this.accountAddress) return this.accountAddress;
|
|
2714
2859
|
const id = this._requireAgentId();
|
|
2715
2860
|
const addr = await this.agether4337Factory.getAccount(id);
|
|
2716
|
-
if (addr ===
|
|
2861
|
+
if (addr === import_ethers3.ethers.ZeroAddress) {
|
|
2717
2862
|
throw new AgetherError(
|
|
2718
2863
|
"No account found. Create one with createAccount() or register().",
|
|
2719
2864
|
"NO_ACCOUNT"
|
|
@@ -2790,7 +2935,7 @@ var init_AgetherClient = __esm({
|
|
|
2790
2935
|
async getBalances() {
|
|
2791
2936
|
const provider = this.signer.provider;
|
|
2792
2937
|
const eoaAddr = await this._getSignerAddress();
|
|
2793
|
-
const usdc = new
|
|
2938
|
+
const usdc = new import_ethers3.Contract(this.config.contracts.usdc, ERC20_ABI, provider);
|
|
2794
2939
|
const ethBal = await provider.getBalance(eoaAddr);
|
|
2795
2940
|
const usdcBal = await usdc.balanceOf(eoaAddr);
|
|
2796
2941
|
const knownTokens = {
|
|
@@ -2808,9 +2953,9 @@ var init_AgetherClient = __esm({
|
|
|
2808
2953
|
const eoaCollateral = {};
|
|
2809
2954
|
for (const [symbol, info] of Object.entries(knownTokens)) {
|
|
2810
2955
|
try {
|
|
2811
|
-
const token = new
|
|
2956
|
+
const token = new import_ethers3.Contract(info.address, ERC20_ABI, provider);
|
|
2812
2957
|
const bal = await token.balanceOf(eoaAddr);
|
|
2813
|
-
eoaCollateral[symbol] =
|
|
2958
|
+
eoaCollateral[symbol] = import_ethers3.ethers.formatUnits(bal, info.decimals);
|
|
2814
2959
|
} catch (e) {
|
|
2815
2960
|
console.warn(`[agether] EOA collateral fetch failed for ${symbol}:`, e instanceof Error ? e.message : e);
|
|
2816
2961
|
eoaCollateral[symbol] = "0";
|
|
@@ -2819,8 +2964,8 @@ var init_AgetherClient = __esm({
|
|
|
2819
2964
|
const result = {
|
|
2820
2965
|
agentId: this.agentId !== void 0 ? this.agentId.toString() : "?",
|
|
2821
2966
|
address: eoaAddr,
|
|
2822
|
-
eth:
|
|
2823
|
-
usdc:
|
|
2967
|
+
eth: import_ethers3.ethers.formatEther(ethBal),
|
|
2968
|
+
usdc: import_ethers3.ethers.formatUnits(usdcBal, 6),
|
|
2824
2969
|
collateral: eoaCollateral
|
|
2825
2970
|
};
|
|
2826
2971
|
try {
|
|
@@ -2830,9 +2975,9 @@ var init_AgetherClient = __esm({
|
|
|
2830
2975
|
const acctCollateral = {};
|
|
2831
2976
|
for (const [symbol, info] of Object.entries(knownTokens)) {
|
|
2832
2977
|
try {
|
|
2833
|
-
const token = new
|
|
2978
|
+
const token = new import_ethers3.Contract(info.address, ERC20_ABI, provider);
|
|
2834
2979
|
const bal = await token.balanceOf(acctAddr);
|
|
2835
|
-
acctCollateral[symbol] =
|
|
2980
|
+
acctCollateral[symbol] = import_ethers3.ethers.formatUnits(bal, info.decimals);
|
|
2836
2981
|
} catch (e) {
|
|
2837
2982
|
console.warn(`[agether] Account collateral fetch failed for ${symbol}:`, e instanceof Error ? e.message : e);
|
|
2838
2983
|
acctCollateral[symbol] = "0";
|
|
@@ -2840,8 +2985,8 @@ var init_AgetherClient = __esm({
|
|
|
2840
2985
|
}
|
|
2841
2986
|
result.agentAccount = {
|
|
2842
2987
|
address: acctAddr,
|
|
2843
|
-
eth:
|
|
2844
|
-
usdc:
|
|
2988
|
+
eth: import_ethers3.ethers.formatEther(acctEth),
|
|
2989
|
+
usdc: import_ethers3.ethers.formatUnits(acctUsdc, 6),
|
|
2845
2990
|
collateral: acctCollateral
|
|
2846
2991
|
};
|
|
2847
2992
|
} catch (e) {
|
|
@@ -2866,7 +3011,7 @@ var init_AgetherClient = __esm({
|
|
|
2866
3011
|
const acctAddr = await this.getAccountAddress();
|
|
2867
3012
|
const eoaAddr = await this._getSignerAddress();
|
|
2868
3013
|
const tokenInfo = await this._resolveToken(tokenSymbol);
|
|
2869
|
-
const tokenContract = new
|
|
3014
|
+
const tokenContract = new import_ethers3.Contract(tokenInfo.address, ERC20_ABI, this.signer.provider);
|
|
2870
3015
|
let weiAmount;
|
|
2871
3016
|
if (amount === "all") {
|
|
2872
3017
|
weiAmount = await tokenContract.balanceOf(acctAddr);
|
|
@@ -2874,11 +3019,11 @@ var init_AgetherClient = __esm({
|
|
|
2874
3019
|
throw new AgetherError(`No ${tokenInfo.symbol} in Safe account`, "INSUFFICIENT_BALANCE");
|
|
2875
3020
|
}
|
|
2876
3021
|
} else {
|
|
2877
|
-
weiAmount =
|
|
3022
|
+
weiAmount = import_ethers3.ethers.parseUnits(amount, tokenInfo.decimals);
|
|
2878
3023
|
}
|
|
2879
3024
|
const data = erc20Iface2.encodeFunctionData("transfer", [eoaAddr, weiAmount]);
|
|
2880
3025
|
const receipt = await this._exec(tokenInfo.address, data);
|
|
2881
|
-
const actualAmount = amount === "all" ?
|
|
3026
|
+
const actualAmount = amount === "all" ? import_ethers3.ethers.formatUnits(weiAmount, tokenInfo.decimals) : amount;
|
|
2882
3027
|
return { tx: receipt.hash, token: tokenInfo.symbol, amount: actualAmount, destination: eoaAddr };
|
|
2883
3028
|
}
|
|
2884
3029
|
/**
|
|
@@ -2895,10 +3040,10 @@ var init_AgetherClient = __esm({
|
|
|
2895
3040
|
weiAmount = await this.signer.provider.getBalance(acctAddr);
|
|
2896
3041
|
if (weiAmount === 0n) throw new AgetherError("No ETH in Safe account", "INSUFFICIENT_BALANCE");
|
|
2897
3042
|
} else {
|
|
2898
|
-
weiAmount =
|
|
3043
|
+
weiAmount = import_ethers3.ethers.parseEther(amount);
|
|
2899
3044
|
}
|
|
2900
3045
|
const receipt = await this._exec(eoaAddr, "0x", weiAmount);
|
|
2901
|
-
const actualAmount = amount === "all" ?
|
|
3046
|
+
const actualAmount = amount === "all" ? import_ethers3.ethers.formatEther(weiAmount) : amount;
|
|
2902
3047
|
return { tx: receipt.hash, token: "ETH", amount: actualAmount, destination: eoaAddr };
|
|
2903
3048
|
}
|
|
2904
3049
|
// ════════════════════════════════════════════════════════
|
|
@@ -2914,12 +3059,12 @@ var init_AgetherClient = __esm({
|
|
|
2914
3059
|
async fundAccountToken(tokenSymbol, amount) {
|
|
2915
3060
|
const acctAddr = await this.getAccountAddress();
|
|
2916
3061
|
const tokenInfo = await this._resolveToken(tokenSymbol);
|
|
2917
|
-
const tokenContract = new
|
|
2918
|
-
const weiAmount =
|
|
3062
|
+
const tokenContract = new import_ethers3.Contract(tokenInfo.address, ERC20_ABI, this.signer);
|
|
3063
|
+
const weiAmount = import_ethers3.ethers.parseUnits(amount, tokenInfo.decimals);
|
|
2919
3064
|
const eoaBalance = await tokenContract.balanceOf(await this._getSignerAddress());
|
|
2920
3065
|
if (eoaBalance < weiAmount) {
|
|
2921
3066
|
throw new AgetherError(
|
|
2922
|
-
`Insufficient ${tokenInfo.symbol}. EOA has ${
|
|
3067
|
+
`Insufficient ${tokenInfo.symbol}. EOA has ${import_ethers3.ethers.formatUnits(eoaBalance, tokenInfo.decimals)}, need ${amount}.`,
|
|
2923
3068
|
"INSUFFICIENT_BALANCE"
|
|
2924
3069
|
);
|
|
2925
3070
|
}
|
|
@@ -2944,13 +3089,13 @@ var init_AgetherClient = __esm({
|
|
|
2944
3089
|
async transferToken(tokenSymbol, amount, to) {
|
|
2945
3090
|
const acctAddr = await this.getAccountAddress();
|
|
2946
3091
|
const tokenInfo = await this._resolveToken(tokenSymbol);
|
|
2947
|
-
const tokenContract = new
|
|
3092
|
+
const tokenContract = new import_ethers3.Contract(tokenInfo.address, ERC20_ABI, this.signer.provider);
|
|
2948
3093
|
let toAddr;
|
|
2949
3094
|
if (to.address) {
|
|
2950
3095
|
toAddr = to.address;
|
|
2951
3096
|
} else if (to.agentId) {
|
|
2952
3097
|
toAddr = await this.agether4337Factory.getAccount(BigInt(to.agentId));
|
|
2953
|
-
if (toAddr ===
|
|
3098
|
+
if (toAddr === import_ethers3.ethers.ZeroAddress) {
|
|
2954
3099
|
throw new AgetherError(`Agent ${to.agentId} has no account`, "NO_ACCOUNT");
|
|
2955
3100
|
}
|
|
2956
3101
|
} else {
|
|
@@ -2963,11 +3108,11 @@ var init_AgetherClient = __esm({
|
|
|
2963
3108
|
throw new AgetherError(`No ${tokenInfo.symbol} in AgentAccount`, "INSUFFICIENT_BALANCE");
|
|
2964
3109
|
}
|
|
2965
3110
|
} else {
|
|
2966
|
-
weiAmount =
|
|
3111
|
+
weiAmount = import_ethers3.ethers.parseUnits(amount, tokenInfo.decimals);
|
|
2967
3112
|
}
|
|
2968
3113
|
const data = erc20Iface2.encodeFunctionData("transfer", [toAddr, weiAmount]);
|
|
2969
3114
|
const receipt = await this._exec(tokenInfo.address, data);
|
|
2970
|
-
const actualAmount = amount === "all" ?
|
|
3115
|
+
const actualAmount = amount === "all" ? import_ethers3.ethers.formatUnits(weiAmount, tokenInfo.decimals) : amount;
|
|
2971
3116
|
return { tx: receipt.hash, token: tokenInfo.symbol, amount: actualAmount, destination: toAddr };
|
|
2972
3117
|
}
|
|
2973
3118
|
/**
|
|
@@ -2984,7 +3129,7 @@ var init_AgetherClient = __esm({
|
|
|
2984
3129
|
toAddr = to.address;
|
|
2985
3130
|
} else if (to.agentId) {
|
|
2986
3131
|
toAddr = await this.agether4337Factory.getAccount(BigInt(to.agentId));
|
|
2987
|
-
if (toAddr ===
|
|
3132
|
+
if (toAddr === import_ethers3.ethers.ZeroAddress) {
|
|
2988
3133
|
throw new AgetherError(`Agent ${to.agentId} has no account`, "NO_ACCOUNT");
|
|
2989
3134
|
}
|
|
2990
3135
|
} else {
|
|
@@ -2995,10 +3140,10 @@ var init_AgetherClient = __esm({
|
|
|
2995
3140
|
weiAmount = await this.signer.provider.getBalance(acctAddr);
|
|
2996
3141
|
if (weiAmount === 0n) throw new AgetherError("No ETH in AgentAccount", "INSUFFICIENT_BALANCE");
|
|
2997
3142
|
} else {
|
|
2998
|
-
weiAmount =
|
|
3143
|
+
weiAmount = import_ethers3.ethers.parseEther(amount);
|
|
2999
3144
|
}
|
|
3000
3145
|
const receipt = await this._exec(toAddr, "0x", weiAmount);
|
|
3001
|
-
const actualAmount = amount === "all" ?
|
|
3146
|
+
const actualAmount = amount === "all" ? import_ethers3.ethers.formatEther(weiAmount) : amount;
|
|
3002
3147
|
return { tx: receipt.hash, token: "ETH", amount: actualAmount, destination: toAddr };
|
|
3003
3148
|
}
|
|
3004
3149
|
/**
|
|
@@ -3016,7 +3161,7 @@ var init_AgetherClient = __esm({
|
|
|
3016
3161
|
spenderAddr = spender.address;
|
|
3017
3162
|
} else if (spender.agentId) {
|
|
3018
3163
|
spenderAddr = await this.agether4337Factory.getAccount(BigInt(spender.agentId));
|
|
3019
|
-
if (spenderAddr ===
|
|
3164
|
+
if (spenderAddr === import_ethers3.ethers.ZeroAddress) {
|
|
3020
3165
|
throw new AgetherError(`Agent ${spender.agentId} has no account`, "NO_ACCOUNT");
|
|
3021
3166
|
}
|
|
3022
3167
|
} else {
|
|
@@ -3024,9 +3169,9 @@ var init_AgetherClient = __esm({
|
|
|
3024
3169
|
}
|
|
3025
3170
|
let weiAmount;
|
|
3026
3171
|
if (amount === "max") {
|
|
3027
|
-
weiAmount =
|
|
3172
|
+
weiAmount = import_ethers3.ethers.MaxUint256;
|
|
3028
3173
|
} else {
|
|
3029
|
-
weiAmount =
|
|
3174
|
+
weiAmount = import_ethers3.ethers.parseUnits(amount, tokenInfo.decimals);
|
|
3030
3175
|
}
|
|
3031
3176
|
const data = erc20Iface2.encodeFunctionData("approve", [spenderAddr, weiAmount]);
|
|
3032
3177
|
const receipt = await this._exec(tokenInfo.address, data);
|
|
@@ -3051,14 +3196,14 @@ var init_AgetherClient = __esm({
|
|
|
3051
3196
|
targetAddr = target.address;
|
|
3052
3197
|
} else if (target.agentId) {
|
|
3053
3198
|
targetAddr = await this.agether4337Factory.getAccount(BigInt(target.agentId));
|
|
3054
|
-
if (targetAddr ===
|
|
3199
|
+
if (targetAddr === import_ethers3.ethers.ZeroAddress) {
|
|
3055
3200
|
throw new AgetherError("Target agent has no account", "NO_ACCOUNT");
|
|
3056
3201
|
}
|
|
3057
3202
|
} else {
|
|
3058
3203
|
throw new AgetherError("Provide agentId or address", "INVALID_TARGET");
|
|
3059
3204
|
}
|
|
3060
|
-
const weiAmount =
|
|
3061
|
-
const tokenContract = new
|
|
3205
|
+
const weiAmount = import_ethers3.ethers.parseUnits(amount, tokenInfo.decimals);
|
|
3206
|
+
const tokenContract = new import_ethers3.Contract(tokenInfo.address, ERC20_ABI, this.signer);
|
|
3062
3207
|
const tx = await tokenContract.transfer(targetAddr, weiAmount);
|
|
3063
3208
|
const receipt = await tx.wait();
|
|
3064
3209
|
this._refreshSigner();
|
|
@@ -3074,7 +3219,7 @@ var init_AgetherClient = __esm({
|
|
|
3074
3219
|
async isKyaRequired() {
|
|
3075
3220
|
try {
|
|
3076
3221
|
const registryAddr = await this.validationModule.validationRegistry();
|
|
3077
|
-
return registryAddr !==
|
|
3222
|
+
return registryAddr !== import_ethers3.ethers.ZeroAddress;
|
|
3078
3223
|
} catch {
|
|
3079
3224
|
return false;
|
|
3080
3225
|
}
|
|
@@ -3174,7 +3319,7 @@ var init_AgetherClient = __esm({
|
|
|
3174
3319
|
if (cached) return cached;
|
|
3175
3320
|
if (symbolOrAddress.startsWith("0x") && symbolOrAddress.length === 42) {
|
|
3176
3321
|
try {
|
|
3177
|
-
const token = new
|
|
3322
|
+
const token = new import_ethers3.Contract(
|
|
3178
3323
|
symbolOrAddress,
|
|
3179
3324
|
["function decimals() view returns (uint8)", "function symbol() view returns (string)"],
|
|
3180
3325
|
this.signer.provider
|
|
@@ -3249,17 +3394,17 @@ var init_AgetherClient = __esm({
|
|
|
3249
3394
|
*/
|
|
3250
3395
|
_refreshSigner() {
|
|
3251
3396
|
if (!this._useExternalSigner && this._privateKey) {
|
|
3252
|
-
const provider = new
|
|
3253
|
-
const wallet = new
|
|
3397
|
+
const provider = new import_ethers3.ethers.JsonRpcProvider(this._rpcUrl);
|
|
3398
|
+
const wallet = new import_ethers3.ethers.Wallet(this._privateKey, provider);
|
|
3254
3399
|
this.signer = wallet;
|
|
3255
3400
|
this._eoaAddress = wallet.address;
|
|
3256
3401
|
}
|
|
3257
3402
|
const c = this.config.contracts;
|
|
3258
|
-
this.agether4337Factory = new
|
|
3259
|
-
this.identityRegistry = new
|
|
3260
|
-
this.agether8004Scorer = new
|
|
3261
|
-
this.validationModule = new
|
|
3262
|
-
this.entryPoint = new
|
|
3403
|
+
this.agether4337Factory = new import_ethers3.Contract(c.agether4337Factory, AGETHER_4337_FACTORY_ABI, this.signer);
|
|
3404
|
+
this.identityRegistry = new import_ethers3.Contract(c.identityRegistry, IDENTITY_REGISTRY_ABI, this.signer);
|
|
3405
|
+
this.agether8004Scorer = new import_ethers3.Contract(c.agether8004Scorer, AGETHER_8004_SCORER_ABI, this.signer.provider);
|
|
3406
|
+
this.validationModule = new import_ethers3.Contract(c.erc8004ValidationModule, AGETHER_8004_VALIDATION_MODULE_ABI, this.signer.provider);
|
|
3407
|
+
this.entryPoint = new import_ethers3.Contract(c.entryPoint, ENTRYPOINT_V07_ABI, this.signer);
|
|
3263
3408
|
}
|
|
3264
3409
|
// ────────────────────────────────────────────────────────
|
|
3265
3410
|
// ERC-4337 UserOp helpers (Safe + Safe7579 + EntryPoint v0.7)
|
|
@@ -3269,7 +3414,7 @@ var init_AgetherClient = __esm({
|
|
|
3269
3414
|
* bytes32 = (hi << 128) | lo
|
|
3270
3415
|
*/
|
|
3271
3416
|
_packUint128(hi, lo) {
|
|
3272
|
-
return
|
|
3417
|
+
return import_ethers3.ethers.zeroPadValue(import_ethers3.ethers.toBeHex(hi << 128n | lo), 32);
|
|
3273
3418
|
}
|
|
3274
3419
|
/**
|
|
3275
3420
|
* Build, sign and submit a PackedUserOperation through EntryPoint.handleOps.
|
|
@@ -3281,8 +3426,8 @@ var init_AgetherClient = __esm({
|
|
|
3281
3426
|
const nonceKey = BigInt(validatorAddr) << 32n;
|
|
3282
3427
|
const nonce = await this.entryPoint.getNonce(sender, nonceKey);
|
|
3283
3428
|
const feeData = await this.signer.provider.getFeeData();
|
|
3284
|
-
const maxFeePerGas = feeData.maxFeePerGas ??
|
|
3285
|
-
const maxPriorityFeePerGas = feeData.maxPriorityFeePerGas ??
|
|
3429
|
+
const maxFeePerGas = feeData.maxFeePerGas ?? import_ethers3.ethers.parseUnits("0.5", "gwei");
|
|
3430
|
+
const maxPriorityFeePerGas = feeData.maxPriorityFeePerGas ?? import_ethers3.ethers.parseUnits("0.1", "gwei");
|
|
3286
3431
|
const verificationGasLimit = 500000n;
|
|
3287
3432
|
const callGasLimit = 800000n;
|
|
3288
3433
|
const preVerificationGas = 100000n;
|
|
@@ -3312,12 +3457,12 @@ var init_AgetherClient = __esm({
|
|
|
3312
3457
|
signature: "0x"
|
|
3313
3458
|
};
|
|
3314
3459
|
const userOpHash = await this.entryPoint.getUserOpHash(userOp);
|
|
3315
|
-
const signature = await this.signer.signMessage(
|
|
3460
|
+
const signature = await this.signer.signMessage(import_ethers3.ethers.getBytes(userOpHash));
|
|
3316
3461
|
userOp.signature = signature;
|
|
3317
3462
|
const tx = await this.entryPoint.handleOps([userOp], eoaAddr);
|
|
3318
3463
|
const receipt = await tx.wait();
|
|
3319
3464
|
this._refreshSigner();
|
|
3320
|
-
const epIface = new
|
|
3465
|
+
const epIface = new import_ethers3.ethers.Interface(ENTRYPOINT_V07_ABI);
|
|
3321
3466
|
for (const log of receipt.logs) {
|
|
3322
3467
|
try {
|
|
3323
3468
|
const parsed = epIface.parseLog({ topics: log.topics, data: log.data });
|
|
@@ -3330,7 +3475,7 @@ var init_AgetherClient = __esm({
|
|
|
3330
3475
|
const reason = rParsed.args.revertReason;
|
|
3331
3476
|
try {
|
|
3332
3477
|
if (reason.length >= 10 && reason.slice(0, 10) === "0x08c379a0") {
|
|
3333
|
-
const decoded =
|
|
3478
|
+
const decoded = import_ethers3.ethers.AbiCoder.defaultAbiCoder().decode(
|
|
3334
3479
|
["string"],
|
|
3335
3480
|
"0x" + reason.slice(10)
|
|
3336
3481
|
);
|
|
@@ -3361,9 +3506,9 @@ var init_AgetherClient = __esm({
|
|
|
3361
3506
|
* through an ERC-4337 UserOperation.
|
|
3362
3507
|
*/
|
|
3363
3508
|
async _exec(target, data, value = 0n) {
|
|
3364
|
-
const valueHex =
|
|
3365
|
-
const executionCalldata =
|
|
3366
|
-
const safe7579Iface = new
|
|
3509
|
+
const valueHex = import_ethers3.ethers.zeroPadValue(import_ethers3.ethers.toBeHex(value), 32);
|
|
3510
|
+
const executionCalldata = import_ethers3.ethers.concat([target, valueHex, data]);
|
|
3511
|
+
const safe7579Iface = new import_ethers3.ethers.Interface(SAFE7579_ACCOUNT_ABI);
|
|
3367
3512
|
const callData = safe7579Iface.encodeFunctionData("execute", [MODE_SINGLE2, executionCalldata]);
|
|
3368
3513
|
return this._submitUserOp(callData);
|
|
3369
3514
|
}
|
|
@@ -3737,7 +3882,7 @@ var init_X402Client = __esm({
|
|
|
3737
3882
|
});
|
|
3738
3883
|
|
|
3739
3884
|
// src/cli.ts
|
|
3740
|
-
var
|
|
3885
|
+
var import_ethers4 = require("ethers");
|
|
3741
3886
|
var fs = __toESM(require("fs"));
|
|
3742
3887
|
var path = __toESM(require("path"));
|
|
3743
3888
|
var os = __toESM(require("os"));
|
|
@@ -3862,7 +4007,7 @@ async function cmdInit(privateKey, agentId, chain) {
|
|
|
3862
4007
|
const rpcUrl = process.env.AGETHER_RPC_URL || CHAIN_RPC[chainId] || DEFAULT_RPC;
|
|
3863
4008
|
let wallet;
|
|
3864
4009
|
try {
|
|
3865
|
-
wallet = new
|
|
4010
|
+
wallet = new import_ethers4.ethers.Wallet(privateKey);
|
|
3866
4011
|
} catch {
|
|
3867
4012
|
console.error("\u274C Invalid private key");
|
|
3868
4013
|
process.exit(1);
|
|
@@ -3879,8 +4024,8 @@ async function cmdInit(privateKey, agentId, chain) {
|
|
|
3879
4024
|
}
|
|
3880
4025
|
async function cmdRegister(name) {
|
|
3881
4026
|
const config = requireConfig();
|
|
3882
|
-
const provider = new
|
|
3883
|
-
const signer = new
|
|
4027
|
+
const provider = new import_ethers4.ethers.JsonRpcProvider(config.rpcUrl);
|
|
4028
|
+
const signer = new import_ethers4.ethers.Wallet(config.privateKey, provider);
|
|
3884
4029
|
const agentName = name || `Agent-${signer.address.slice(0, 8)}`;
|
|
3885
4030
|
console.log(`\u{1F916} Registering agent: ${agentName}
|
|
3886
4031
|
`);
|
|
@@ -3903,7 +4048,7 @@ async function cmdRegister(name) {
|
|
|
3903
4048
|
process.exit(1);
|
|
3904
4049
|
}
|
|
3905
4050
|
console.log(" [2/4] Registering on ERC-8004 IdentityRegistry...");
|
|
3906
|
-
const agentRegistry = new
|
|
4051
|
+
const agentRegistry = new import_ethers4.ethers.Contract(registryAddr, ERC8004_ABI, signer);
|
|
3907
4052
|
let agentId;
|
|
3908
4053
|
if (config.agentId && config.agentId !== "0") {
|
|
3909
4054
|
agentId = BigInt(config.agentId);
|
|
@@ -3934,7 +4079,7 @@ async function cmdRegister(name) {
|
|
|
3934
4079
|
const agentURI = `data:application/json;base64,${Buffer.from(registrationFile).toString("base64")}`;
|
|
3935
4080
|
const tx = await agentRegistry["register(string)"](agentURI);
|
|
3936
4081
|
const receipt = await waitForTx(tx);
|
|
3937
|
-
const transferTopic =
|
|
4082
|
+
const transferTopic = import_ethers4.ethers.id("Transfer(address,address,uint256)");
|
|
3938
4083
|
const transferLog = receipt.logs.find((log) => log.topics[0] === transferTopic);
|
|
3939
4084
|
if (transferLog && transferLog.topics.length >= 4) {
|
|
3940
4085
|
agentId = BigInt(transferLog.topics[3]);
|
|
@@ -3967,11 +4112,11 @@ async function cmdRegister(name) {
|
|
|
3967
4112
|
if (chainId === 31337 || chainId === 1) {
|
|
3968
4113
|
console.log(" [3/4] Minting test USDC (Hardhat fork)...");
|
|
3969
4114
|
const deployerPk = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
|
|
3970
|
-
const deployer = new
|
|
4115
|
+
const deployer = new import_ethers4.ethers.Wallet(deployerPk, provider);
|
|
3971
4116
|
const usdcAddr = contracts.usdc;
|
|
3972
4117
|
if (usdcAddr) {
|
|
3973
4118
|
try {
|
|
3974
|
-
const usdc = new
|
|
4119
|
+
const usdc = new import_ethers4.ethers.Contract(usdcAddr, MOCK_ERC20_ABI, deployer);
|
|
3975
4120
|
const tx = await usdc.mint(signer.address, BigInt(5e10));
|
|
3976
4121
|
await waitForTx(tx);
|
|
3977
4122
|
console.log(" \u2713 Minted $50,000 USDC");
|
|
@@ -3984,7 +4129,7 @@ async function cmdRegister(name) {
|
|
|
3984
4129
|
}
|
|
3985
4130
|
console.log(" [4/4] Creating Safe account...");
|
|
3986
4131
|
if (factoryAddr) {
|
|
3987
|
-
const factory = new
|
|
4132
|
+
const factory = new import_ethers4.ethers.Contract(factoryAddr, ACCOUNT_FACTORY_ABI2, signer);
|
|
3988
4133
|
try {
|
|
3989
4134
|
const exists = await factory.accountExists(agentId);
|
|
3990
4135
|
if (exists) {
|
|
@@ -4002,7 +4147,7 @@ async function cmdRegister(name) {
|
|
|
4002
4147
|
}
|
|
4003
4148
|
}
|
|
4004
4149
|
if (validationAddr) {
|
|
4005
|
-
const vr = new
|
|
4150
|
+
const vr = new import_ethers4.ethers.Contract(validationAddr, VALIDATION_REGISTRY_ABI, provider);
|
|
4006
4151
|
try {
|
|
4007
4152
|
const approved = await vr.isAgentCodeApproved(agentId);
|
|
4008
4153
|
console.log(`
|
|
@@ -4223,7 +4368,7 @@ async function cmdX402Call(url, method = "GET", body) {
|
|
|
4223
4368
|
const config = requireConfig();
|
|
4224
4369
|
console.log("\n\u{1F510} x402 Paid API Call\n");
|
|
4225
4370
|
const x402 = await getX402Client(config);
|
|
4226
|
-
console.log(` Wallet: ${new
|
|
4371
|
+
console.log(` Wallet: ${new import_ethers4.ethers.Wallet(config.privateKey).address}`);
|
|
4227
4372
|
console.log(`
|
|
4228
4373
|
\u{1F4E1} ${method} ${url}`);
|
|
4229
4374
|
if (body) console.log(`\u{1F4E6} Body: ${body}`);
|