@agether/sdk 1.11.0 → 1.11.2
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 +72 -30
- package/dist/index.js +72 -30
- package/dist/index.mjs +72 -30
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -615,7 +615,7 @@ var init_MorphoClient = __esm({
|
|
|
615
615
|
const mkt = await this.morphoBlue.market(m.uniqueKey);
|
|
616
616
|
const totalBorrowShares = BigInt(mkt.totalBorrowShares);
|
|
617
617
|
const totalBorrowAssets = BigInt(mkt.totalBorrowAssets);
|
|
618
|
-
debt = totalBorrowShares > 0n ? BigInt(pos.borrowShares) * totalBorrowAssets / totalBorrowShares : 0n;
|
|
618
|
+
debt = totalBorrowShares > 0n ? (BigInt(pos.borrowShares) * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares : 0n;
|
|
619
619
|
totalDebt += debt;
|
|
620
620
|
} catch (e) {
|
|
621
621
|
console.warn(`[agether] debt calc failed for market ${m.uniqueKey}:`, e instanceof Error ? e.message : e);
|
|
@@ -677,7 +677,7 @@ var init_MorphoClient = __esm({
|
|
|
677
677
|
const mktState = await this.morphoBlue.market(m.uniqueKey);
|
|
678
678
|
const totalBorrowShares = BigInt(mktState.totalBorrowShares);
|
|
679
679
|
const totalBorrowAssets = BigInt(mktState.totalBorrowAssets);
|
|
680
|
-
const currentDebt = totalBorrowShares > 0n ? BigInt(pos.borrowShares) * totalBorrowAssets / totalBorrowShares : 0n;
|
|
680
|
+
const currentDebt = totalBorrowShares > 0n ? (BigInt(pos.borrowShares) * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares : 0n;
|
|
681
681
|
let collateralValueInLoan;
|
|
682
682
|
try {
|
|
683
683
|
const oracleContract = new import_ethers.Contract(m.oracle, [
|
|
@@ -989,26 +989,21 @@ var init_MorphoClient = __esm({
|
|
|
989
989
|
repayAssets = import_ethers.ethers.parseUnits(usdcAmount, 6);
|
|
990
990
|
repayShares = 0n;
|
|
991
991
|
approveAmount = repayAssets;
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
992
|
+
}
|
|
993
|
+
const usdcContract = new import_ethers.Contract(usdcAddr, ERC20_ABI, this._signer);
|
|
994
|
+
const acctBalance = await usdcContract.balanceOf(acctAddr);
|
|
995
|
+
if (acctBalance < approveAmount) {
|
|
996
|
+
const shortfall = approveAmount - acctBalance;
|
|
997
|
+
const eoaBalance = await usdcContract.balanceOf(await this.getSignerAddress());
|
|
998
|
+
if (eoaBalance < shortfall) {
|
|
999
|
+
throw new AgetherError(
|
|
1000
|
+
`Insufficient USDC for repay. Need ${import_ethers.ethers.formatUnits(approveAmount, 6)} USDC, AgentAccount has ${import_ethers.ethers.formatUnits(acctBalance, 6)}, EOA has ${import_ethers.ethers.formatUnits(eoaBalance, 6)}.`,
|
|
1001
|
+
"INSUFFICIENT_BALANCE"
|
|
996
1002
|
);
|
|
997
|
-
if (mkt) {
|
|
998
|
-
const pos = await this.morphoBlue.position(mkt.uniqueKey, acctAddr);
|
|
999
|
-
const onChainMkt = await this.morphoBlue.market(mkt.uniqueKey);
|
|
1000
|
-
const totalBorrowAssets = BigInt(onChainMkt.totalBorrowAssets);
|
|
1001
|
-
const totalBorrowShares = BigInt(onChainMkt.totalBorrowShares);
|
|
1002
|
-
const currentDebt = totalBorrowShares > 0n ? BigInt(pos.borrowShares) * totalBorrowAssets / totalBorrowShares : 0n;
|
|
1003
|
-
if (repayAssets >= currentDebt && BigInt(pos.borrowShares) > 0n) {
|
|
1004
|
-
repayShares = BigInt(pos.borrowShares);
|
|
1005
|
-
repayAssets = 0n;
|
|
1006
|
-
approveAmount = currentDebt + 10n;
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
} catch (e) {
|
|
1010
|
-
console.warn("[agether] share-based repay detection failed, falling through to asset-based:", e instanceof Error ? e.message : e);
|
|
1011
1003
|
}
|
|
1004
|
+
const transferTx = await usdcContract.transfer(acctAddr, shortfall);
|
|
1005
|
+
await transferTx.wait();
|
|
1006
|
+
this._refreshSigner();
|
|
1012
1007
|
}
|
|
1013
1008
|
const targets = [usdcAddr, morphoAddr];
|
|
1014
1009
|
const values = [0n, 0n];
|
|
@@ -1045,13 +1040,14 @@ var init_MorphoClient = __esm({
|
|
|
1045
1040
|
if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
|
|
1046
1041
|
const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
|
|
1047
1042
|
const morphoAddr = this.config.contracts.morphoBlue;
|
|
1043
|
+
const usdcAddr = this.config.contracts.usdc;
|
|
1048
1044
|
const dest = receiver || await this.getSignerAddress();
|
|
1049
1045
|
let weiAmount;
|
|
1046
|
+
const markets = await this.getMarkets();
|
|
1047
|
+
const market = markets.find(
|
|
1048
|
+
(m) => m.collateralAsset?.address.toLowerCase() === colInfo.address.toLowerCase()
|
|
1049
|
+
);
|
|
1050
1050
|
if (amount === "all") {
|
|
1051
|
-
const markets = await this.getMarkets();
|
|
1052
|
-
const market = markets.find(
|
|
1053
|
-
(m) => m.collateralAsset.address.toLowerCase() === colInfo.address.toLowerCase()
|
|
1054
|
-
);
|
|
1055
1051
|
if (!market) throw new AgetherError("Market not found", "MARKET_NOT_FOUND");
|
|
1056
1052
|
const pos = await this.morphoBlue.position(market.uniqueKey, acctAddr);
|
|
1057
1053
|
weiAmount = pos.collateral;
|
|
@@ -1059,19 +1055,65 @@ var init_MorphoClient = __esm({
|
|
|
1059
1055
|
} else {
|
|
1060
1056
|
weiAmount = import_ethers.ethers.parseUnits(amount, colInfo.decimals);
|
|
1061
1057
|
}
|
|
1062
|
-
|
|
1058
|
+
let hasDustDebt = false;
|
|
1059
|
+
let dustBorrowShares = 0n;
|
|
1060
|
+
let dustApproveAmount = 0n;
|
|
1061
|
+
if (market) {
|
|
1062
|
+
try {
|
|
1063
|
+
const pos = await this.morphoBlue.position(market.uniqueKey, acctAddr);
|
|
1064
|
+
dustBorrowShares = BigInt(pos.borrowShares);
|
|
1065
|
+
if (dustBorrowShares > 0n) {
|
|
1066
|
+
hasDustDebt = true;
|
|
1067
|
+
const onChainMkt = await this.morphoBlue.market(market.uniqueKey);
|
|
1068
|
+
const totalBorrowAssets = BigInt(onChainMkt.totalBorrowAssets);
|
|
1069
|
+
const totalBorrowShares = BigInt(onChainMkt.totalBorrowShares);
|
|
1070
|
+
const estimated = totalBorrowShares > 0n ? dustBorrowShares * totalBorrowAssets / totalBorrowShares + 10n : 0n;
|
|
1071
|
+
dustApproveAmount = estimated > 0n ? estimated : import_ethers.ethers.parseUnits("1", 6);
|
|
1072
|
+
console.log(`[agether] dust borrow shares detected: ${dustBorrowShares} shares \u2248 ${import_ethers.ethers.formatUnits(dustApproveAmount, 6)} USDC \u2014 auto-repaying before withdraw`);
|
|
1073
|
+
}
|
|
1074
|
+
} catch (e) {
|
|
1075
|
+
console.warn("[agether] failed to check borrow shares before withdraw:", e instanceof Error ? e.message : e);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
const withdrawData = morphoIface.encodeFunctionData("withdrawCollateral", [
|
|
1063
1079
|
this._toTuple(params),
|
|
1064
1080
|
weiAmount,
|
|
1065
1081
|
acctAddr,
|
|
1066
1082
|
dest
|
|
1067
1083
|
]);
|
|
1068
|
-
|
|
1084
|
+
let receipt;
|
|
1085
|
+
if (hasDustDebt) {
|
|
1086
|
+
const usdcContract = new import_ethers.Contract(usdcAddr, ERC20_ABI, this._signer);
|
|
1087
|
+
const acctBalance = await usdcContract.balanceOf(acctAddr);
|
|
1088
|
+
if (acctBalance < dustApproveAmount) {
|
|
1089
|
+
const shortfall = dustApproveAmount - acctBalance;
|
|
1090
|
+
const eoaBalance = await usdcContract.balanceOf(await this.getSignerAddress());
|
|
1091
|
+
if (eoaBalance >= shortfall) {
|
|
1092
|
+
console.log(`[agether] transferring ${import_ethers.ethers.formatUnits(shortfall, 6)} USDC from EOA \u2192 AgentAccount for dust repay`);
|
|
1093
|
+
const transferTx = await usdcContract.transfer(acctAddr, shortfall);
|
|
1094
|
+
await transferTx.wait();
|
|
1095
|
+
this._refreshSigner();
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
const targets = [usdcAddr, morphoAddr, morphoAddr];
|
|
1099
|
+
const values = [0n, 0n, 0n];
|
|
1100
|
+
const datas = [
|
|
1101
|
+
erc20Iface.encodeFunctionData("approve", [morphoAddr, dustApproveAmount]),
|
|
1102
|
+
morphoIface.encodeFunctionData("repay", [
|
|
1103
|
+
this._toTuple(params),
|
|
1104
|
+
0n,
|
|
1105
|
+
dustBorrowShares,
|
|
1106
|
+
acctAddr,
|
|
1107
|
+
"0x"
|
|
1108
|
+
]),
|
|
1109
|
+
withdrawData
|
|
1110
|
+
];
|
|
1111
|
+
receipt = await this.batch(targets, values, datas);
|
|
1112
|
+
} else {
|
|
1113
|
+
receipt = await this.exec(morphoAddr, withdrawData);
|
|
1114
|
+
}
|
|
1069
1115
|
let remainingCollateral = "0";
|
|
1070
1116
|
try {
|
|
1071
|
-
const markets = await this.getMarkets();
|
|
1072
|
-
const market = markets.find(
|
|
1073
|
-
(m) => m.collateralAsset.address.toLowerCase() === colInfo.address.toLowerCase()
|
|
1074
|
-
);
|
|
1075
1117
|
if (market) {
|
|
1076
1118
|
const pos = await this.morphoBlue.position(market.uniqueKey, acctAddr);
|
|
1077
1119
|
remainingCollateral = import_ethers.ethers.formatUnits(pos.collateral, colInfo.decimals);
|
package/dist/index.js
CHANGED
|
@@ -854,7 +854,7 @@ var MorphoClient = class {
|
|
|
854
854
|
const mkt = await this.morphoBlue.market(m.uniqueKey);
|
|
855
855
|
const totalBorrowShares = BigInt(mkt.totalBorrowShares);
|
|
856
856
|
const totalBorrowAssets = BigInt(mkt.totalBorrowAssets);
|
|
857
|
-
debt = totalBorrowShares > 0n ? BigInt(pos.borrowShares) * totalBorrowAssets / totalBorrowShares : 0n;
|
|
857
|
+
debt = totalBorrowShares > 0n ? (BigInt(pos.borrowShares) * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares : 0n;
|
|
858
858
|
totalDebt += debt;
|
|
859
859
|
} catch (e) {
|
|
860
860
|
console.warn(`[agether] debt calc failed for market ${m.uniqueKey}:`, e instanceof Error ? e.message : e);
|
|
@@ -916,7 +916,7 @@ var MorphoClient = class {
|
|
|
916
916
|
const mktState = await this.morphoBlue.market(m.uniqueKey);
|
|
917
917
|
const totalBorrowShares = BigInt(mktState.totalBorrowShares);
|
|
918
918
|
const totalBorrowAssets = BigInt(mktState.totalBorrowAssets);
|
|
919
|
-
const currentDebt = totalBorrowShares > 0n ? BigInt(pos.borrowShares) * totalBorrowAssets / totalBorrowShares : 0n;
|
|
919
|
+
const currentDebt = totalBorrowShares > 0n ? (BigInt(pos.borrowShares) * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares : 0n;
|
|
920
920
|
let collateralValueInLoan;
|
|
921
921
|
try {
|
|
922
922
|
const oracleContract = new import_ethers2.Contract(m.oracle, [
|
|
@@ -1228,26 +1228,21 @@ var MorphoClient = class {
|
|
|
1228
1228
|
repayAssets = import_ethers2.ethers.parseUnits(usdcAmount, 6);
|
|
1229
1229
|
repayShares = 0n;
|
|
1230
1230
|
approveAmount = repayAssets;
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1231
|
+
}
|
|
1232
|
+
const usdcContract = new import_ethers2.Contract(usdcAddr, ERC20_ABI, this._signer);
|
|
1233
|
+
const acctBalance = await usdcContract.balanceOf(acctAddr);
|
|
1234
|
+
if (acctBalance < approveAmount) {
|
|
1235
|
+
const shortfall = approveAmount - acctBalance;
|
|
1236
|
+
const eoaBalance = await usdcContract.balanceOf(await this.getSignerAddress());
|
|
1237
|
+
if (eoaBalance < shortfall) {
|
|
1238
|
+
throw new AgetherError(
|
|
1239
|
+
`Insufficient USDC for repay. Need ${import_ethers2.ethers.formatUnits(approveAmount, 6)} USDC, AgentAccount has ${import_ethers2.ethers.formatUnits(acctBalance, 6)}, EOA has ${import_ethers2.ethers.formatUnits(eoaBalance, 6)}.`,
|
|
1240
|
+
"INSUFFICIENT_BALANCE"
|
|
1235
1241
|
);
|
|
1236
|
-
if (mkt) {
|
|
1237
|
-
const pos = await this.morphoBlue.position(mkt.uniqueKey, acctAddr);
|
|
1238
|
-
const onChainMkt = await this.morphoBlue.market(mkt.uniqueKey);
|
|
1239
|
-
const totalBorrowAssets = BigInt(onChainMkt.totalBorrowAssets);
|
|
1240
|
-
const totalBorrowShares = BigInt(onChainMkt.totalBorrowShares);
|
|
1241
|
-
const currentDebt = totalBorrowShares > 0n ? BigInt(pos.borrowShares) * totalBorrowAssets / totalBorrowShares : 0n;
|
|
1242
|
-
if (repayAssets >= currentDebt && BigInt(pos.borrowShares) > 0n) {
|
|
1243
|
-
repayShares = BigInt(pos.borrowShares);
|
|
1244
|
-
repayAssets = 0n;
|
|
1245
|
-
approveAmount = currentDebt + 10n;
|
|
1246
|
-
}
|
|
1247
|
-
}
|
|
1248
|
-
} catch (e) {
|
|
1249
|
-
console.warn("[agether] share-based repay detection failed, falling through to asset-based:", e instanceof Error ? e.message : e);
|
|
1250
1242
|
}
|
|
1243
|
+
const transferTx = await usdcContract.transfer(acctAddr, shortfall);
|
|
1244
|
+
await transferTx.wait();
|
|
1245
|
+
this._refreshSigner();
|
|
1251
1246
|
}
|
|
1252
1247
|
const targets = [usdcAddr, morphoAddr];
|
|
1253
1248
|
const values = [0n, 0n];
|
|
@@ -1284,13 +1279,14 @@ var MorphoClient = class {
|
|
|
1284
1279
|
if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
|
|
1285
1280
|
const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
|
|
1286
1281
|
const morphoAddr = this.config.contracts.morphoBlue;
|
|
1282
|
+
const usdcAddr = this.config.contracts.usdc;
|
|
1287
1283
|
const dest = receiver || await this.getSignerAddress();
|
|
1288
1284
|
let weiAmount;
|
|
1285
|
+
const markets = await this.getMarkets();
|
|
1286
|
+
const market = markets.find(
|
|
1287
|
+
(m) => m.collateralAsset?.address.toLowerCase() === colInfo.address.toLowerCase()
|
|
1288
|
+
);
|
|
1289
1289
|
if (amount === "all") {
|
|
1290
|
-
const markets = await this.getMarkets();
|
|
1291
|
-
const market = markets.find(
|
|
1292
|
-
(m) => m.collateralAsset.address.toLowerCase() === colInfo.address.toLowerCase()
|
|
1293
|
-
);
|
|
1294
1290
|
if (!market) throw new AgetherError("Market not found", "MARKET_NOT_FOUND");
|
|
1295
1291
|
const pos = await this.morphoBlue.position(market.uniqueKey, acctAddr);
|
|
1296
1292
|
weiAmount = pos.collateral;
|
|
@@ -1298,19 +1294,65 @@ var MorphoClient = class {
|
|
|
1298
1294
|
} else {
|
|
1299
1295
|
weiAmount = import_ethers2.ethers.parseUnits(amount, colInfo.decimals);
|
|
1300
1296
|
}
|
|
1301
|
-
|
|
1297
|
+
let hasDustDebt = false;
|
|
1298
|
+
let dustBorrowShares = 0n;
|
|
1299
|
+
let dustApproveAmount = 0n;
|
|
1300
|
+
if (market) {
|
|
1301
|
+
try {
|
|
1302
|
+
const pos = await this.morphoBlue.position(market.uniqueKey, acctAddr);
|
|
1303
|
+
dustBorrowShares = BigInt(pos.borrowShares);
|
|
1304
|
+
if (dustBorrowShares > 0n) {
|
|
1305
|
+
hasDustDebt = true;
|
|
1306
|
+
const onChainMkt = await this.morphoBlue.market(market.uniqueKey);
|
|
1307
|
+
const totalBorrowAssets = BigInt(onChainMkt.totalBorrowAssets);
|
|
1308
|
+
const totalBorrowShares = BigInt(onChainMkt.totalBorrowShares);
|
|
1309
|
+
const estimated = totalBorrowShares > 0n ? dustBorrowShares * totalBorrowAssets / totalBorrowShares + 10n : 0n;
|
|
1310
|
+
dustApproveAmount = estimated > 0n ? estimated : import_ethers2.ethers.parseUnits("1", 6);
|
|
1311
|
+
console.log(`[agether] dust borrow shares detected: ${dustBorrowShares} shares \u2248 ${import_ethers2.ethers.formatUnits(dustApproveAmount, 6)} USDC \u2014 auto-repaying before withdraw`);
|
|
1312
|
+
}
|
|
1313
|
+
} catch (e) {
|
|
1314
|
+
console.warn("[agether] failed to check borrow shares before withdraw:", e instanceof Error ? e.message : e);
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
const withdrawData = morphoIface.encodeFunctionData("withdrawCollateral", [
|
|
1302
1318
|
this._toTuple(params),
|
|
1303
1319
|
weiAmount,
|
|
1304
1320
|
acctAddr,
|
|
1305
1321
|
dest
|
|
1306
1322
|
]);
|
|
1307
|
-
|
|
1323
|
+
let receipt;
|
|
1324
|
+
if (hasDustDebt) {
|
|
1325
|
+
const usdcContract = new import_ethers2.Contract(usdcAddr, ERC20_ABI, this._signer);
|
|
1326
|
+
const acctBalance = await usdcContract.balanceOf(acctAddr);
|
|
1327
|
+
if (acctBalance < dustApproveAmount) {
|
|
1328
|
+
const shortfall = dustApproveAmount - acctBalance;
|
|
1329
|
+
const eoaBalance = await usdcContract.balanceOf(await this.getSignerAddress());
|
|
1330
|
+
if (eoaBalance >= shortfall) {
|
|
1331
|
+
console.log(`[agether] transferring ${import_ethers2.ethers.formatUnits(shortfall, 6)} USDC from EOA \u2192 AgentAccount for dust repay`);
|
|
1332
|
+
const transferTx = await usdcContract.transfer(acctAddr, shortfall);
|
|
1333
|
+
await transferTx.wait();
|
|
1334
|
+
this._refreshSigner();
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
const targets = [usdcAddr, morphoAddr, morphoAddr];
|
|
1338
|
+
const values = [0n, 0n, 0n];
|
|
1339
|
+
const datas = [
|
|
1340
|
+
erc20Iface.encodeFunctionData("approve", [morphoAddr, dustApproveAmount]),
|
|
1341
|
+
morphoIface.encodeFunctionData("repay", [
|
|
1342
|
+
this._toTuple(params),
|
|
1343
|
+
0n,
|
|
1344
|
+
dustBorrowShares,
|
|
1345
|
+
acctAddr,
|
|
1346
|
+
"0x"
|
|
1347
|
+
]),
|
|
1348
|
+
withdrawData
|
|
1349
|
+
];
|
|
1350
|
+
receipt = await this.batch(targets, values, datas);
|
|
1351
|
+
} else {
|
|
1352
|
+
receipt = await this.exec(morphoAddr, withdrawData);
|
|
1353
|
+
}
|
|
1308
1354
|
let remainingCollateral = "0";
|
|
1309
1355
|
try {
|
|
1310
|
-
const markets = await this.getMarkets();
|
|
1311
|
-
const market = markets.find(
|
|
1312
|
-
(m) => m.collateralAsset.address.toLowerCase() === colInfo.address.toLowerCase()
|
|
1313
|
-
);
|
|
1314
1356
|
if (market) {
|
|
1315
1357
|
const pos = await this.morphoBlue.position(market.uniqueKey, acctAddr);
|
|
1316
1358
|
remainingCollateral = import_ethers2.ethers.formatUnits(pos.collateral, colInfo.decimals);
|
package/dist/index.mjs
CHANGED
|
@@ -789,7 +789,7 @@ var MorphoClient = class {
|
|
|
789
789
|
const mkt = await this.morphoBlue.market(m.uniqueKey);
|
|
790
790
|
const totalBorrowShares = BigInt(mkt.totalBorrowShares);
|
|
791
791
|
const totalBorrowAssets = BigInt(mkt.totalBorrowAssets);
|
|
792
|
-
debt = totalBorrowShares > 0n ? BigInt(pos.borrowShares) * totalBorrowAssets / totalBorrowShares : 0n;
|
|
792
|
+
debt = totalBorrowShares > 0n ? (BigInt(pos.borrowShares) * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares : 0n;
|
|
793
793
|
totalDebt += debt;
|
|
794
794
|
} catch (e) {
|
|
795
795
|
console.warn(`[agether] debt calc failed for market ${m.uniqueKey}:`, e instanceof Error ? e.message : e);
|
|
@@ -851,7 +851,7 @@ var MorphoClient = class {
|
|
|
851
851
|
const mktState = await this.morphoBlue.market(m.uniqueKey);
|
|
852
852
|
const totalBorrowShares = BigInt(mktState.totalBorrowShares);
|
|
853
853
|
const totalBorrowAssets = BigInt(mktState.totalBorrowAssets);
|
|
854
|
-
const currentDebt = totalBorrowShares > 0n ? BigInt(pos.borrowShares) * totalBorrowAssets / totalBorrowShares : 0n;
|
|
854
|
+
const currentDebt = totalBorrowShares > 0n ? (BigInt(pos.borrowShares) * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares : 0n;
|
|
855
855
|
let collateralValueInLoan;
|
|
856
856
|
try {
|
|
857
857
|
const oracleContract = new Contract2(m.oracle, [
|
|
@@ -1163,26 +1163,21 @@ var MorphoClient = class {
|
|
|
1163
1163
|
repayAssets = ethers2.parseUnits(usdcAmount, 6);
|
|
1164
1164
|
repayShares = 0n;
|
|
1165
1165
|
approveAmount = repayAssets;
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1166
|
+
}
|
|
1167
|
+
const usdcContract = new Contract2(usdcAddr, ERC20_ABI, this._signer);
|
|
1168
|
+
const acctBalance = await usdcContract.balanceOf(acctAddr);
|
|
1169
|
+
if (acctBalance < approveAmount) {
|
|
1170
|
+
const shortfall = approveAmount - acctBalance;
|
|
1171
|
+
const eoaBalance = await usdcContract.balanceOf(await this.getSignerAddress());
|
|
1172
|
+
if (eoaBalance < shortfall) {
|
|
1173
|
+
throw new AgetherError(
|
|
1174
|
+
`Insufficient USDC for repay. Need ${ethers2.formatUnits(approveAmount, 6)} USDC, AgentAccount has ${ethers2.formatUnits(acctBalance, 6)}, EOA has ${ethers2.formatUnits(eoaBalance, 6)}.`,
|
|
1175
|
+
"INSUFFICIENT_BALANCE"
|
|
1170
1176
|
);
|
|
1171
|
-
if (mkt) {
|
|
1172
|
-
const pos = await this.morphoBlue.position(mkt.uniqueKey, acctAddr);
|
|
1173
|
-
const onChainMkt = await this.morphoBlue.market(mkt.uniqueKey);
|
|
1174
|
-
const totalBorrowAssets = BigInt(onChainMkt.totalBorrowAssets);
|
|
1175
|
-
const totalBorrowShares = BigInt(onChainMkt.totalBorrowShares);
|
|
1176
|
-
const currentDebt = totalBorrowShares > 0n ? BigInt(pos.borrowShares) * totalBorrowAssets / totalBorrowShares : 0n;
|
|
1177
|
-
if (repayAssets >= currentDebt && BigInt(pos.borrowShares) > 0n) {
|
|
1178
|
-
repayShares = BigInt(pos.borrowShares);
|
|
1179
|
-
repayAssets = 0n;
|
|
1180
|
-
approveAmount = currentDebt + 10n;
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
} catch (e) {
|
|
1184
|
-
console.warn("[agether] share-based repay detection failed, falling through to asset-based:", e instanceof Error ? e.message : e);
|
|
1185
1177
|
}
|
|
1178
|
+
const transferTx = await usdcContract.transfer(acctAddr, shortfall);
|
|
1179
|
+
await transferTx.wait();
|
|
1180
|
+
this._refreshSigner();
|
|
1186
1181
|
}
|
|
1187
1182
|
const targets = [usdcAddr, morphoAddr];
|
|
1188
1183
|
const values = [0n, 0n];
|
|
@@ -1219,13 +1214,14 @@ var MorphoClient = class {
|
|
|
1219
1214
|
if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
|
|
1220
1215
|
const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
|
|
1221
1216
|
const morphoAddr = this.config.contracts.morphoBlue;
|
|
1217
|
+
const usdcAddr = this.config.contracts.usdc;
|
|
1222
1218
|
const dest = receiver || await this.getSignerAddress();
|
|
1223
1219
|
let weiAmount;
|
|
1220
|
+
const markets = await this.getMarkets();
|
|
1221
|
+
const market = markets.find(
|
|
1222
|
+
(m) => m.collateralAsset?.address.toLowerCase() === colInfo.address.toLowerCase()
|
|
1223
|
+
);
|
|
1224
1224
|
if (amount === "all") {
|
|
1225
|
-
const markets = await this.getMarkets();
|
|
1226
|
-
const market = markets.find(
|
|
1227
|
-
(m) => m.collateralAsset.address.toLowerCase() === colInfo.address.toLowerCase()
|
|
1228
|
-
);
|
|
1229
1225
|
if (!market) throw new AgetherError("Market not found", "MARKET_NOT_FOUND");
|
|
1230
1226
|
const pos = await this.morphoBlue.position(market.uniqueKey, acctAddr);
|
|
1231
1227
|
weiAmount = pos.collateral;
|
|
@@ -1233,19 +1229,65 @@ var MorphoClient = class {
|
|
|
1233
1229
|
} else {
|
|
1234
1230
|
weiAmount = ethers2.parseUnits(amount, colInfo.decimals);
|
|
1235
1231
|
}
|
|
1236
|
-
|
|
1232
|
+
let hasDustDebt = false;
|
|
1233
|
+
let dustBorrowShares = 0n;
|
|
1234
|
+
let dustApproveAmount = 0n;
|
|
1235
|
+
if (market) {
|
|
1236
|
+
try {
|
|
1237
|
+
const pos = await this.morphoBlue.position(market.uniqueKey, acctAddr);
|
|
1238
|
+
dustBorrowShares = BigInt(pos.borrowShares);
|
|
1239
|
+
if (dustBorrowShares > 0n) {
|
|
1240
|
+
hasDustDebt = true;
|
|
1241
|
+
const onChainMkt = await this.morphoBlue.market(market.uniqueKey);
|
|
1242
|
+
const totalBorrowAssets = BigInt(onChainMkt.totalBorrowAssets);
|
|
1243
|
+
const totalBorrowShares = BigInt(onChainMkt.totalBorrowShares);
|
|
1244
|
+
const estimated = totalBorrowShares > 0n ? dustBorrowShares * totalBorrowAssets / totalBorrowShares + 10n : 0n;
|
|
1245
|
+
dustApproveAmount = estimated > 0n ? estimated : ethers2.parseUnits("1", 6);
|
|
1246
|
+
console.log(`[agether] dust borrow shares detected: ${dustBorrowShares} shares \u2248 ${ethers2.formatUnits(dustApproveAmount, 6)} USDC \u2014 auto-repaying before withdraw`);
|
|
1247
|
+
}
|
|
1248
|
+
} catch (e) {
|
|
1249
|
+
console.warn("[agether] failed to check borrow shares before withdraw:", e instanceof Error ? e.message : e);
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
const withdrawData = morphoIface.encodeFunctionData("withdrawCollateral", [
|
|
1237
1253
|
this._toTuple(params),
|
|
1238
1254
|
weiAmount,
|
|
1239
1255
|
acctAddr,
|
|
1240
1256
|
dest
|
|
1241
1257
|
]);
|
|
1242
|
-
|
|
1258
|
+
let receipt;
|
|
1259
|
+
if (hasDustDebt) {
|
|
1260
|
+
const usdcContract = new Contract2(usdcAddr, ERC20_ABI, this._signer);
|
|
1261
|
+
const acctBalance = await usdcContract.balanceOf(acctAddr);
|
|
1262
|
+
if (acctBalance < dustApproveAmount) {
|
|
1263
|
+
const shortfall = dustApproveAmount - acctBalance;
|
|
1264
|
+
const eoaBalance = await usdcContract.balanceOf(await this.getSignerAddress());
|
|
1265
|
+
if (eoaBalance >= shortfall) {
|
|
1266
|
+
console.log(`[agether] transferring ${ethers2.formatUnits(shortfall, 6)} USDC from EOA \u2192 AgentAccount for dust repay`);
|
|
1267
|
+
const transferTx = await usdcContract.transfer(acctAddr, shortfall);
|
|
1268
|
+
await transferTx.wait();
|
|
1269
|
+
this._refreshSigner();
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
const targets = [usdcAddr, morphoAddr, morphoAddr];
|
|
1273
|
+
const values = [0n, 0n, 0n];
|
|
1274
|
+
const datas = [
|
|
1275
|
+
erc20Iface.encodeFunctionData("approve", [morphoAddr, dustApproveAmount]),
|
|
1276
|
+
morphoIface.encodeFunctionData("repay", [
|
|
1277
|
+
this._toTuple(params),
|
|
1278
|
+
0n,
|
|
1279
|
+
dustBorrowShares,
|
|
1280
|
+
acctAddr,
|
|
1281
|
+
"0x"
|
|
1282
|
+
]),
|
|
1283
|
+
withdrawData
|
|
1284
|
+
];
|
|
1285
|
+
receipt = await this.batch(targets, values, datas);
|
|
1286
|
+
} else {
|
|
1287
|
+
receipt = await this.exec(morphoAddr, withdrawData);
|
|
1288
|
+
}
|
|
1243
1289
|
let remainingCollateral = "0";
|
|
1244
1290
|
try {
|
|
1245
|
-
const markets = await this.getMarkets();
|
|
1246
|
-
const market = markets.find(
|
|
1247
|
-
(m) => m.collateralAsset.address.toLowerCase() === colInfo.address.toLowerCase()
|
|
1248
|
-
);
|
|
1249
1291
|
if (market) {
|
|
1250
1292
|
const pos = await this.morphoBlue.position(market.uniqueKey, acctAddr);
|
|
1251
1293
|
remainingCollateral = ethers2.formatUnits(pos.collateral, colInfo.decimals);
|