@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 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
- try {
993
- const markets = await this.getMarkets();
994
- const mkt = markets.find(
995
- (m) => m.collateralAsset?.address.toLowerCase() === params.collateralToken.toLowerCase()
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
- const data = morphoIface.encodeFunctionData("withdrawCollateral", [
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
- const receipt = await this.exec(morphoAddr, data);
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
- try {
1232
- const markets = await this.getMarkets();
1233
- const mkt = markets.find(
1234
- (m) => m.collateralAsset?.address.toLowerCase() === params.collateralToken.toLowerCase()
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
- const data = morphoIface.encodeFunctionData("withdrawCollateral", [
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
- const receipt = await this.exec(morphoAddr, data);
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
- try {
1167
- const markets = await this.getMarkets();
1168
- const mkt = markets.find(
1169
- (m) => m.collateralAsset?.address.toLowerCase() === params.collateralToken.toLowerCase()
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
- const data = morphoIface.encodeFunctionData("withdrawCollateral", [
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
- const receipt = await this.exec(morphoAddr, data);
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agether/sdk",
3
- "version": "1.11.0",
3
+ "version": "1.11.2",
4
4
  "description": "TypeScript SDK for Agether - autonomous credit for AI agents on Base",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",