@hypurrquant/defi-cli 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -986,6 +986,7 @@ var init_dist2 = __esm({
986
986
  TxStatus2["DryRun"] = "dry_run";
987
987
  TxStatus2["Simulated"] = "simulated";
988
988
  TxStatus2["SimulationFailed"] = "simulation_failed";
989
+ TxStatus2["NeedsApproval"] = "needs_approval";
989
990
  TxStatus2["Pending"] = "pending";
990
991
  TxStatus2["Confirmed"] = "confirmed";
991
992
  TxStatus2["Failed"] = "failed";
@@ -1235,6 +1236,7 @@ __export(dist_exports2, {
1235
1236
  HlpVaultAdapter: () => HlpVaultAdapter,
1236
1237
  KinetiqAdapter: () => KinetiqAdapter,
1237
1238
  MasterChefAdapter: () => MasterChefAdapter,
1239
+ MerchantMoeLBAdapter: () => MerchantMoeLBAdapter,
1238
1240
  MorphoBlueAdapter: () => MorphoBlueAdapter,
1239
1241
  PendleAdapter: () => PendleAdapter,
1240
1242
  RyskAdapter: () => RyskAdapter,
@@ -1251,6 +1253,7 @@ __export(dist_exports2, {
1251
1253
  createLending: () => createLending,
1252
1254
  createLiquidStaking: () => createLiquidStaking,
1253
1255
  createMasterChef: () => createMasterChef,
1256
+ createMerchantMoeLB: () => createMerchantMoeLB,
1254
1257
  createNft: () => createNft,
1255
1258
  createOptions: () => createOptions,
1256
1259
  createOracleFromCdp: () => createOracleFromCdp,
@@ -1263,31 +1266,169 @@ import { encodeFunctionData as encodeFunctionData22, parseAbi as parseAbi22, cre
1263
1266
  import { encodeFunctionData as encodeFunctionData32, parseAbi as parseAbi32, createPublicClient as createPublicClient3, http as http3, decodeAbiParameters as decodeAbiParameters3, concatHex, zeroAddress } from "viem";
1264
1267
  import { encodeFunctionData as encodeFunctionData4, parseAbi as parseAbi4, zeroAddress as zeroAddress2 } from "viem";
1265
1268
  import { encodeFunctionData as encodeFunctionData5, parseAbi as parseAbi5 } from "viem";
1266
- import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6, createPublicClient as createPublicClient4, http as http4, decodeAbiParameters as decodeAbiParameters4 } from "viem";
1269
+ import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6, decodeAbiParameters as decodeAbiParameters4 } from "viem";
1267
1270
  import { encodeFunctionData as encodeFunctionData7, parseAbi as parseAbi7, zeroAddress as zeroAddress3 } from "viem";
1268
- import { createPublicClient as createPublicClient5, encodeFunctionData as encodeFunctionData8, http as http5, parseAbi as parseAbi8, zeroAddress as zeroAddress4 } from "viem";
1269
- import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9, createPublicClient as createPublicClient6, http as http6 } from "viem";
1270
- import { createPublicClient as createPublicClient7, http as http7, parseAbi as parseAbi10, encodeFunctionData as encodeFunctionData10, zeroAddress as zeroAddress5 } from "viem";
1271
- import { createPublicClient as createPublicClient8, http as http8, parseAbi as parseAbi11, encodeFunctionData as encodeFunctionData11, zeroAddress as zeroAddress6 } from "viem";
1272
- import { createPublicClient as createPublicClient9, http as http9, parseAbi as parseAbi12 } from "viem";
1273
- import { createPublicClient as createPublicClient10, http as http10, parseAbi as parseAbi13, encodeFunctionData as encodeFunctionData12 } from "viem";
1274
- import { createPublicClient as createPublicClient11, http as http11, parseAbi as parseAbi14, encodeFunctionData as encodeFunctionData13 } from "viem";
1275
- import { createPublicClient as createPublicClient12, http as http12, parseAbi as parseAbi15, encodeFunctionData as encodeFunctionData14 } from "viem";
1276
- import { createPublicClient as createPublicClient13, http as http13, parseAbi as parseAbi16, encodeFunctionData as encodeFunctionData15, zeroAddress as zeroAddress7 } from "viem";
1277
- import { createPublicClient as createPublicClient14, http as http14, parseAbi as parseAbi17, encodeFunctionData as encodeFunctionData16, zeroAddress as zeroAddress8 } from "viem";
1278
- import { createPublicClient as createPublicClient15, http as http15, parseAbi as parseAbi18 } from "viem";
1279
- import { createPublicClient as createPublicClient16, http as http16, parseAbi as parseAbi19, encodeFunctionData as encodeFunctionData17 } from "viem";
1280
- import { parseAbi as parseAbi20, encodeFunctionData as encodeFunctionData18 } from "viem";
1281
- import { createPublicClient as createPublicClient17, http as http17, parseAbi as parseAbi21, encodeFunctionData as encodeFunctionData19, zeroAddress as zeroAddress9 } from "viem";
1282
- import { createPublicClient as createPublicClient18, http as http18, parseAbi as parseAbi222, encodeFunctionData as encodeFunctionData20, zeroAddress as zeroAddress10 } from "viem";
1283
- import { parseAbi as parseAbi23, encodeFunctionData as encodeFunctionData21 } from "viem";
1271
+ import { createPublicClient as createPublicClient4, encodeFunctionData as encodeFunctionData8, http as http4, parseAbi as parseAbi8, zeroAddress as zeroAddress4 } from "viem";
1272
+ import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9, createPublicClient as createPublicClient5, http as http5 } from "viem";
1273
+ import {
1274
+ encodeFunctionData as encodeFunctionData10,
1275
+ decodeFunctionResult as decodeFunctionResult22,
1276
+ parseAbi as parseAbi10,
1277
+ createPublicClient as createPublicClient6,
1278
+ http as http6
1279
+ } from "viem";
1280
+ import { createPublicClient as createPublicClient7, http as http7, parseAbi as parseAbi11, encodeFunctionData as encodeFunctionData11, decodeFunctionResult as decodeFunctionResult3, zeroAddress as zeroAddress5 } from "viem";
1281
+ import { createPublicClient as createPublicClient8, http as http8, parseAbi as parseAbi12, encodeFunctionData as encodeFunctionData12, zeroAddress as zeroAddress6 } from "viem";
1282
+ import { createPublicClient as createPublicClient9, http as http9, parseAbi as parseAbi13 } from "viem";
1283
+ import { createPublicClient as createPublicClient10, http as http10, parseAbi as parseAbi14, encodeFunctionData as encodeFunctionData13 } from "viem";
1284
+ import { createPublicClient as createPublicClient11, http as http11, parseAbi as parseAbi15, encodeFunctionData as encodeFunctionData14 } from "viem";
1285
+ import { createPublicClient as createPublicClient12, http as http12, parseAbi as parseAbi16, encodeFunctionData as encodeFunctionData15 } from "viem";
1286
+ import { parseAbi as parseAbi17, encodeFunctionData as encodeFunctionData16, decodeFunctionResult as decodeFunctionResult4, zeroAddress as zeroAddress7 } from "viem";
1287
+ import { createPublicClient as createPublicClient13, http as http13, parseAbi as parseAbi18, encodeFunctionData as encodeFunctionData17, zeroAddress as zeroAddress8 } from "viem";
1288
+ import { createPublicClient as createPublicClient14, http as http14, parseAbi as parseAbi19 } from "viem";
1289
+ import { createPublicClient as createPublicClient15, http as http15, parseAbi as parseAbi20, encodeFunctionData as encodeFunctionData18 } from "viem";
1290
+ import { parseAbi as parseAbi21, encodeFunctionData as encodeFunctionData19 } from "viem";
1291
+ import { createPublicClient as createPublicClient16, http as http16, parseAbi as parseAbi222, encodeFunctionData as encodeFunctionData20, zeroAddress as zeroAddress9 } from "viem";
1292
+ import { createPublicClient as createPublicClient17, http as http17, parseAbi as parseAbi23, encodeFunctionData as encodeFunctionData21, zeroAddress as zeroAddress10 } from "viem";
1284
1293
  import { parseAbi as parseAbi24, encodeFunctionData as encodeFunctionData222 } from "viem";
1285
- import { createPublicClient as createPublicClient19, http as http19, parseAbi as parseAbi25 } from "viem";
1294
+ import { parseAbi as parseAbi25, encodeFunctionData as encodeFunctionData23 } from "viem";
1295
+ import { createPublicClient as createPublicClient18, http as http18, parseAbi as parseAbi26 } from "viem";
1296
+ function decodeAddressResult(data) {
1297
+ if (!data) return null;
1298
+ try {
1299
+ return decodeFunctionResult22({ abi: _addressAbi, functionName: "f", data });
1300
+ } catch {
1301
+ return null;
1302
+ }
1303
+ }
1304
+ function decodeUint256Result(data) {
1305
+ if (!data) return null;
1306
+ try {
1307
+ return decodeFunctionResult22({ abi: _uint256Abi, functionName: "f", data });
1308
+ } catch {
1309
+ return null;
1310
+ }
1311
+ }
1312
+ function decodeBoolResult(data) {
1313
+ if (!data) return null;
1314
+ try {
1315
+ return decodeFunctionResult22({ abi: _boolAbi, functionName: "f", data });
1316
+ } catch {
1317
+ return null;
1318
+ }
1319
+ }
1320
+ function decodeStringResult(data) {
1321
+ if (!data) return "?";
1322
+ try {
1323
+ return decodeFunctionResult22({ abi: erc20Abi2, functionName: "symbol", data });
1324
+ } catch {
1325
+ return "?";
1326
+ }
1327
+ }
1328
+ function decodeRangeResult(data) {
1329
+ if (!data) return null;
1330
+ try {
1331
+ return decodeFunctionResult22({ abi: _rangeAbi, functionName: "f", data });
1332
+ } catch {
1333
+ return null;
1334
+ }
1335
+ }
1336
+ function decodeBinResult(data) {
1337
+ if (!data) return null;
1338
+ try {
1339
+ return decodeFunctionResult22({ abi: _binAbi, functionName: "f", data });
1340
+ } catch {
1341
+ return null;
1342
+ }
1343
+ }
1344
+ function decodeUint256ArrayResult(data) {
1345
+ if (!data) return null;
1346
+ try {
1347
+ return decodeFunctionResult22({ abi: _uint256ArrayAbi, functionName: "f", data });
1348
+ } catch {
1349
+ return null;
1350
+ }
1351
+ }
1352
+ function extractRewarderAddress(hooksParams) {
1353
+ if (!hooksParams || hooksParams === "0x0000000000000000000000000000000000000000000000000000000000000000") {
1354
+ return null;
1355
+ }
1356
+ const hex = hooksParams.slice(2);
1357
+ if (hex.length < 64) return null;
1358
+ const addrHex = hex.slice(24, 64);
1359
+ if (addrHex === "0000000000000000000000000000000000000000") return null;
1360
+ return `0x${addrHex}`;
1361
+ }
1362
+ function buildUniformDistribution(deltaIds) {
1363
+ const PRECISION = 10n ** 18n;
1364
+ const n = deltaIds.length;
1365
+ const xBins = deltaIds.filter((d) => d >= 0).length;
1366
+ const yBins = deltaIds.filter((d) => d <= 0).length;
1367
+ const distributionX = [];
1368
+ const distributionY = [];
1369
+ for (const delta of deltaIds) {
1370
+ const xShare = delta >= 0 && xBins > 0 ? PRECISION / BigInt(xBins) : 0n;
1371
+ const yShare = delta <= 0 && yBins > 0 ? PRECISION / BigInt(yBins) : 0n;
1372
+ distributionX.push(xShare);
1373
+ distributionY.push(yShare);
1374
+ }
1375
+ const xSum = distributionX.reduce((a, b) => a + b, 0n);
1376
+ const ySum = distributionY.reduce((a, b) => a + b, 0n);
1377
+ if (xSum > 0n && xSum !== PRECISION) {
1378
+ const firstX = distributionX.findIndex((v) => v > 0n);
1379
+ if (firstX !== -1) distributionX[firstX] += PRECISION - xSum;
1380
+ }
1381
+ if (ySum > 0n && ySum !== PRECISION) {
1382
+ const firstY = distributionY.findIndex((v) => v > 0n);
1383
+ if (firstY !== -1) distributionY[firstY] += PRECISION - ySum;
1384
+ }
1385
+ return { distributionX, distributionY };
1386
+ }
1286
1387
  function u256ToF64(v) {
1287
1388
  const MAX_U128 = (1n << 128n) - 1n;
1288
1389
  if (v > MAX_U128) return Infinity;
1289
1390
  return Number(v);
1290
1391
  }
1392
+ function decodeAddress(data) {
1393
+ if (!data || data.length < 66) return null;
1394
+ return `0x${data.slice(26, 66)}`;
1395
+ }
1396
+ function decodeAddressArray(data) {
1397
+ if (!data) return [];
1398
+ try {
1399
+ return decodeFunctionResult3({
1400
+ abi: REWARDS_CONTROLLER_ABI,
1401
+ functionName: "getRewardsByAsset",
1402
+ data
1403
+ });
1404
+ } catch {
1405
+ return [];
1406
+ }
1407
+ }
1408
+ function decodeReserveData(data) {
1409
+ if (!data) return null;
1410
+ try {
1411
+ return decodeFunctionResult3({
1412
+ abi: POOL_ABI,
1413
+ functionName: "getReserveData",
1414
+ data
1415
+ });
1416
+ } catch {
1417
+ return null;
1418
+ }
1419
+ }
1420
+ function decodeRewardsData(data) {
1421
+ if (!data) return null;
1422
+ try {
1423
+ return decodeFunctionResult3({
1424
+ abi: REWARDS_CONTROLLER_ABI,
1425
+ functionName: "getRewardsData",
1426
+ data
1427
+ });
1428
+ } catch {
1429
+ return null;
1430
+ }
1431
+ }
1291
1432
  function u256ToF642(v) {
1292
1433
  const MAX_U128 = (1n << 128n) - 1n;
1293
1434
  if (v > MAX_U128) return Infinity;
@@ -1302,6 +1443,30 @@ function defaultMarketParams(loanToken = zeroAddress7) {
1302
1443
  lltv: 0n
1303
1444
  };
1304
1445
  }
1446
+ function decodeMarket(data) {
1447
+ if (!data) return null;
1448
+ try {
1449
+ return decodeFunctionResult4({
1450
+ abi: MORPHO_ABI,
1451
+ functionName: "market",
1452
+ data
1453
+ });
1454
+ } catch {
1455
+ return null;
1456
+ }
1457
+ }
1458
+ function decodeMarketParams(data) {
1459
+ if (!data) return null;
1460
+ try {
1461
+ return decodeFunctionResult4({
1462
+ abi: MORPHO_ABI,
1463
+ functionName: "idToMarketParams",
1464
+ data
1465
+ });
1466
+ } catch {
1467
+ return null;
1468
+ }
1469
+ }
1305
1470
  function createDex(entry, rpcUrl) {
1306
1471
  switch (entry.interface) {
1307
1472
  case "uniswap_v3":
@@ -1441,7 +1606,10 @@ function createOracleFromCdp(entry, _asset, rpcUrl) {
1441
1606
  throw DefiError.unsupported(`Oracle not available for CDP interface '${entry.interface}'`);
1442
1607
  }
1443
1608
  }
1444
- var DEFAULT_FEE, swapRouterAbi, quoterAbi, ramsesQuoterAbi, positionManagerAbi, UniswapV3Adapter, abi, lbQuoterAbi, UniswapV2Adapter, abi2, algebraQuoterAbi, algebraSingleQuoterAbi, algebraPositionManagerAbi, AlgebraV3Adapter, abi3, BalancerV3Adapter, poolAbi, CurveStableSwapAdapter, abi4, abiV2, SolidlyAdapter, abi5, WooFiAdapter, gaugeAbi, veAbi, voterAbi, SolidlyGaugeAdapter, masterchefAbi, MasterChefAdapter, POOL_ABI, ERC20_ABI, INCENTIVES_ABI, REWARDS_CONTROLLER_ABI, POOL_PROVIDER_ABI, ADDRESSES_PROVIDER_ABI, ORACLE_ABI, ERC20_DECIMALS_ABI, AaveV3Adapter, POOL_ABI2, ERC20_ABI2, AaveV2Adapter, ORACLE_ABI2, AaveOracleAdapter, CTOKEN_ABI, BSC_BLOCKS_PER_YEAR, CompoundV2Adapter, COMET_ABI, SECONDS_PER_YEAR, CompoundV3Adapter, EULER_VAULT_ABI, SECONDS_PER_YEAR2, EulerV2Adapter, MORPHO_ABI, META_MORPHO_ABI, IRM_ABI, SECONDS_PER_YEAR3, MorphoBlueAdapter, BORROWER_OPS_ABI, TROVE_MANAGER_ABI, HINT_HELPERS_ABI, SORTED_TROVES_ABI, FelixCdpAdapter, PRICE_FEED_ABI, FelixOracleAdapter, ERC4626_ABI, ERC4626VaultAdapter, GENERIC_LST_ABI, GenericLstAdapter, STHYPE_ABI, ERC20_ABI3, StHypeAdapter, KINETIQ_ABI, ORACLE_ABI3, WHYPE, HYPERLEND_ORACLE, KinetiqAdapter, PendleAdapter, GenericYieldAdapter, HLP_ABI, HlpVaultAdapter, GenericDerivativesAdapter, RYSK_ABI, RyskAdapter, GenericOptionsAdapter, ERC721_ABI, ERC721Adapter, DexSpotPrice;
1609
+ function createMerchantMoeLB(entry, rpcUrl) {
1610
+ return new MerchantMoeLBAdapter(entry, rpcUrl);
1611
+ }
1612
+ var DEFAULT_FEE, swapRouterAbi, quoterAbi, ramsesQuoterAbi, positionManagerAbi, UniswapV3Adapter, abi, lbQuoterAbi, UniswapV2Adapter, abi2, algebraQuoterAbi, algebraSingleQuoterAbi, algebraPositionManagerAbi, AlgebraV3Adapter, abi3, BalancerV3Adapter, poolAbi, CurveStableSwapAdapter, abi4, abiV2, SolidlyAdapter, abi5, WooFiAdapter, gaugeAbi, veAbi, voterAbi, SolidlyGaugeAdapter, masterchefAbi, MasterChefAdapter, lbRouterAbi, lbFactoryAbi, lbPairAbi, lbRewarderAbi, masterChefAbi, veMoeAbi, lbPairBinAbi, lbQuoterAbi2, erc20Abi2, _addressAbi, _uint256Abi, _boolAbi, _rangeAbi, _binAbi, _uint256ArrayAbi, MerchantMoeLBAdapter, POOL_ABI, ERC20_ABI, INCENTIVES_ABI, REWARDS_CONTROLLER_ABI, POOL_PROVIDER_ABI, ADDRESSES_PROVIDER_ABI, ORACLE_ABI, ERC20_DECIMALS_ABI, AaveV3Adapter, POOL_ABI2, ERC20_ABI2, AaveV2Adapter, ORACLE_ABI2, AaveOracleAdapter, CTOKEN_ABI, BSC_BLOCKS_PER_YEAR, CompoundV2Adapter, COMET_ABI, SECONDS_PER_YEAR, CompoundV3Adapter, EULER_VAULT_ABI, SECONDS_PER_YEAR2, EulerV2Adapter, MORPHO_ABI, META_MORPHO_ABI, IRM_ABI, SECONDS_PER_YEAR3, MorphoBlueAdapter, BORROWER_OPS_ABI, TROVE_MANAGER_ABI, HINT_HELPERS_ABI, SORTED_TROVES_ABI, FelixCdpAdapter, PRICE_FEED_ABI, FelixOracleAdapter, ERC4626_ABI, ERC4626VaultAdapter, GENERIC_LST_ABI, GenericLstAdapter, STHYPE_ABI, ERC20_ABI3, StHypeAdapter, KINETIQ_ABI, ORACLE_ABI3, WHYPE, HYPERLEND_ORACLE, KinetiqAdapter, PendleAdapter, GenericYieldAdapter, HLP_ABI, HlpVaultAdapter, GenericDerivativesAdapter, RYSK_ABI, RyskAdapter, GenericOptionsAdapter, ERC721_ABI, ERC721Adapter, DexSpotPrice;
1445
1613
  var init_dist3 = __esm({
1446
1614
  "../defi-protocols/dist/index.js"() {
1447
1615
  "use strict";
@@ -1475,6 +1643,7 @@ var init_dist3 = __esm({
1475
1643
  init_dist2();
1476
1644
  init_dist2();
1477
1645
  init_dist2();
1646
+ init_dist2();
1478
1647
  DEFAULT_FEE = 3e3;
1479
1648
  swapRouterAbi = parseAbi3([
1480
1649
  "struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; }",
@@ -1542,7 +1711,8 @@ var init_dist3 = __esm({
1542
1711
  to: this.router,
1543
1712
  data,
1544
1713
  value: 0n,
1545
- gas_estimate: 2e5
1714
+ gas_estimate: 2e5,
1715
+ approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
1546
1716
  };
1547
1717
  }
1548
1718
  async quote(params) {
@@ -1712,7 +1882,11 @@ var init_dist3 = __esm({
1712
1882
  to: pm,
1713
1883
  data,
1714
1884
  value: 0n,
1715
- gas_estimate: 5e5
1885
+ gas_estimate: 5e5,
1886
+ approvals: [
1887
+ { token: token0, spender: pm, amount: amount0 },
1888
+ { token: token1, spender: pm, amount: amount1 }
1889
+ ]
1716
1890
  };
1717
1891
  }
1718
1892
  async buildRemoveLiquidity(_params) {
@@ -1771,7 +1945,8 @@ var init_dist3 = __esm({
1771
1945
  to: this.router,
1772
1946
  data,
1773
1947
  value: 0n,
1774
- gas_estimate: 15e4
1948
+ gas_estimate: 15e4,
1949
+ approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
1775
1950
  };
1776
1951
  }
1777
1952
  async quote(params) {
@@ -1890,7 +2065,11 @@ var init_dist3 = __esm({
1890
2065
  to: this.router,
1891
2066
  data,
1892
2067
  value: 0n,
1893
- gas_estimate: 3e5
2068
+ gas_estimate: 3e5,
2069
+ approvals: [
2070
+ { token: params.token_a, spender: this.router, amount: params.amount_a },
2071
+ { token: params.token_b, spender: this.router, amount: params.amount_b }
2072
+ ]
1894
2073
  };
1895
2074
  }
1896
2075
  async buildRemoveLiquidity(params) {
@@ -1977,7 +2156,8 @@ var init_dist3 = __esm({
1977
2156
  to: this.router,
1978
2157
  data,
1979
2158
  value: 0n,
1980
- gas_estimate: 25e4
2159
+ gas_estimate: 25e4,
2160
+ approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
1981
2161
  };
1982
2162
  }
1983
2163
  async quote(params) {
@@ -2095,7 +2275,11 @@ var init_dist3 = __esm({
2095
2275
  to: pm,
2096
2276
  data,
2097
2277
  value: 0n,
2098
- gas_estimate: 5e5
2278
+ gas_estimate: 5e5,
2279
+ approvals: [
2280
+ { token: token0, spender: pm, amount: amount0 },
2281
+ { token: token1, spender: pm, amount: amount1 }
2282
+ ]
2099
2283
  };
2100
2284
  }
2101
2285
  async buildRemoveLiquidity(_params) {
@@ -2272,18 +2456,10 @@ var init_dist3 = __esm({
2272
2456
  to: this.router,
2273
2457
  data,
2274
2458
  value: 0n,
2275
- gas_estimate: 2e5
2459
+ gas_estimate: 2e5,
2460
+ approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
2276
2461
  };
2277
2462
  }
2278
- async callGetAmountsOut(client, callData) {
2279
- const result = await client.call({ to: this.router, data: callData });
2280
- if (!result.data) return 0n;
2281
- const [amounts] = decodeAbiParameters4(
2282
- [{ name: "amounts", type: "uint256[]" }],
2283
- result.data
2284
- );
2285
- return amounts.length >= 2 ? amounts[amounts.length - 1] : 0n;
2286
- }
2287
2463
  encodeV1(params, stable) {
2288
2464
  return encodeFunctionData6({
2289
2465
  abi: abi4,
@@ -2300,7 +2476,6 @@ var init_dist3 = __esm({
2300
2476
  }
2301
2477
  async quote(params) {
2302
2478
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
2303
- const client = createPublicClient4({ transport: http4(this.rpcUrl) });
2304
2479
  const candidates = [
2305
2480
  { callData: this.encodeV1(params, false), stable: false },
2306
2481
  { callData: this.encodeV1(params, true), stable: true }
@@ -2311,16 +2486,26 @@ var init_dist3 = __esm({
2311
2486
  { callData: this.encodeV2(params, true), stable: true }
2312
2487
  );
2313
2488
  }
2314
- const results = await Promise.allSettled(
2315
- candidates.map((c) => this.callGetAmountsOut(client, c.callData))
2489
+ const rawResults = await multicallRead(
2490
+ this.rpcUrl,
2491
+ candidates.map((c) => [this.router, c.callData])
2316
2492
  );
2317
2493
  let bestOut = 0n;
2318
2494
  let bestStable = false;
2319
- for (let i = 0; i < results.length; i++) {
2320
- const r = results[i];
2321
- if (r.status === "fulfilled" && r.value > bestOut) {
2322
- bestOut = r.value;
2323
- bestStable = candidates[i].stable;
2495
+ for (let i = 0; i < rawResults.length; i++) {
2496
+ const raw = rawResults[i];
2497
+ if (!raw) continue;
2498
+ try {
2499
+ const [amounts] = decodeAbiParameters4(
2500
+ [{ name: "amounts", type: "uint256[]" }],
2501
+ raw
2502
+ );
2503
+ const out = amounts.length >= 2 ? amounts[amounts.length - 1] : 0n;
2504
+ if (out > bestOut) {
2505
+ bestOut = out;
2506
+ bestStable = candidates[i].stable;
2507
+ }
2508
+ } catch {
2324
2509
  }
2325
2510
  }
2326
2511
  if (bestOut === 0n) {
@@ -2355,7 +2540,11 @@ var init_dist3 = __esm({
2355
2540
  to: this.router,
2356
2541
  data,
2357
2542
  value: 0n,
2358
- gas_estimate: 35e4
2543
+ gas_estimate: 35e4,
2544
+ approvals: [
2545
+ { token: params.token_a, spender: this.router, amount: params.amount_a },
2546
+ { token: params.token_b, spender: this.router, amount: params.amount_b }
2547
+ ]
2359
2548
  };
2360
2549
  }
2361
2550
  async buildRemoveLiquidity(params) {
@@ -2481,7 +2670,7 @@ var init_dist3 = __esm({
2481
2670
  return this.protocolName;
2482
2671
  }
2483
2672
  // IGauge
2484
- async buildDeposit(gauge, amount, tokenId) {
2673
+ async buildDeposit(gauge, amount, tokenId, lpToken) {
2485
2674
  if (tokenId !== void 0) {
2486
2675
  const data2 = encodeFunctionData8({
2487
2676
  abi: gaugeAbi,
@@ -2493,7 +2682,8 @@ var init_dist3 = __esm({
2493
2682
  to: gauge,
2494
2683
  data: data2,
2495
2684
  value: 0n,
2496
- gas_estimate: 2e5
2685
+ gas_estimate: 2e5,
2686
+ approvals: lpToken ? [{ token: lpToken, spender: gauge, amount }] : void 0
2497
2687
  };
2498
2688
  }
2499
2689
  const data = encodeFunctionData8({
@@ -2506,7 +2696,8 @@ var init_dist3 = __esm({
2506
2696
  to: gauge,
2507
2697
  data,
2508
2698
  value: 0n,
2509
- gas_estimate: 2e5
2699
+ gas_estimate: 2e5,
2700
+ approvals: lpToken ? [{ token: lpToken, spender: gauge, amount }] : void 0
2510
2701
  };
2511
2702
  }
2512
2703
  async buildWithdraw(gauge, amount) {
@@ -2526,7 +2717,7 @@ var init_dist3 = __esm({
2526
2717
  async buildClaimRewards(gauge, account) {
2527
2718
  if (account && this.rpcUrl) {
2528
2719
  try {
2529
- const client = createPublicClient5({ transport: http5(this.rpcUrl) });
2720
+ const client = createPublicClient4({ transport: http4(this.rpcUrl) });
2530
2721
  const listLen = await client.readContract({
2531
2722
  address: gauge,
2532
2723
  abi: gaugeAbi,
@@ -2784,7 +2975,7 @@ var init_dist3 = __esm({
2784
2975
  if (!this.rpcUrl) {
2785
2976
  throw DefiError.unsupported(`[${this.protocolName}] getPendingRewards requires RPC`);
2786
2977
  }
2787
- const client = createPublicClient6({ transport: http6(this.rpcUrl) });
2978
+ const client = createPublicClient5({ transport: http5(this.rpcUrl) });
2788
2979
  const rewards = await client.readContract({
2789
2980
  address: this.masterchef,
2790
2981
  abi: masterchefAbi,
@@ -2798,7 +2989,591 @@ var init_dist3 = __esm({
2798
2989
  }));
2799
2990
  }
2800
2991
  };
2801
- POOL_ABI = parseAbi10([
2992
+ lbRouterAbi = parseAbi10([
2993
+ "struct LiquidityParameters { address tokenX; address tokenY; uint256 binStep; uint256 amountX; uint256 amountY; uint256 amountXMin; uint256 amountYMin; uint256 activeIdDesired; uint256 idSlippage; int256[] deltaIds; uint256[] distributionX; uint256[] distributionY; address to; address refundTo; uint256 deadline; }",
2994
+ "function addLiquidity(LiquidityParameters calldata liquidityParameters) external returns (uint256 amountXAdded, uint256 amountYAdded, uint256 amountXLeft, uint256 amountYLeft, uint256[] memory depositIds, uint256[] memory liquidityMinted)",
2995
+ "function removeLiquidity(address tokenX, address tokenY, uint16 binStep, uint256 amountXMin, uint256 amountYMin, uint256[] memory ids, uint256[] memory amounts, address to, uint256 deadline) external returns (uint256 amountX, uint256 amountY)"
2996
+ ]);
2997
+ lbFactoryAbi = parseAbi10([
2998
+ "function getNumberOfLBPairs() external view returns (uint256)",
2999
+ "function getLBPairAtIndex(uint256 index) external view returns (address)"
3000
+ ]);
3001
+ lbPairAbi = parseAbi10([
3002
+ "function getLBHooksParameters() external view returns (bytes32)",
3003
+ "function getActiveId() external view returns (uint24)",
3004
+ "function getBinStep() external view returns (uint16)",
3005
+ "function getTokenX() external view returns (address)",
3006
+ "function getTokenY() external view returns (address)",
3007
+ "function balanceOf(address account, uint256 id) external view returns (uint256)",
3008
+ "function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory)"
3009
+ ]);
3010
+ lbRewarderAbi = parseAbi10([
3011
+ "function getRewardToken() external view returns (address)",
3012
+ "function getRewardedRange() external view returns (uint256 minBinId, uint256 maxBinId)",
3013
+ "function getPendingRewards(address user, uint256[] calldata ids) external view returns (uint256 pendingRewards)",
3014
+ "function claim(address user, uint256[] calldata ids) external",
3015
+ "function getPid() external view returns (uint256)",
3016
+ "function isStopped() external view returns (bool)",
3017
+ "function getLBPair() external view returns (address)",
3018
+ "function getMasterChef() external view returns (address)"
3019
+ ]);
3020
+ masterChefAbi = parseAbi10([
3021
+ "function getMoePerSecond() external view returns (uint256)",
3022
+ "function getTreasuryShare() external view returns (uint256)",
3023
+ "function getStaticShare() external view returns (uint256)",
3024
+ "function getVeMoe() external view returns (address)"
3025
+ ]);
3026
+ veMoeAbi = parseAbi10([
3027
+ "function getWeight(uint256 pid) external view returns (uint256)",
3028
+ "function getTotalWeight() external view returns (uint256)",
3029
+ "function getTopPoolIds() external view returns (uint256[] memory)"
3030
+ ]);
3031
+ lbPairBinAbi = parseAbi10([
3032
+ "function getBin(uint24 id) external view returns (uint128 reserveX, uint128 reserveY)",
3033
+ "function getActiveId() external view returns (uint24)"
3034
+ ]);
3035
+ lbQuoterAbi2 = parseAbi10([
3036
+ "function findBestPathFromAmountIn(address[] calldata route, uint128 amountIn) external view returns ((address[] route, address[] pairs, uint256[] binSteps, uint256[] versions, uint128[] amounts, uint128[] virtualAmountsWithoutSlippage, uint128[] fees))"
3037
+ ]);
3038
+ erc20Abi2 = parseAbi10([
3039
+ "function symbol() external view returns (string)"
3040
+ ]);
3041
+ _addressAbi = parseAbi10(["function f() external view returns (address)"]);
3042
+ _uint256Abi = parseAbi10(["function f() external view returns (uint256)"]);
3043
+ _boolAbi = parseAbi10(["function f() external view returns (bool)"]);
3044
+ _rangeAbi = parseAbi10(["function f() external view returns (uint256 minBinId, uint256 maxBinId)"]);
3045
+ _binAbi = parseAbi10(["function f() external view returns (uint128 reserveX, uint128 reserveY)"]);
3046
+ _uint256ArrayAbi = parseAbi10(["function f() external view returns (uint256[] memory)"]);
3047
+ MerchantMoeLBAdapter = class {
3048
+ protocolName;
3049
+ lbRouter;
3050
+ lbFactory;
3051
+ lbQuoter;
3052
+ rpcUrl;
3053
+ /** WMNT address (lb_mid_wmnt in config) used for MOE price routing */
3054
+ wmnt;
3055
+ /** USDT address (lb_mid_usdt in config) used for MNT/USD price routing */
3056
+ usdt;
3057
+ constructor(entry, rpcUrl) {
3058
+ this.protocolName = entry.name;
3059
+ const lbRouter = entry.contracts?.["lb_router"];
3060
+ if (!lbRouter) {
3061
+ throw new DefiError("CONTRACT_ERROR", "Missing 'lb_router' contract address");
3062
+ }
3063
+ const lbFactory = entry.contracts?.["lb_factory"];
3064
+ if (!lbFactory) {
3065
+ throw new DefiError("CONTRACT_ERROR", "Missing 'lb_factory' contract address");
3066
+ }
3067
+ this.lbRouter = lbRouter;
3068
+ this.lbFactory = lbFactory;
3069
+ this.lbQuoter = entry.contracts?.["lb_quoter"];
3070
+ this.wmnt = entry.contracts?.["lb_mid_wmnt"];
3071
+ this.usdt = entry.contracts?.["lb_mid_usdt"];
3072
+ this.rpcUrl = rpcUrl;
3073
+ }
3074
+ name() {
3075
+ return this.protocolName;
3076
+ }
3077
+ requireRpc() {
3078
+ if (!this.rpcUrl) {
3079
+ throw DefiError.rpcError(`[${this.protocolName}] RPC URL required`);
3080
+ }
3081
+ return this.rpcUrl;
3082
+ }
3083
+ /**
3084
+ * Build an addLiquidity transaction for a Liquidity Book pair.
3085
+ * Distributes tokenX/tokenY uniformly across active bin ± numBins.
3086
+ */
3087
+ async buildAddLiquidity(params) {
3088
+ const numBins = params.numBins ?? 5;
3089
+ const deadline = params.deadline ?? BigInt("18446744073709551615");
3090
+ let activeIdDesired = params.activeIdDesired;
3091
+ if (activeIdDesired === void 0) {
3092
+ const rpcUrl = this.requireRpc();
3093
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3094
+ const activeId = await client.readContract({
3095
+ address: params.pool,
3096
+ abi: lbPairAbi,
3097
+ functionName: "getActiveId"
3098
+ });
3099
+ activeIdDesired = activeId;
3100
+ }
3101
+ const deltaIds = [];
3102
+ for (let d = -numBins; d <= numBins; d++) {
3103
+ deltaIds.push(d);
3104
+ }
3105
+ const { distributionX, distributionY } = buildUniformDistribution(deltaIds);
3106
+ const data = encodeFunctionData10({
3107
+ abi: lbRouterAbi,
3108
+ functionName: "addLiquidity",
3109
+ args: [
3110
+ {
3111
+ tokenX: params.tokenX,
3112
+ tokenY: params.tokenY,
3113
+ binStep: BigInt(params.binStep),
3114
+ amountX: params.amountX,
3115
+ amountY: params.amountY,
3116
+ amountXMin: 0n,
3117
+ amountYMin: 0n,
3118
+ activeIdDesired: BigInt(activeIdDesired),
3119
+ idSlippage: BigInt(numBins + 2),
3120
+ deltaIds: deltaIds.map(BigInt),
3121
+ distributionX,
3122
+ distributionY,
3123
+ to: params.recipient,
3124
+ refundTo: params.recipient,
3125
+ deadline
3126
+ }
3127
+ ]
3128
+ });
3129
+ return {
3130
+ description: `[${this.protocolName}] LB addLiquidity ${params.amountX} tokenX + ${params.amountY} tokenY across ${deltaIds.length} bins`,
3131
+ to: this.lbRouter,
3132
+ data,
3133
+ value: 0n,
3134
+ gas_estimate: 8e5,
3135
+ approvals: [
3136
+ { token: params.tokenX, spender: this.lbRouter, amount: params.amountX },
3137
+ { token: params.tokenY, spender: this.lbRouter, amount: params.amountY }
3138
+ ]
3139
+ };
3140
+ }
3141
+ /**
3142
+ * Build a removeLiquidity transaction for specific LB bins.
3143
+ */
3144
+ async buildRemoveLiquidity(params) {
3145
+ const deadline = params.deadline ?? BigInt("18446744073709551615");
3146
+ const data = encodeFunctionData10({
3147
+ abi: lbRouterAbi,
3148
+ functionName: "removeLiquidity",
3149
+ args: [
3150
+ params.tokenX,
3151
+ params.tokenY,
3152
+ params.binStep,
3153
+ params.amountXMin ?? 0n,
3154
+ params.amountYMin ?? 0n,
3155
+ params.binIds.map(BigInt),
3156
+ params.amounts,
3157
+ params.recipient,
3158
+ deadline
3159
+ ]
3160
+ });
3161
+ return {
3162
+ description: `[${this.protocolName}] LB removeLiquidity from ${params.binIds.length} bins`,
3163
+ to: this.lbRouter,
3164
+ data,
3165
+ value: 0n,
3166
+ gas_estimate: 6e5
3167
+ };
3168
+ }
3169
+ /**
3170
+ * Auto-detect bin IDs for a pool from the rewarder's rewarded range.
3171
+ * Falls back to active bin ± 50 scan if no rewarder exists.
3172
+ */
3173
+ async autoDetectBins(pool) {
3174
+ const rpcUrl = this.requireRpc();
3175
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3176
+ const hooksParams = await client.readContract({
3177
+ address: pool,
3178
+ abi: lbPairAbi,
3179
+ functionName: "getLBHooksParameters"
3180
+ });
3181
+ const rewarder = extractRewarderAddress(hooksParams);
3182
+ if (rewarder) {
3183
+ const range = await client.readContract({
3184
+ address: rewarder,
3185
+ abi: lbRewarderAbi,
3186
+ functionName: "getRewardedRange"
3187
+ });
3188
+ const min = Number(range[0]);
3189
+ const max = Number(range[1]);
3190
+ const ids2 = [];
3191
+ for (let b = min; b <= max; b++) ids2.push(b);
3192
+ return ids2;
3193
+ }
3194
+ const activeId = await client.readContract({
3195
+ address: pool,
3196
+ abi: lbPairAbi,
3197
+ functionName: "getActiveId"
3198
+ });
3199
+ const ids = [];
3200
+ for (let b = activeId - 50; b <= activeId + 50; b++) ids.push(b);
3201
+ return ids;
3202
+ }
3203
+ /**
3204
+ * Get pending MOE rewards for a user across specified bin IDs.
3205
+ * If binIds is omitted, auto-detects from the rewarder's rewarded range.
3206
+ * Reads the rewarder address from the pool's hooks parameters.
3207
+ */
3208
+ async getPendingRewards(user, pool, binIds) {
3209
+ const rpcUrl = this.requireRpc();
3210
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3211
+ const hooksParams = await client.readContract({
3212
+ address: pool,
3213
+ abi: lbPairAbi,
3214
+ functionName: "getLBHooksParameters"
3215
+ });
3216
+ const rewarder = extractRewarderAddress(hooksParams);
3217
+ if (!rewarder) {
3218
+ return [];
3219
+ }
3220
+ let resolvedBinIds = binIds;
3221
+ if (!resolvedBinIds || resolvedBinIds.length === 0) {
3222
+ const range = await client.readContract({
3223
+ address: rewarder,
3224
+ abi: lbRewarderAbi,
3225
+ functionName: "getRewardedRange"
3226
+ });
3227
+ const min = Number(range[0]);
3228
+ const max = Number(range[1]);
3229
+ resolvedBinIds = [];
3230
+ for (let b = min; b <= max; b++) resolvedBinIds.push(b);
3231
+ }
3232
+ const [pending, rewardToken] = await Promise.all([
3233
+ client.readContract({
3234
+ address: rewarder,
3235
+ abi: lbRewarderAbi,
3236
+ functionName: "getPendingRewards",
3237
+ args: [user, resolvedBinIds.map(BigInt)]
3238
+ }),
3239
+ client.readContract({
3240
+ address: rewarder,
3241
+ abi: lbRewarderAbi,
3242
+ functionName: "getRewardToken"
3243
+ })
3244
+ ]);
3245
+ return [
3246
+ {
3247
+ token: rewardToken,
3248
+ symbol: "MOE",
3249
+ amount: pending
3250
+ }
3251
+ ];
3252
+ }
3253
+ /**
3254
+ * Build a claim rewards transaction for specific LB bins.
3255
+ * If binIds is omitted, auto-detects from the rewarder's rewarded range.
3256
+ */
3257
+ async buildClaimRewards(user, pool, binIds) {
3258
+ const rpcUrl = this.requireRpc();
3259
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3260
+ const hooksParams = await client.readContract({
3261
+ address: pool,
3262
+ abi: lbPairAbi,
3263
+ functionName: "getLBHooksParameters"
3264
+ });
3265
+ const rewarder = extractRewarderAddress(hooksParams);
3266
+ if (!rewarder) {
3267
+ throw new DefiError("CONTRACT_ERROR", `[${this.protocolName}] Pool ${pool} has no active rewarder`);
3268
+ }
3269
+ let resolvedBinIds = binIds;
3270
+ if (!resolvedBinIds || resolvedBinIds.length === 0) {
3271
+ const range = await client.readContract({
3272
+ address: rewarder,
3273
+ abi: lbRewarderAbi,
3274
+ functionName: "getRewardedRange"
3275
+ });
3276
+ const min = Number(range[0]);
3277
+ const max = Number(range[1]);
3278
+ resolvedBinIds = [];
3279
+ for (let b = min; b <= max; b++) resolvedBinIds.push(b);
3280
+ }
3281
+ const data = encodeFunctionData10({
3282
+ abi: lbRewarderAbi,
3283
+ functionName: "claim",
3284
+ args: [user, resolvedBinIds.map(BigInt)]
3285
+ });
3286
+ return {
3287
+ description: `[${this.protocolName}] LB claim rewards for ${resolvedBinIds.length} bins`,
3288
+ to: rewarder,
3289
+ data,
3290
+ value: 0n,
3291
+ gas_estimate: 3e5
3292
+ };
3293
+ }
3294
+ /**
3295
+ * Discover all active rewarded LB pools by iterating the factory.
3296
+ * Uses 7 multicall batches to minimise RPC round-trips and avoid 429s.
3297
+ *
3298
+ * Batch 1: getNumberOfLBPairs(), then getLBPairAtIndex(i) for all i
3299
+ * Batch 2: getLBHooksParameters() for all pairs → extract rewarder addresses
3300
+ * Batch 3: isStopped/getRewardedRange/getRewardToken/getPid/getMasterChef for each rewarder
3301
+ * Batch 4: getTokenX/getTokenY for each rewarded pair, then symbol() for unique tokens
3302
+ * Batch 5: Bootstrap MasterChef→VeMoe, then getMoePerSecond/getTreasuryShare/getStaticShare/getTotalWeight/getTopPoolIds
3303
+ * Batch 6: VeMoe.getWeight(pid) for each rewarded pool
3304
+ * Batch 7: Pool.getBin(binId) for all bins in rewarded range of each pool
3305
+ * Price: LB Quoter findBestPathFromAmountIn for MOE/WMNT and WMNT/USDT prices
3306
+ */
3307
+ async discoverRewardedPools() {
3308
+ const rpcUrl = this.requireRpc();
3309
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3310
+ const pairCount = await client.readContract({
3311
+ address: this.lbFactory,
3312
+ abi: lbFactoryAbi,
3313
+ functionName: "getNumberOfLBPairs"
3314
+ });
3315
+ const count = Number(pairCount);
3316
+ if (count === 0) return [];
3317
+ const batch1Calls = Array.from({ length: count }, (_, i) => [
3318
+ this.lbFactory,
3319
+ encodeFunctionData10({ abi: lbFactoryAbi, functionName: "getLBPairAtIndex", args: [BigInt(i)] })
3320
+ ]);
3321
+ const batch1Results = await multicallRead(rpcUrl, batch1Calls);
3322
+ const pairAddresses = batch1Results.map((r) => decodeAddressResult(r)).filter((a) => a !== null);
3323
+ if (pairAddresses.length === 0) return [];
3324
+ const batch2Calls = pairAddresses.map((pair) => [
3325
+ pair,
3326
+ encodeFunctionData10({ abi: lbPairAbi, functionName: "getLBHooksParameters" })
3327
+ ]);
3328
+ const batch2Results = await multicallRead(rpcUrl, batch2Calls);
3329
+ const rewardedPairs = [];
3330
+ for (let i = 0; i < pairAddresses.length; i++) {
3331
+ const raw = batch2Results[i];
3332
+ if (!raw) continue;
3333
+ let hooksBytes;
3334
+ try {
3335
+ const _bytes32Abi = parseAbi10(["function f() external view returns (bytes32)"]);
3336
+ hooksBytes = decodeFunctionResult22({ abi: _bytes32Abi, functionName: "f", data: raw });
3337
+ } catch {
3338
+ continue;
3339
+ }
3340
+ const rewarder = extractRewarderAddress(hooksBytes);
3341
+ if (rewarder) {
3342
+ rewardedPairs.push({ pool: pairAddresses[i], rewarder });
3343
+ }
3344
+ }
3345
+ if (rewardedPairs.length === 0) return [];
3346
+ const batch3Calls = [];
3347
+ for (const { rewarder } of rewardedPairs) {
3348
+ batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "isStopped" })]);
3349
+ batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getRewardedRange" })]);
3350
+ batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getRewardToken" })]);
3351
+ batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getPid" })]);
3352
+ batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getMasterChef" })]);
3353
+ }
3354
+ const batch3Results = await multicallRead(rpcUrl, batch3Calls);
3355
+ const batch4aCalls = [];
3356
+ for (const { pool } of rewardedPairs) {
3357
+ batch4aCalls.push([pool, encodeFunctionData10({ abi: lbPairAbi, functionName: "getTokenX" })]);
3358
+ batch4aCalls.push([pool, encodeFunctionData10({ abi: lbPairAbi, functionName: "getTokenY" })]);
3359
+ }
3360
+ const batch4aResults = await multicallRead(rpcUrl, batch4aCalls);
3361
+ const tokenXAddresses = [];
3362
+ const tokenYAddresses = [];
3363
+ for (let i = 0; i < rewardedPairs.length; i++) {
3364
+ tokenXAddresses.push(decodeAddressResult(batch4aResults[i * 2] ?? null));
3365
+ tokenYAddresses.push(decodeAddressResult(batch4aResults[i * 2 + 1] ?? null));
3366
+ }
3367
+ const uniqueTokens = Array.from(
3368
+ new Set([...tokenXAddresses, ...tokenYAddresses].filter((a) => a !== null))
3369
+ );
3370
+ const batch4bCalls = uniqueTokens.map((token) => [
3371
+ token,
3372
+ encodeFunctionData10({ abi: erc20Abi2, functionName: "symbol" })
3373
+ ]);
3374
+ const batch4bResults = await multicallRead(rpcUrl, batch4bCalls);
3375
+ const symbolMap = /* @__PURE__ */ new Map();
3376
+ for (let i = 0; i < uniqueTokens.length; i++) {
3377
+ symbolMap.set(uniqueTokens[i], decodeStringResult(batch4bResults[i] ?? null));
3378
+ }
3379
+ const STRIDE3 = 5;
3380
+ const poolData = [];
3381
+ for (let i = 0; i < rewardedPairs.length; i++) {
3382
+ const base = i * STRIDE3;
3383
+ poolData.push({
3384
+ stopped: decodeBoolResult(batch3Results[base] ?? null) ?? false,
3385
+ range: decodeRangeResult(batch3Results[base + 1] ?? null),
3386
+ rewardToken: decodeAddressResult(batch3Results[base + 2] ?? null),
3387
+ pid: Number(decodeUint256Result(batch3Results[base + 3] ?? null) ?? 0n),
3388
+ masterChef: decodeAddressResult(batch3Results[base + 4] ?? null)
3389
+ });
3390
+ }
3391
+ const masterChefAddr = poolData.map((d) => d.masterChef).find((a) => a !== null) ?? null;
3392
+ let moePerDay = 0;
3393
+ let topPoolIds = /* @__PURE__ */ new Set();
3394
+ let totalWeightRaw = 0n;
3395
+ let veMoeAddr = null;
3396
+ if (masterChefAddr) {
3397
+ veMoeAddr = await client.readContract({
3398
+ address: masterChefAddr,
3399
+ abi: masterChefAbi,
3400
+ functionName: "getVeMoe"
3401
+ });
3402
+ const batch5Calls = [
3403
+ [masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getMoePerSecond" })],
3404
+ [masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getTreasuryShare" })],
3405
+ [masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getStaticShare" })],
3406
+ [veMoeAddr, encodeFunctionData10({ abi: veMoeAbi, functionName: "getTotalWeight" })],
3407
+ [veMoeAddr, encodeFunctionData10({ abi: veMoeAbi, functionName: "getTopPoolIds" })]
3408
+ ];
3409
+ const batch5Results = await multicallRead(rpcUrl, batch5Calls);
3410
+ const moePerSecRaw = decodeUint256Result(batch5Results[0] ?? null) ?? 0n;
3411
+ const treasuryShareRaw = decodeUint256Result(batch5Results[1] ?? null) ?? 0n;
3412
+ const staticShareRaw = decodeUint256Result(batch5Results[2] ?? null) ?? 0n;
3413
+ totalWeightRaw = decodeUint256Result(batch5Results[3] ?? null) ?? 0n;
3414
+ const topPoolIdsRaw = decodeUint256ArrayResult(batch5Results[4] ?? null) ?? [];
3415
+ topPoolIds = new Set(topPoolIdsRaw.map(Number));
3416
+ const PRECISION = 10n ** 18n;
3417
+ const netPerSec = moePerSecRaw * (PRECISION - treasuryShareRaw) / PRECISION * (PRECISION - staticShareRaw) / PRECISION;
3418
+ moePerDay = Number(netPerSec * 86400n) / 1e18;
3419
+ }
3420
+ const weightByPid = /* @__PURE__ */ new Map();
3421
+ if (veMoeAddr && rewardedPairs.length > 0) {
3422
+ const batch6Calls = poolData.map((d) => [
3423
+ veMoeAddr,
3424
+ encodeFunctionData10({ abi: veMoeAbi, functionName: "getWeight", args: [BigInt(d.pid)] })
3425
+ ]);
3426
+ const batch6Results = await multicallRead(rpcUrl, batch6Calls);
3427
+ for (let i = 0; i < poolData.length; i++) {
3428
+ weightByPid.set(poolData[i].pid, decodeUint256Result(batch6Results[i] ?? null) ?? 0n);
3429
+ }
3430
+ }
3431
+ let moePriceUsd = 0;
3432
+ let wmntPriceUsd = 0;
3433
+ const MOE_ADDR = "0x4515A45337F461A11Ff0FE8aBF3c606AE5dC00c9";
3434
+ if (this.lbQuoter && this.wmnt && this.usdt) {
3435
+ try {
3436
+ const [moeWmntQuote, wmntUsdtQuote] = await Promise.all([
3437
+ client.readContract({
3438
+ address: this.lbQuoter,
3439
+ abi: lbQuoterAbi2,
3440
+ functionName: "findBestPathFromAmountIn",
3441
+ args: [[MOE_ADDR, this.wmnt], 10n ** 18n]
3442
+ }),
3443
+ client.readContract({
3444
+ address: this.lbQuoter,
3445
+ abi: lbQuoterAbi2,
3446
+ functionName: "findBestPathFromAmountIn",
3447
+ args: [[this.wmnt, this.usdt], 10n ** 18n]
3448
+ })
3449
+ ]);
3450
+ const moeInWmnt = Number(moeWmntQuote.amounts.at(-1) ?? 0n) / 1e18;
3451
+ wmntPriceUsd = Number(wmntUsdtQuote.amounts.at(-1) ?? 0n) / 1e6;
3452
+ moePriceUsd = moeInWmnt * wmntPriceUsd;
3453
+ } catch {
3454
+ }
3455
+ }
3456
+ const binRequests = [];
3457
+ for (let i = 0; i < rewardedPairs.length; i++) {
3458
+ const range = poolData[i].range;
3459
+ if (!range) continue;
3460
+ const minBin = Number(range[0]);
3461
+ const maxBin = Number(range[1]);
3462
+ for (let b = minBin; b <= maxBin; b++) {
3463
+ binRequests.push({ poolIdx: i, binId: b });
3464
+ }
3465
+ }
3466
+ const binReservesX = /* @__PURE__ */ new Map();
3467
+ const binReservesY = /* @__PURE__ */ new Map();
3468
+ if (binRequests.length > 0) {
3469
+ const batch7Calls = binRequests.map(({ poolIdx, binId }) => [
3470
+ rewardedPairs[poolIdx].pool,
3471
+ encodeFunctionData10({ abi: lbPairBinAbi, functionName: "getBin", args: [binId] })
3472
+ ]);
3473
+ const batch7Results = await multicallRead(rpcUrl, batch7Calls);
3474
+ for (let j = 0; j < binRequests.length; j++) {
3475
+ const { poolIdx, binId } = binRequests[j];
3476
+ const decoded = decodeBinResult(batch7Results[j] ?? null);
3477
+ if (!decoded) continue;
3478
+ if (!binReservesX.has(poolIdx)) {
3479
+ binReservesX.set(poolIdx, /* @__PURE__ */ new Map());
3480
+ binReservesY.set(poolIdx, /* @__PURE__ */ new Map());
3481
+ }
3482
+ binReservesX.get(poolIdx).set(binId, decoded[0]);
3483
+ binReservesY.get(poolIdx).set(binId, decoded[1]);
3484
+ }
3485
+ }
3486
+ const stableSymbols = /* @__PURE__ */ new Set(["USDT", "USDC", "MUSD", "AUSD", "USDY", "FDUSD"]);
3487
+ const mntSymbols = /* @__PURE__ */ new Set(["WMNT", "MNT"]);
3488
+ const moeSymbols = /* @__PURE__ */ new Set(["MOE"]);
3489
+ const sixDecimalStables = /* @__PURE__ */ new Set(["USDT", "USDC", "FDUSD"]);
3490
+ const getTokenPriceUsd = (sym) => {
3491
+ if (stableSymbols.has(sym)) return 1;
3492
+ if (mntSymbols.has(sym)) return wmntPriceUsd;
3493
+ if (moeSymbols.has(sym)) return moePriceUsd;
3494
+ return 0;
3495
+ };
3496
+ const getTokenDecimals = (sym) => {
3497
+ return sixDecimalStables.has(sym) ? 6 : 18;
3498
+ };
3499
+ const results = [];
3500
+ for (let i = 0; i < rewardedPairs.length; i++) {
3501
+ const { pool, rewarder } = rewardedPairs[i];
3502
+ const data = poolData[i];
3503
+ const tokenX = tokenXAddresses[i] ?? "0x0000000000000000000000000000000000000000";
3504
+ const tokenY = tokenYAddresses[i] ?? "0x0000000000000000000000000000000000000000";
3505
+ const symX = symbolMap.get(tokenX) ?? "?";
3506
+ const symY = symbolMap.get(tokenY) ?? "?";
3507
+ const isTopPool = topPoolIds.has(data.pid);
3508
+ const weight = weightByPid.get(data.pid) ?? 0n;
3509
+ let poolMoePerDay = 0;
3510
+ if (isTopPool && totalWeightRaw > 0n && weight > 0n) {
3511
+ poolMoePerDay = moePerDay * (Number(weight) / Number(totalWeightRaw));
3512
+ }
3513
+ const rxMap = binReservesX.get(i);
3514
+ const ryMap = binReservesY.get(i);
3515
+ const range = data.range;
3516
+ let rangeTvlUsd = 0;
3517
+ let rewardedBins = 0;
3518
+ if (range) {
3519
+ const minBin = Number(range[0]);
3520
+ const maxBin = Number(range[1]);
3521
+ rewardedBins = maxBin - minBin + 1;
3522
+ if (rxMap && ryMap) {
3523
+ const priceX = getTokenPriceUsd(symX);
3524
+ const priceY = getTokenPriceUsd(symY);
3525
+ const decX = getTokenDecimals(symX);
3526
+ const decY = getTokenDecimals(symY);
3527
+ for (let b = minBin; b <= maxBin; b++) {
3528
+ const rx = rxMap.get(b) ?? 0n;
3529
+ const ry = ryMap.get(b) ?? 0n;
3530
+ rangeTvlUsd += Number(rx) / 10 ** decX * priceX;
3531
+ rangeTvlUsd += Number(ry) / 10 ** decY * priceY;
3532
+ }
3533
+ }
3534
+ }
3535
+ const aprPercent = rangeTvlUsd > 0 && moePriceUsd > 0 ? poolMoePerDay * moePriceUsd * 365 / rangeTvlUsd * 100 : 0;
3536
+ results.push({
3537
+ pool,
3538
+ rewarder,
3539
+ rewardToken: data.rewardToken ?? "0x0000000000000000000000000000000000000000",
3540
+ minBinId: range ? Number(range[0]) : 0,
3541
+ maxBinId: range ? Number(range[1]) : 0,
3542
+ pid: data.pid,
3543
+ stopped: data.stopped,
3544
+ tokenX,
3545
+ tokenY,
3546
+ symbolX: symX,
3547
+ symbolY: symY,
3548
+ isTopPool,
3549
+ moePerDay: poolMoePerDay,
3550
+ rangeTvlUsd,
3551
+ aprPercent,
3552
+ rewardedBins
3553
+ });
3554
+ }
3555
+ return results;
3556
+ }
3557
+ /**
3558
+ * Get a user's LB positions (bin balances) across a range of bin IDs.
3559
+ * If binIds is omitted, auto-detects from the rewarder's rewarded range (or active ± 50).
3560
+ */
3561
+ async getUserPositions(user, pool, binIds) {
3562
+ const rpcUrl = this.requireRpc();
3563
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3564
+ const resolvedBinIds = binIds && binIds.length > 0 ? binIds : await this.autoDetectBins(pool);
3565
+ const accounts = resolvedBinIds.map(() => user);
3566
+ const ids = resolvedBinIds.map(BigInt);
3567
+ const balances = await client.readContract({
3568
+ address: pool,
3569
+ abi: lbPairAbi,
3570
+ functionName: "balanceOfBatch",
3571
+ args: [accounts, ids]
3572
+ });
3573
+ return resolvedBinIds.map((binId, i) => ({ binId, balance: balances[i] ?? 0n })).filter((p) => p.balance > 0n);
3574
+ }
3575
+ };
3576
+ POOL_ABI = parseAbi11([
2802
3577
  "function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
2803
3578
  "function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
2804
3579
  "function repay(address asset, uint256 amount, uint256 interestRateMode, address onBehalfOf) external returns (uint256)",
@@ -2806,27 +3581,27 @@ var init_dist3 = __esm({
2806
3581
  "function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)",
2807
3582
  "function getReserveData(address asset) external view returns (uint256 configuration, uint128 liquidityIndex, uint128 currentLiquidityRate, uint128 variableBorrowIndex, uint128 currentVariableBorrowRate, uint128 currentStableBorrowRate, uint40 lastUpdateTimestamp, uint16 id, address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress, address interestRateStrategyAddress, uint128 accruedToTreasury, uint128 unbacked, uint128 isolationModeTotalDebt)"
2808
3583
  ]);
2809
- ERC20_ABI = parseAbi10([
3584
+ ERC20_ABI = parseAbi11([
2810
3585
  "function totalSupply() external view returns (uint256)"
2811
3586
  ]);
2812
- INCENTIVES_ABI = parseAbi10([
3587
+ INCENTIVES_ABI = parseAbi11([
2813
3588
  "function getIncentivesController() external view returns (address)"
2814
3589
  ]);
2815
- REWARDS_CONTROLLER_ABI = parseAbi10([
3590
+ REWARDS_CONTROLLER_ABI = parseAbi11([
2816
3591
  "function getRewardsByAsset(address asset) external view returns (address[])",
2817
3592
  "function getRewardsData(address asset, address reward) external view returns (uint256 index, uint256 emissionsPerSecond, uint256 lastUpdateTimestamp, uint256 distributionEnd)"
2818
3593
  ]);
2819
- POOL_PROVIDER_ABI = parseAbi10([
3594
+ POOL_PROVIDER_ABI = parseAbi11([
2820
3595
  "function ADDRESSES_PROVIDER() external view returns (address)"
2821
3596
  ]);
2822
- ADDRESSES_PROVIDER_ABI = parseAbi10([
3597
+ ADDRESSES_PROVIDER_ABI = parseAbi11([
2823
3598
  "function getPriceOracle() external view returns (address)"
2824
3599
  ]);
2825
- ORACLE_ABI = parseAbi10([
3600
+ ORACLE_ABI = parseAbi11([
2826
3601
  "function getAssetPrice(address asset) external view returns (uint256)",
2827
3602
  "function BASE_CURRENCY_UNIT() external view returns (uint256)"
2828
3603
  ]);
2829
- ERC20_DECIMALS_ABI = parseAbi10([
3604
+ ERC20_DECIMALS_ABI = parseAbi11([
2830
3605
  "function decimals() external view returns (uint8)"
2831
3606
  ]);
2832
3607
  AaveV3Adapter = class {
@@ -2844,7 +3619,7 @@ var init_dist3 = __esm({
2844
3619
  return this.protocolName;
2845
3620
  }
2846
3621
  async buildSupply(params) {
2847
- const data = encodeFunctionData10({
3622
+ const data = encodeFunctionData11({
2848
3623
  abi: POOL_ABI,
2849
3624
  functionName: "supply",
2850
3625
  args: [params.asset, params.amount, params.on_behalf_of, 0]
@@ -2854,12 +3629,13 @@ var init_dist3 = __esm({
2854
3629
  to: this.pool,
2855
3630
  data,
2856
3631
  value: 0n,
2857
- gas_estimate: 3e5
3632
+ gas_estimate: 3e5,
3633
+ approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
2858
3634
  };
2859
3635
  }
2860
3636
  async buildBorrow(params) {
2861
3637
  const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
2862
- const data = encodeFunctionData10({
3638
+ const data = encodeFunctionData11({
2863
3639
  abi: POOL_ABI,
2864
3640
  functionName: "borrow",
2865
3641
  args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
@@ -2874,7 +3650,7 @@ var init_dist3 = __esm({
2874
3650
  }
2875
3651
  async buildRepay(params) {
2876
3652
  const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
2877
- const data = encodeFunctionData10({
3653
+ const data = encodeFunctionData11({
2878
3654
  abi: POOL_ABI,
2879
3655
  functionName: "repay",
2880
3656
  args: [params.asset, params.amount, rateMode, params.on_behalf_of]
@@ -2884,11 +3660,12 @@ var init_dist3 = __esm({
2884
3660
  to: this.pool,
2885
3661
  data,
2886
3662
  value: 0n,
2887
- gas_estimate: 3e5
3663
+ gas_estimate: 3e5,
3664
+ approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
2888
3665
  };
2889
3666
  }
2890
3667
  async buildWithdraw(params) {
2891
- const data = encodeFunctionData10({
3668
+ const data = encodeFunctionData11({
2892
3669
  abi: POOL_ABI,
2893
3670
  functionName: "withdraw",
2894
3671
  args: [params.asset, params.amount, params.to]
@@ -2903,15 +3680,21 @@ var init_dist3 = __esm({
2903
3680
  }
2904
3681
  async getRates(asset) {
2905
3682
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
2906
- const client = createPublicClient7({ transport: http7(this.rpcUrl) });
2907
- const result = await client.readContract({
2908
- address: this.pool,
3683
+ const reserveCallData = encodeFunctionData11({
2909
3684
  abi: POOL_ABI,
2910
3685
  functionName: "getReserveData",
2911
3686
  args: [asset]
2912
- }).catch((e) => {
3687
+ });
3688
+ const [reserveRaw] = await multicallRead(this.rpcUrl, [
3689
+ [this.pool, reserveCallData]
3690
+ ]).catch((e) => {
2913
3691
  throw DefiError.rpcError(`[${this.protocolName}] getReserveData failed: ${e}`);
2914
3692
  });
3693
+ const reserveDecoded = decodeReserveData(reserveRaw ?? null);
3694
+ if (!reserveDecoded) {
3695
+ throw DefiError.rpcError(`[${this.protocolName}] getReserveData returned no data`);
3696
+ }
3697
+ const result = reserveDecoded;
2915
3698
  const RAY = 1e27;
2916
3699
  const SECONDS_PER_YEAR4 = 31536e3;
2917
3700
  const toApy = (rayRate) => {
@@ -2923,74 +3706,56 @@ var init_dist3 = __esm({
2923
3706
  const stableRate = toApy(result[5]);
2924
3707
  const aTokenAddress = result[8];
2925
3708
  const variableDebtTokenAddress = result[10];
2926
- const [totalSupply, totalBorrow] = await Promise.all([
2927
- client.readContract({
2928
- address: aTokenAddress,
2929
- abi: ERC20_ABI,
2930
- functionName: "totalSupply"
2931
- }).catch(() => 0n),
2932
- client.readContract({
2933
- address: variableDebtTokenAddress,
2934
- abi: ERC20_ABI,
2935
- functionName: "totalSupply"
2936
- }).catch(() => 0n)
3709
+ const [supplyRaw, borrowRaw] = await multicallRead(this.rpcUrl, [
3710
+ [aTokenAddress, encodeFunctionData11({ abi: ERC20_ABI, functionName: "totalSupply" })],
3711
+ [variableDebtTokenAddress, encodeFunctionData11({ abi: ERC20_ABI, functionName: "totalSupply" })]
2937
3712
  ]);
3713
+ const totalSupply = decodeU256(supplyRaw ?? null);
3714
+ const totalBorrow = decodeU256(borrowRaw ?? null);
2938
3715
  const utilization = totalSupply > 0n ? Number(totalBorrow * 10000n / totalSupply) / 100 : 0;
2939
3716
  const supplyRewardTokens = [];
2940
3717
  const borrowRewardTokens = [];
2941
3718
  const supplyEmissions = [];
2942
3719
  const borrowEmissions = [];
2943
3720
  try {
2944
- const controllerAddr = await client.readContract({
2945
- address: aTokenAddress,
2946
- abi: INCENTIVES_ABI,
2947
- functionName: "getIncentivesController"
2948
- });
3721
+ const [controllerRaw] = await multicallRead(this.rpcUrl, [
3722
+ [aTokenAddress, encodeFunctionData11({ abi: INCENTIVES_ABI, functionName: "getIncentivesController" })]
3723
+ ]);
3724
+ const controllerAddr = decodeAddress(controllerRaw ?? null);
2949
3725
  if (controllerAddr && controllerAddr !== zeroAddress5) {
2950
- const [supplyRewards, borrowRewards] = await Promise.all([
2951
- client.readContract({
2952
- address: controllerAddr,
2953
- abi: REWARDS_CONTROLLER_ABI,
2954
- functionName: "getRewardsByAsset",
2955
- args: [aTokenAddress]
2956
- }).catch(() => []),
2957
- client.readContract({
2958
- address: controllerAddr,
2959
- abi: REWARDS_CONTROLLER_ABI,
2960
- functionName: "getRewardsByAsset",
2961
- args: [variableDebtTokenAddress]
2962
- }).catch(() => [])
3726
+ const [supplyRewardsRaw, borrowRewardsRaw] = await multicallRead(this.rpcUrl, [
3727
+ [controllerAddr, encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [aTokenAddress] })],
3728
+ [controllerAddr, encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [variableDebtTokenAddress] })]
2963
3729
  ]);
2964
- const supplyDataPromises = supplyRewards.map(
2965
- (reward) => client.readContract({
2966
- address: controllerAddr,
2967
- abi: REWARDS_CONTROLLER_ABI,
2968
- functionName: "getRewardsData",
2969
- args: [aTokenAddress, reward]
2970
- }).catch(() => null)
2971
- );
2972
- const supplyData = await Promise.all(supplyDataPromises);
2973
- for (let i = 0; i < supplyRewards.length; i++) {
2974
- const data = supplyData[i];
2975
- if (data && data[1] > 0n) {
2976
- supplyRewardTokens.push(supplyRewards[i]);
2977
- supplyEmissions.push(data[1].toString());
3730
+ const supplyRewards = decodeAddressArray(supplyRewardsRaw ?? null);
3731
+ const borrowRewards = decodeAddressArray(borrowRewardsRaw ?? null);
3732
+ const rewardsDataCalls = [
3733
+ ...supplyRewards.map((reward) => [
3734
+ controllerAddr,
3735
+ encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [aTokenAddress, reward] })
3736
+ ]),
3737
+ ...borrowRewards.map((reward) => [
3738
+ controllerAddr,
3739
+ encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [variableDebtTokenAddress, reward] })
3740
+ ])
3741
+ ];
3742
+ if (rewardsDataCalls.length > 0) {
3743
+ const rewardsDataResults = await multicallRead(this.rpcUrl, rewardsDataCalls);
3744
+ const supplyDataResults = rewardsDataResults.slice(0, supplyRewards.length);
3745
+ const borrowDataResults = rewardsDataResults.slice(supplyRewards.length);
3746
+ for (let i = 0; i < supplyRewards.length; i++) {
3747
+ const data = decodeRewardsData(supplyDataResults[i] ?? null);
3748
+ if (data && data[1] > 0n) {
3749
+ supplyRewardTokens.push(supplyRewards[i]);
3750
+ supplyEmissions.push(data[1].toString());
3751
+ }
2978
3752
  }
2979
- }
2980
- const borrowDataPromises = borrowRewards.map(
2981
- (reward) => client.readContract({
2982
- address: controllerAddr,
2983
- abi: REWARDS_CONTROLLER_ABI,
2984
- functionName: "getRewardsData",
2985
- args: [variableDebtTokenAddress, reward]
2986
- }).catch(() => null)
2987
- );
2988
- const borrowData = await Promise.all(borrowDataPromises);
2989
- for (let i = 0; i < borrowRewards.length; i++) {
2990
- const data = borrowData[i];
2991
- if (data && data[1] > 0n) {
2992
- borrowRewardTokens.push(borrowRewards[i]);
2993
- borrowEmissions.push(data[1].toString());
3753
+ for (let i = 0; i < borrowRewards.length; i++) {
3754
+ const data = decodeRewardsData(borrowDataResults[i] ?? null);
3755
+ if (data && data[1] > 0n) {
3756
+ borrowRewardTokens.push(borrowRewards[i]);
3757
+ borrowEmissions.push(data[1].toString());
3758
+ }
2994
3759
  }
2995
3760
  }
2996
3761
  }
@@ -3002,55 +3767,49 @@ var init_dist3 = __esm({
3002
3767
  const hasBorrowRewards = borrowRewardTokens.length > 0;
3003
3768
  if ((hasSupplyRewards || hasBorrowRewards) && totalSupply > 0n) {
3004
3769
  try {
3005
- const providerAddr = await client.readContract({
3006
- address: this.pool,
3007
- abi: POOL_PROVIDER_ABI,
3008
- functionName: "ADDRESSES_PROVIDER"
3009
- });
3010
- const oracleAddr = await client.readContract({
3011
- address: providerAddr,
3012
- abi: ADDRESSES_PROVIDER_ABI,
3013
- functionName: "getPriceOracle"
3014
- });
3015
- const [assetPrice, baseCurrencyUnit, assetDecimals] = await Promise.all([
3016
- client.readContract({
3017
- address: oracleAddr,
3018
- abi: ORACLE_ABI,
3019
- functionName: "getAssetPrice",
3020
- args: [asset]
3021
- }),
3022
- client.readContract({
3023
- address: oracleAddr,
3024
- abi: ORACLE_ABI,
3025
- functionName: "BASE_CURRENCY_UNIT"
3026
- }),
3027
- client.readContract({
3028
- address: asset,
3029
- abi: ERC20_DECIMALS_ABI,
3030
- functionName: "decimals"
3031
- }).catch(() => 18)
3770
+ const [providerRaw] = await multicallRead(this.rpcUrl, [
3771
+ [this.pool, encodeFunctionData11({ abi: POOL_PROVIDER_ABI, functionName: "ADDRESSES_PROVIDER" })]
3032
3772
  ]);
3033
- const priceUnit = Number(baseCurrencyUnit);
3773
+ const providerAddr = decodeAddress(providerRaw ?? null);
3774
+ if (!providerAddr) throw new Error("No provider address");
3775
+ const [oracleRaw] = await multicallRead(this.rpcUrl, [
3776
+ [providerAddr, encodeFunctionData11({ abi: ADDRESSES_PROVIDER_ABI, functionName: "getPriceOracle" })]
3777
+ ]);
3778
+ const oracleAddr = decodeAddress(oracleRaw ?? null);
3779
+ if (!oracleAddr) throw new Error("No oracle address");
3780
+ const [assetPriceRaw, baseCurrencyUnitRaw, assetDecimalsRaw] = await multicallRead(this.rpcUrl, [
3781
+ [oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [asset] })],
3782
+ [oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "BASE_CURRENCY_UNIT" })],
3783
+ [asset, encodeFunctionData11({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
3784
+ ]);
3785
+ const assetPrice = decodeU256(assetPriceRaw ?? null);
3786
+ const baseCurrencyUnit = decodeU256(baseCurrencyUnitRaw ?? null);
3787
+ const assetDecimals = assetDecimalsRaw ? Number(decodeU256(assetDecimalsRaw)) : 18;
3788
+ const priceUnit = Number(baseCurrencyUnit) || 1e8;
3034
3789
  const assetPriceF = Number(assetPrice) / priceUnit;
3035
3790
  const assetDecimalsDivisor = 10 ** assetDecimals;
3791
+ const allRewardTokens = Array.from(/* @__PURE__ */ new Set([...supplyRewardTokens, ...borrowRewardTokens]));
3792
+ const rewardPriceCalls = allRewardTokens.flatMap((token) => [
3793
+ [oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [token] })],
3794
+ [token, encodeFunctionData11({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
3795
+ ]);
3796
+ const rewardPriceResults = rewardPriceCalls.length > 0 ? await multicallRead(this.rpcUrl, rewardPriceCalls) : [];
3797
+ const rewardPriceMap = /* @__PURE__ */ new Map();
3798
+ for (let i = 0; i < allRewardTokens.length; i++) {
3799
+ const priceRaw = rewardPriceResults[i * 2] ?? null;
3800
+ const decimalsRaw = rewardPriceResults[i * 2 + 1] ?? null;
3801
+ const price = decodeU256(priceRaw);
3802
+ const decimals = decimalsRaw ? Number(decodeU256(decimalsRaw)) : 18;
3803
+ rewardPriceMap.set(allRewardTokens[i].toLowerCase(), { price, decimals });
3804
+ }
3036
3805
  if (hasSupplyRewards) {
3037
3806
  let totalSupplyIncentiveUsdPerYear = 0;
3038
3807
  const totalSupplyUsd = Number(totalSupply) / assetDecimalsDivisor * assetPriceF;
3039
3808
  for (let i = 0; i < supplyRewardTokens.length; i++) {
3040
3809
  const emissionPerSec = BigInt(supplyEmissions[i]);
3041
- const [rewardPrice, rewardDecimals] = await Promise.all([
3042
- client.readContract({
3043
- address: oracleAddr,
3044
- abi: ORACLE_ABI,
3045
- functionName: "getAssetPrice",
3046
- args: [supplyRewardTokens[i]]
3047
- }).catch(() => 0n),
3048
- client.readContract({
3049
- address: supplyRewardTokens[i],
3050
- abi: ERC20_DECIMALS_ABI,
3051
- functionName: "decimals"
3052
- }).catch(() => 18)
3053
- ]);
3810
+ const entry = rewardPriceMap.get(supplyRewardTokens[i].toLowerCase());
3811
+ const rewardPrice = entry?.price ?? 0n;
3812
+ const rewardDecimals = entry?.decimals ?? 18;
3054
3813
  if (rewardPrice > 0n) {
3055
3814
  const rewardPriceF = Number(rewardPrice) / priceUnit;
3056
3815
  const emissionPerYear = Number(emissionPerSec) / 10 ** rewardDecimals * SECONDS_PER_YEAR4;
@@ -3066,19 +3825,9 @@ var init_dist3 = __esm({
3066
3825
  const totalBorrowUsd = Number(totalBorrow) / assetDecimalsDivisor * assetPriceF;
3067
3826
  for (let i = 0; i < borrowRewardTokens.length; i++) {
3068
3827
  const emissionPerSec = BigInt(borrowEmissions[i]);
3069
- const [rewardPrice, rewardDecimals] = await Promise.all([
3070
- client.readContract({
3071
- address: oracleAddr,
3072
- abi: ORACLE_ABI,
3073
- functionName: "getAssetPrice",
3074
- args: [borrowRewardTokens[i]]
3075
- }).catch(() => 0n),
3076
- client.readContract({
3077
- address: borrowRewardTokens[i],
3078
- abi: ERC20_DECIMALS_ABI,
3079
- functionName: "decimals"
3080
- }).catch(() => 18)
3081
- ]);
3828
+ const entry = rewardPriceMap.get(borrowRewardTokens[i].toLowerCase());
3829
+ const rewardPrice = entry?.price ?? 0n;
3830
+ const rewardDecimals = entry?.decimals ?? 18;
3082
3831
  if (rewardPrice > 0n) {
3083
3832
  const rewardPriceF = Number(rewardPrice) / priceUnit;
3084
3833
  const emissionPerYear = Number(emissionPerSec) / 10 ** rewardDecimals * SECONDS_PER_YEAR4;
@@ -3142,7 +3891,7 @@ var init_dist3 = __esm({
3142
3891
  };
3143
3892
  }
3144
3893
  };
3145
- POOL_ABI2 = parseAbi11([
3894
+ POOL_ABI2 = parseAbi12([
3146
3895
  "function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
3147
3896
  "function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
3148
3897
  "function repay(address asset, uint256 amount, uint256 rateMode, address onBehalfOf) external returns (uint256)",
@@ -3155,7 +3904,7 @@ var init_dist3 = __esm({
3155
3904
  // [9]=variableDebtTokenAddress, [10]=interestRateStrategyAddress, [11]=id
3156
3905
  "function getReserveData(address asset) external view returns (uint256 configuration, uint128 liquidityIndex, uint128 variableBorrowIndex, uint128 currentLiquidityRate, uint128 currentVariableBorrowRate, uint128 currentStableBorrowRate, uint40 lastUpdateTimestamp, address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress, address interestRateStrategyAddress, uint8 id)"
3157
3906
  ]);
3158
- ERC20_ABI2 = parseAbi11([
3907
+ ERC20_ABI2 = parseAbi12([
3159
3908
  "function totalSupply() external view returns (uint256)"
3160
3909
  ]);
3161
3910
  AaveV2Adapter = class {
@@ -3173,7 +3922,7 @@ var init_dist3 = __esm({
3173
3922
  return this.protocolName;
3174
3923
  }
3175
3924
  async buildSupply(params) {
3176
- const data = encodeFunctionData11({
3925
+ const data = encodeFunctionData12({
3177
3926
  abi: POOL_ABI2,
3178
3927
  functionName: "deposit",
3179
3928
  args: [params.asset, params.amount, params.on_behalf_of, 0]
@@ -3183,12 +3932,13 @@ var init_dist3 = __esm({
3183
3932
  to: this.pool,
3184
3933
  data,
3185
3934
  value: 0n,
3186
- gas_estimate: 3e5
3935
+ gas_estimate: 3e5,
3936
+ approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
3187
3937
  };
3188
3938
  }
3189
3939
  async buildBorrow(params) {
3190
3940
  const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
3191
- const data = encodeFunctionData11({
3941
+ const data = encodeFunctionData12({
3192
3942
  abi: POOL_ABI2,
3193
3943
  functionName: "borrow",
3194
3944
  args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
@@ -3203,7 +3953,7 @@ var init_dist3 = __esm({
3203
3953
  }
3204
3954
  async buildRepay(params) {
3205
3955
  const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
3206
- const data = encodeFunctionData11({
3956
+ const data = encodeFunctionData12({
3207
3957
  abi: POOL_ABI2,
3208
3958
  functionName: "repay",
3209
3959
  args: [params.asset, params.amount, rateMode, params.on_behalf_of]
@@ -3213,11 +3963,12 @@ var init_dist3 = __esm({
3213
3963
  to: this.pool,
3214
3964
  data,
3215
3965
  value: 0n,
3216
- gas_estimate: 3e5
3966
+ gas_estimate: 3e5,
3967
+ approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
3217
3968
  };
3218
3969
  }
3219
3970
  async buildWithdraw(params) {
3220
- const data = encodeFunctionData11({
3971
+ const data = encodeFunctionData12({
3221
3972
  abi: POOL_ABI2,
3222
3973
  functionName: "withdraw",
3223
3974
  args: [params.asset, params.amount, params.to]
@@ -3305,7 +4056,7 @@ var init_dist3 = __esm({
3305
4056
  };
3306
4057
  }
3307
4058
  };
3308
- ORACLE_ABI2 = parseAbi12([
4059
+ ORACLE_ABI2 = parseAbi13([
3309
4060
  "function getAssetPrice(address asset) external view returns (uint256)",
3310
4061
  "function getAssetsPrices(address[] calldata assets) external view returns (uint256[] memory)",
3311
4062
  "function BASE_CURRENCY_UNIT() external view returns (uint256)"
@@ -3382,7 +4133,7 @@ var init_dist3 = __esm({
3382
4133
  });
3383
4134
  }
3384
4135
  };
3385
- CTOKEN_ABI = parseAbi13([
4136
+ CTOKEN_ABI = parseAbi14([
3386
4137
  "function supplyRatePerBlock() external view returns (uint256)",
3387
4138
  "function borrowRatePerBlock() external view returns (uint256)",
3388
4139
  "function totalSupply() external view returns (uint256)",
@@ -3409,7 +4160,7 @@ var init_dist3 = __esm({
3409
4160
  return this.protocolName;
3410
4161
  }
3411
4162
  async buildSupply(params) {
3412
- const data = encodeFunctionData12({
4163
+ const data = encodeFunctionData13({
3413
4164
  abi: CTOKEN_ABI,
3414
4165
  functionName: "mint",
3415
4166
  args: [params.amount]
@@ -3423,7 +4174,7 @@ var init_dist3 = __esm({
3423
4174
  };
3424
4175
  }
3425
4176
  async buildBorrow(params) {
3426
- const data = encodeFunctionData12({
4177
+ const data = encodeFunctionData13({
3427
4178
  abi: CTOKEN_ABI,
3428
4179
  functionName: "borrow",
3429
4180
  args: [params.amount]
@@ -3437,7 +4188,7 @@ var init_dist3 = __esm({
3437
4188
  };
3438
4189
  }
3439
4190
  async buildRepay(params) {
3440
- const data = encodeFunctionData12({
4191
+ const data = encodeFunctionData13({
3441
4192
  abi: CTOKEN_ABI,
3442
4193
  functionName: "repayBorrow",
3443
4194
  args: [params.amount]
@@ -3451,7 +4202,7 @@ var init_dist3 = __esm({
3451
4202
  };
3452
4203
  }
3453
4204
  async buildWithdraw(params) {
3454
- const data = encodeFunctionData12({
4205
+ const data = encodeFunctionData13({
3455
4206
  abi: CTOKEN_ABI,
3456
4207
  functionName: "redeem",
3457
4208
  args: [params.amount]
@@ -3500,7 +4251,7 @@ var init_dist3 = __esm({
3500
4251
  );
3501
4252
  }
3502
4253
  };
3503
- COMET_ABI = parseAbi14([
4254
+ COMET_ABI = parseAbi15([
3504
4255
  "function getUtilization() external view returns (uint256)",
3505
4256
  "function getSupplyRate(uint256 utilization) external view returns (uint64)",
3506
4257
  "function getBorrowRate(uint256 utilization) external view returns (uint64)",
@@ -3526,7 +4277,7 @@ var init_dist3 = __esm({
3526
4277
  return this.protocolName;
3527
4278
  }
3528
4279
  async buildSupply(params) {
3529
- const data = encodeFunctionData13({
4280
+ const data = encodeFunctionData14({
3530
4281
  abi: COMET_ABI,
3531
4282
  functionName: "supply",
3532
4283
  args: [params.asset, params.amount]
@@ -3540,7 +4291,7 @@ var init_dist3 = __esm({
3540
4291
  };
3541
4292
  }
3542
4293
  async buildBorrow(params) {
3543
- const data = encodeFunctionData13({
4294
+ const data = encodeFunctionData14({
3544
4295
  abi: COMET_ABI,
3545
4296
  functionName: "withdraw",
3546
4297
  args: [params.asset, params.amount]
@@ -3554,7 +4305,7 @@ var init_dist3 = __esm({
3554
4305
  };
3555
4306
  }
3556
4307
  async buildRepay(params) {
3557
- const data = encodeFunctionData13({
4308
+ const data = encodeFunctionData14({
3558
4309
  abi: COMET_ABI,
3559
4310
  functionName: "supply",
3560
4311
  args: [params.asset, params.amount]
@@ -3568,7 +4319,7 @@ var init_dist3 = __esm({
3568
4319
  };
3569
4320
  }
3570
4321
  async buildWithdraw(params) {
3571
- const data = encodeFunctionData13({
4322
+ const data = encodeFunctionData14({
3572
4323
  abi: COMET_ABI,
3573
4324
  functionName: "withdraw",
3574
4325
  args: [params.asset, params.amount]
@@ -3622,7 +4373,7 @@ var init_dist3 = __esm({
3622
4373
  );
3623
4374
  }
3624
4375
  };
3625
- EULER_VAULT_ABI = parseAbi15([
4376
+ EULER_VAULT_ABI = parseAbi16([
3626
4377
  "function deposit(uint256 amount, address receiver) external returns (uint256)",
3627
4378
  "function withdraw(uint256 amount, address receiver, address owner) external returns (uint256)",
3628
4379
  "function borrow(uint256 amount, address receiver) external returns (uint256)",
@@ -3648,7 +4399,7 @@ var init_dist3 = __esm({
3648
4399
  return this.protocolName;
3649
4400
  }
3650
4401
  async buildSupply(params) {
3651
- const data = encodeFunctionData14({
4402
+ const data = encodeFunctionData15({
3652
4403
  abi: EULER_VAULT_ABI,
3653
4404
  functionName: "deposit",
3654
4405
  args: [params.amount, params.on_behalf_of]
@@ -3662,7 +4413,7 @@ var init_dist3 = __esm({
3662
4413
  };
3663
4414
  }
3664
4415
  async buildBorrow(params) {
3665
- const data = encodeFunctionData14({
4416
+ const data = encodeFunctionData15({
3666
4417
  abi: EULER_VAULT_ABI,
3667
4418
  functionName: "borrow",
3668
4419
  args: [params.amount, params.on_behalf_of]
@@ -3676,7 +4427,7 @@ var init_dist3 = __esm({
3676
4427
  };
3677
4428
  }
3678
4429
  async buildRepay(params) {
3679
- const data = encodeFunctionData14({
4430
+ const data = encodeFunctionData15({
3680
4431
  abi: EULER_VAULT_ABI,
3681
4432
  functionName: "repay",
3682
4433
  args: [params.amount, params.on_behalf_of]
@@ -3690,7 +4441,7 @@ var init_dist3 = __esm({
3690
4441
  };
3691
4442
  }
3692
4443
  async buildWithdraw(params) {
3693
- const data = encodeFunctionData14({
4444
+ const data = encodeFunctionData15({
3694
4445
  abi: EULER_VAULT_ABI,
3695
4446
  functionName: "withdraw",
3696
4447
  args: [params.amount, params.to, params.to]
@@ -3739,7 +4490,7 @@ var init_dist3 = __esm({
3739
4490
  );
3740
4491
  }
3741
4492
  };
3742
- MORPHO_ABI = parseAbi16([
4493
+ MORPHO_ABI = parseAbi17([
3743
4494
  "function market(bytes32 id) external view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)",
3744
4495
  "function idToMarketParams(bytes32 id) external view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)",
3745
4496
  "function supply((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, uint256 shares, address onBehalf, bytes data) external returns (uint256 assetsSupplied, uint256 sharesSupplied)",
@@ -3747,13 +4498,13 @@ var init_dist3 = __esm({
3747
4498
  "function repay((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, uint256 shares, address onBehalf, bytes data) external returns (uint256 assetsRepaid, uint256 sharesRepaid)",
3748
4499
  "function withdraw((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, uint256 shares, address onBehalf, address receiver) external returns (uint256 assetsWithdrawn, uint256 sharesWithdrawn)"
3749
4500
  ]);
3750
- META_MORPHO_ABI = parseAbi16([
4501
+ META_MORPHO_ABI = parseAbi17([
3751
4502
  "function supplyQueueLength() external view returns (uint256)",
3752
4503
  "function supplyQueue(uint256 index) external view returns (bytes32)",
3753
4504
  "function totalAssets() external view returns (uint256)",
3754
4505
  "function totalSupply() external view returns (uint256)"
3755
4506
  ]);
3756
- IRM_ABI = parseAbi16([
4507
+ IRM_ABI = parseAbi17([
3757
4508
  "function borrowRateView((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee) market) external view returns (uint256)"
3758
4509
  ]);
3759
4510
  SECONDS_PER_YEAR3 = 365.25 * 24 * 3600;
@@ -3776,7 +4527,7 @@ var init_dist3 = __esm({
3776
4527
  }
3777
4528
  async buildSupply(params) {
3778
4529
  const market = defaultMarketParams(params.asset);
3779
- const data = encodeFunctionData15({
4530
+ const data = encodeFunctionData16({
3780
4531
  abi: MORPHO_ABI,
3781
4532
  functionName: "supply",
3782
4533
  args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
@@ -3791,7 +4542,7 @@ var init_dist3 = __esm({
3791
4542
  }
3792
4543
  async buildBorrow(params) {
3793
4544
  const market = defaultMarketParams(params.asset);
3794
- const data = encodeFunctionData15({
4545
+ const data = encodeFunctionData16({
3795
4546
  abi: MORPHO_ABI,
3796
4547
  functionName: "borrow",
3797
4548
  args: [market, params.amount, 0n, params.on_behalf_of, params.on_behalf_of]
@@ -3806,7 +4557,7 @@ var init_dist3 = __esm({
3806
4557
  }
3807
4558
  async buildRepay(params) {
3808
4559
  const market = defaultMarketParams(params.asset);
3809
- const data = encodeFunctionData15({
4560
+ const data = encodeFunctionData16({
3810
4561
  abi: MORPHO_ABI,
3811
4562
  functionName: "repay",
3812
4563
  args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
@@ -3821,7 +4572,7 @@ var init_dist3 = __esm({
3821
4572
  }
3822
4573
  async buildWithdraw(params) {
3823
4574
  const market = defaultMarketParams(params.asset);
3824
- const data = encodeFunctionData15({
4575
+ const data = encodeFunctionData16({
3825
4576
  abi: MORPHO_ABI,
3826
4577
  functionName: "withdraw",
3827
4578
  args: [market, params.amount, 0n, params.to, params.to]
@@ -3839,14 +4590,12 @@ var init_dist3 = __esm({
3839
4590
  if (!this.defaultVault) {
3840
4591
  throw DefiError.contractError(`[${this.protocolName}] No MetaMorpho vault configured for rate query`);
3841
4592
  }
3842
- const client = createPublicClient13({ transport: http13(this.rpcUrl) });
3843
- const queueLen = await client.readContract({
3844
- address: this.defaultVault,
3845
- abi: META_MORPHO_ABI,
3846
- functionName: "supplyQueueLength"
3847
- }).catch((e) => {
4593
+ const [queueLenRaw] = await multicallRead(this.rpcUrl, [
4594
+ [this.defaultVault, encodeFunctionData16({ abi: META_MORPHO_ABI, functionName: "supplyQueueLength" })]
4595
+ ]).catch((e) => {
3848
4596
  throw DefiError.rpcError(`[${this.protocolName}] supplyQueueLength failed: ${e}`);
3849
4597
  });
4598
+ const queueLen = decodeU256(queueLenRaw ?? null);
3850
4599
  if (queueLen === 0n) {
3851
4600
  return {
3852
4601
  protocol: this.protocolName,
@@ -3858,45 +4607,40 @@ var init_dist3 = __esm({
3858
4607
  total_borrow: 0n
3859
4608
  };
3860
4609
  }
3861
- const marketId = await client.readContract({
3862
- address: this.defaultVault,
3863
- abi: META_MORPHO_ABI,
3864
- functionName: "supplyQueue",
3865
- args: [0n]
3866
- }).catch((e) => {
4610
+ const [marketIdRaw] = await multicallRead(this.rpcUrl, [
4611
+ [this.defaultVault, encodeFunctionData16({ abi: META_MORPHO_ABI, functionName: "supplyQueue", args: [0n] })]
4612
+ ]).catch((e) => {
3867
4613
  throw DefiError.rpcError(`[${this.protocolName}] supplyQueue(0) failed: ${e}`);
3868
4614
  });
3869
- const mkt = await client.readContract({
3870
- address: this.morpho,
3871
- abi: MORPHO_ABI,
3872
- functionName: "market",
3873
- args: [marketId]
3874
- }).catch((e) => {
3875
- throw DefiError.rpcError(`[${this.protocolName}] market() failed: ${e}`);
4615
+ if (!marketIdRaw || marketIdRaw.length < 66) {
4616
+ throw DefiError.rpcError(`[${this.protocolName}] supplyQueue(0) returned no data`);
4617
+ }
4618
+ const marketId = marketIdRaw.slice(0, 66);
4619
+ const [marketRaw, paramsRaw] = await multicallRead(this.rpcUrl, [
4620
+ [this.morpho, encodeFunctionData16({ abi: MORPHO_ABI, functionName: "market", args: [marketId] })],
4621
+ [this.morpho, encodeFunctionData16({ abi: MORPHO_ABI, functionName: "idToMarketParams", args: [marketId] })]
4622
+ ]).catch((e) => {
4623
+ throw DefiError.rpcError(`[${this.protocolName}] market/idToMarketParams failed: ${e}`);
3876
4624
  });
3877
- const [totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee] = mkt;
4625
+ const mktDecoded = decodeMarket(marketRaw ?? null);
4626
+ if (!mktDecoded) throw DefiError.rpcError(`[${this.protocolName}] market() returned no data`);
4627
+ const [totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee] = mktDecoded;
4628
+ const paramsDecoded = decodeMarketParams(paramsRaw ?? null);
4629
+ if (!paramsDecoded) throw DefiError.rpcError(`[${this.protocolName}] idToMarketParams returned no data`);
4630
+ const [loanToken, collateralToken, oracle, irm, lltv] = paramsDecoded;
3878
4631
  const supplyF = Number(totalSupplyAssets);
3879
4632
  const borrowF = Number(totalBorrowAssets);
3880
4633
  const util = supplyF > 0 ? borrowF / supplyF : 0;
3881
- const params2 = await client.readContract({
3882
- address: this.morpho,
3883
- abi: MORPHO_ABI,
3884
- functionName: "idToMarketParams",
3885
- args: [marketId]
3886
- }).catch((e) => {
3887
- throw DefiError.rpcError(`[${this.protocolName}] idToMarketParams failed: ${e}`);
3888
- });
3889
- const [loanToken, collateralToken, oracle, irm, lltv] = params2;
3890
4634
  const irmMarketParams = { loanToken, collateralToken, oracle, irm, lltv };
3891
4635
  const irmMarket = { totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee };
3892
- const borrowRatePerSec = await client.readContract({
3893
- address: irm,
3894
- abi: IRM_ABI,
3895
- functionName: "borrowRateView",
3896
- args: [irmMarketParams, irmMarket]
3897
- }).catch((e) => {
3898
- throw DefiError.rpcError(`[${this.protocolName}] borrowRateView failed: ${e}`);
3899
- });
4636
+ const borrowRatePerSec = await (async () => {
4637
+ const [borrowRateRaw] = await multicallRead(this.rpcUrl, [
4638
+ [irm, encodeFunctionData16({ abi: IRM_ABI, functionName: "borrowRateView", args: [irmMarketParams, irmMarket] })]
4639
+ ]).catch((e) => {
4640
+ throw DefiError.rpcError(`[${this.protocolName}] borrowRateView failed: ${e}`);
4641
+ });
4642
+ return decodeU256(borrowRateRaw ?? null);
4643
+ })();
3900
4644
  const ratePerSec = Number(borrowRatePerSec) / 1e18;
3901
4645
  const borrowApy = ratePerSec * SECONDS_PER_YEAR3 * 100;
3902
4646
  const feePct = Number(fee) / 1e18;
@@ -3917,18 +4661,18 @@ var init_dist3 = __esm({
3917
4661
  );
3918
4662
  }
3919
4663
  };
3920
- BORROWER_OPS_ABI = parseAbi17([
4664
+ BORROWER_OPS_ABI = parseAbi18([
3921
4665
  "function openTrove(address _owner, uint256 _ownerIndex, uint256 _collAmount, uint256 _boldAmount, uint256 _upperHint, uint256 _lowerHint, uint256 _annualInterestRate, uint256 _maxUpfrontFee, address _addManager, address _removeManager, address _receiver) external returns (uint256)",
3922
4666
  "function adjustTrove(uint256 _troveId, uint256 _collChange, bool _isCollIncrease, uint256 _debtChange, bool _isDebtIncrease, uint256 _upperHint, uint256 _lowerHint, uint256 _maxUpfrontFee) external",
3923
4667
  "function closeTrove(uint256 _troveId) external"
3924
4668
  ]);
3925
- TROVE_MANAGER_ABI = parseAbi17([
4669
+ TROVE_MANAGER_ABI = parseAbi18([
3926
4670
  "function getLatestTroveData(uint256 _troveId) external view returns (uint256 entireDebt, uint256 entireColl, uint256 redistDebtGain, uint256 redistCollGain, uint256 accruedInterest, uint256 recordedDebt, uint256 annualInterestRate, uint256 accruedBatchManagementFee, uint256 weightedRecordedDebt, uint256 lastInterestRateAdjTime)"
3927
4671
  ]);
3928
- HINT_HELPERS_ABI = parseAbi17([
4672
+ HINT_HELPERS_ABI = parseAbi18([
3929
4673
  "function getApproxHint(uint256 _collIndex, uint256 _interestRate, uint256 _numTrials, uint256 _inputRandomSeed) external view returns (uint256 hintId, uint256 diff, uint256 latestRandomSeed)"
3930
4674
  ]);
3931
- SORTED_TROVES_ABI = parseAbi17([
4675
+ SORTED_TROVES_ABI = parseAbi18([
3932
4676
  "function findInsertPosition(uint256 _annualInterestRate, uint256 _prevId, uint256 _nextId) external view returns (uint256 prevId, uint256 nextId)"
3933
4677
  ]);
3934
4678
  FelixCdpAdapter = class {
@@ -3956,7 +4700,7 @@ var init_dist3 = __esm({
3956
4700
  if (!this.hintHelpers || !this.sortedTroves || !this.rpcUrl) {
3957
4701
  return [0n, 0n];
3958
4702
  }
3959
- const client = createPublicClient14({ transport: http14(this.rpcUrl) });
4703
+ const client = createPublicClient13({ transport: http13(this.rpcUrl) });
3960
4704
  const approxResult = await client.readContract({
3961
4705
  address: this.hintHelpers,
3962
4706
  abi: HINT_HELPERS_ABI,
@@ -3979,7 +4723,7 @@ var init_dist3 = __esm({
3979
4723
  const interestRate = 50000000000000000n;
3980
4724
  const [upperHint, lowerHint] = await this.getHints(interestRate);
3981
4725
  const hasHints = upperHint !== 0n || lowerHint !== 0n;
3982
- const data = encodeFunctionData16({
4726
+ const data = encodeFunctionData17({
3983
4727
  abi: BORROWER_OPS_ABI,
3984
4728
  functionName: "openTrove",
3985
4729
  args: [
@@ -4008,7 +4752,7 @@ var init_dist3 = __esm({
4008
4752
  async buildAdjust(params) {
4009
4753
  const collChange = params.collateral_delta ?? 0n;
4010
4754
  const debtChange = params.debt_delta ?? 0n;
4011
- const data = encodeFunctionData16({
4755
+ const data = encodeFunctionData17({
4012
4756
  abi: BORROWER_OPS_ABI,
4013
4757
  functionName: "adjustTrove",
4014
4758
  args: [
@@ -4031,7 +4775,7 @@ var init_dist3 = __esm({
4031
4775
  };
4032
4776
  }
4033
4777
  async buildClose(params) {
4034
- const data = encodeFunctionData16({
4778
+ const data = encodeFunctionData17({
4035
4779
  abi: BORROWER_OPS_ABI,
4036
4780
  functionName: "closeTrove",
4037
4781
  args: [params.cdp_id]
@@ -4047,7 +4791,7 @@ var init_dist3 = __esm({
4047
4791
  async getCdpInfo(cdpId) {
4048
4792
  if (!this.rpcUrl) throw DefiError.rpcError(`[${this.protocolName}] getCdpInfo requires RPC \u2014 set HYPEREVM_RPC_URL`);
4049
4793
  if (!this.troveManager) throw DefiError.contractError(`[${this.protocolName}] trove_manager contract not configured`);
4050
- const client = createPublicClient14({ transport: http14(this.rpcUrl) });
4794
+ const client = createPublicClient13({ transport: http13(this.rpcUrl) });
4051
4795
  const data = await client.readContract({
4052
4796
  address: this.troveManager,
4053
4797
  abi: TROVE_MANAGER_ABI,
@@ -4080,7 +4824,7 @@ var init_dist3 = __esm({
4080
4824
  };
4081
4825
  }
4082
4826
  };
4083
- PRICE_FEED_ABI = parseAbi18([
4827
+ PRICE_FEED_ABI = parseAbi19([
4084
4828
  "function fetchPrice() external view returns (uint256 price, bool isNewOracleFailureDetected)",
4085
4829
  "function lastGoodPrice() external view returns (uint256)"
4086
4830
  ]);
@@ -4106,7 +4850,7 @@ var init_dist3 = __esm({
4106
4850
  if (asset !== this.asset && this.asset !== "0x0000000000000000000000000000000000000000") {
4107
4851
  throw DefiError.unsupported(`[${this.protocolName}] Felix PriceFeed only supports asset ${this.asset}`);
4108
4852
  }
4109
- const client = createPublicClient15({ transport: http15(this.rpcUrl) });
4853
+ const client = createPublicClient14({ transport: http14(this.rpcUrl) });
4110
4854
  let priceVal;
4111
4855
  try {
4112
4856
  const result = await client.readContract({
@@ -4145,7 +4889,7 @@ var init_dist3 = __esm({
4145
4889
  return results;
4146
4890
  }
4147
4891
  };
4148
- ERC4626_ABI = parseAbi19([
4892
+ ERC4626_ABI = parseAbi20([
4149
4893
  "function asset() external view returns (address)",
4150
4894
  "function totalAssets() external view returns (uint256)",
4151
4895
  "function totalSupply() external view returns (uint256)",
@@ -4169,7 +4913,7 @@ var init_dist3 = __esm({
4169
4913
  return this.protocolName;
4170
4914
  }
4171
4915
  async buildDeposit(assets, receiver) {
4172
- const data = encodeFunctionData17({
4916
+ const data = encodeFunctionData18({
4173
4917
  abi: ERC4626_ABI,
4174
4918
  functionName: "deposit",
4175
4919
  args: [assets, receiver]
@@ -4183,7 +4927,7 @@ var init_dist3 = __esm({
4183
4927
  };
4184
4928
  }
4185
4929
  async buildWithdraw(assets, receiver, owner) {
4186
- const data = encodeFunctionData17({
4930
+ const data = encodeFunctionData18({
4187
4931
  abi: ERC4626_ABI,
4188
4932
  functionName: "withdraw",
4189
4933
  args: [assets, receiver, owner]
@@ -4198,7 +4942,7 @@ var init_dist3 = __esm({
4198
4942
  }
4199
4943
  async totalAssets() {
4200
4944
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4201
- const client = createPublicClient16({ transport: http16(this.rpcUrl) });
4945
+ const client = createPublicClient15({ transport: http15(this.rpcUrl) });
4202
4946
  return client.readContract({
4203
4947
  address: this.vaultAddress,
4204
4948
  abi: ERC4626_ABI,
@@ -4209,7 +4953,7 @@ var init_dist3 = __esm({
4209
4953
  }
4210
4954
  async convertToShares(assets) {
4211
4955
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4212
- const client = createPublicClient16({ transport: http16(this.rpcUrl) });
4956
+ const client = createPublicClient15({ transport: http15(this.rpcUrl) });
4213
4957
  return client.readContract({
4214
4958
  address: this.vaultAddress,
4215
4959
  abi: ERC4626_ABI,
@@ -4221,7 +4965,7 @@ var init_dist3 = __esm({
4221
4965
  }
4222
4966
  async convertToAssets(shares) {
4223
4967
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4224
- const client = createPublicClient16({ transport: http16(this.rpcUrl) });
4968
+ const client = createPublicClient15({ transport: http15(this.rpcUrl) });
4225
4969
  return client.readContract({
4226
4970
  address: this.vaultAddress,
4227
4971
  abi: ERC4626_ABI,
@@ -4233,7 +4977,7 @@ var init_dist3 = __esm({
4233
4977
  }
4234
4978
  async getVaultInfo() {
4235
4979
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4236
- const client = createPublicClient16({ transport: http16(this.rpcUrl) });
4980
+ const client = createPublicClient15({ transport: http15(this.rpcUrl) });
4237
4981
  const [totalAssets, totalSupply, asset] = await Promise.all([
4238
4982
  client.readContract({ address: this.vaultAddress, abi: ERC4626_ABI, functionName: "totalAssets" }).catch((e) => {
4239
4983
  throw DefiError.rpcError(`[${this.protocolName}] totalAssets failed: ${e}`);
@@ -4254,7 +4998,7 @@ var init_dist3 = __esm({
4254
4998
  };
4255
4999
  }
4256
5000
  };
4257
- GENERIC_LST_ABI = parseAbi20([
5001
+ GENERIC_LST_ABI = parseAbi21([
4258
5002
  "function stake() external payable returns (uint256)",
4259
5003
  "function unstake(uint256 amount) external returns (uint256)"
4260
5004
  ]);
@@ -4271,7 +5015,7 @@ var init_dist3 = __esm({
4271
5015
  return this.protocolName;
4272
5016
  }
4273
5017
  async buildStake(params) {
4274
- const data = encodeFunctionData18({ abi: GENERIC_LST_ABI, functionName: "stake" });
5018
+ const data = encodeFunctionData19({ abi: GENERIC_LST_ABI, functionName: "stake" });
4275
5019
  return {
4276
5020
  description: `[${this.protocolName}] Stake ${params.amount} HYPE`,
4277
5021
  to: this.staking,
@@ -4281,7 +5025,7 @@ var init_dist3 = __esm({
4281
5025
  };
4282
5026
  }
4283
5027
  async buildUnstake(params) {
4284
- const data = encodeFunctionData18({
5028
+ const data = encodeFunctionData19({
4285
5029
  abi: GENERIC_LST_ABI,
4286
5030
  functionName: "unstake",
4287
5031
  args: [params.amount]
@@ -4298,11 +5042,11 @@ var init_dist3 = __esm({
4298
5042
  throw DefiError.unsupported(`[${this.protocolName}] getInfo requires RPC`);
4299
5043
  }
4300
5044
  };
4301
- STHYPE_ABI = parseAbi21([
5045
+ STHYPE_ABI = parseAbi222([
4302
5046
  "function submit(address referral) external payable returns (uint256)",
4303
5047
  "function requestWithdrawals(uint256[] amounts, address owner) external returns (uint256[] requestIds)"
4304
5048
  ]);
4305
- ERC20_ABI3 = parseAbi21([
5049
+ ERC20_ABI3 = parseAbi222([
4306
5050
  "function totalSupply() external view returns (uint256)"
4307
5051
  ]);
4308
5052
  StHypeAdapter = class {
@@ -4322,7 +5066,7 @@ var init_dist3 = __esm({
4322
5066
  return this.protocolName;
4323
5067
  }
4324
5068
  async buildStake(params) {
4325
- const data = encodeFunctionData19({
5069
+ const data = encodeFunctionData20({
4326
5070
  abi: STHYPE_ABI,
4327
5071
  functionName: "submit",
4328
5072
  args: [zeroAddress9]
@@ -4336,7 +5080,7 @@ var init_dist3 = __esm({
4336
5080
  };
4337
5081
  }
4338
5082
  async buildUnstake(params) {
4339
- const data = encodeFunctionData19({
5083
+ const data = encodeFunctionData20({
4340
5084
  abi: STHYPE_ABI,
4341
5085
  functionName: "requestWithdrawals",
4342
5086
  args: [[params.amount], params.recipient]
@@ -4351,7 +5095,7 @@ var init_dist3 = __esm({
4351
5095
  }
4352
5096
  async getInfo() {
4353
5097
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4354
- const client = createPublicClient17({ transport: http17(this.rpcUrl) });
5098
+ const client = createPublicClient16({ transport: http16(this.rpcUrl) });
4355
5099
  const tokenAddr = this.sthypeToken ?? this.staking;
4356
5100
  const totalSupply = await client.readContract({
4357
5101
  address: tokenAddr,
@@ -4369,12 +5113,12 @@ var init_dist3 = __esm({
4369
5113
  };
4370
5114
  }
4371
5115
  };
4372
- KINETIQ_ABI = parseAbi222([
5116
+ KINETIQ_ABI = parseAbi23([
4373
5117
  "function stake() external payable returns (uint256)",
4374
5118
  "function requestUnstake(uint256 amount) external returns (uint256)",
4375
5119
  "function totalStaked() external view returns (uint256)"
4376
5120
  ]);
4377
- ORACLE_ABI3 = parseAbi222([
5121
+ ORACLE_ABI3 = parseAbi23([
4378
5122
  "function getAssetPrice(address asset) external view returns (uint256)"
4379
5123
  ]);
4380
5124
  WHYPE = "0x5555555555555555555555555555555555555555";
@@ -4396,7 +5140,7 @@ var init_dist3 = __esm({
4396
5140
  return this.protocolName;
4397
5141
  }
4398
5142
  async buildStake(params) {
4399
- const data = encodeFunctionData20({ abi: KINETIQ_ABI, functionName: "stake" });
5143
+ const data = encodeFunctionData21({ abi: KINETIQ_ABI, functionName: "stake" });
4400
5144
  return {
4401
5145
  description: `[${this.protocolName}] Stake ${params.amount} HYPE for kHYPE`,
4402
5146
  to: this.staking,
@@ -4406,7 +5150,7 @@ var init_dist3 = __esm({
4406
5150
  };
4407
5151
  }
4408
5152
  async buildUnstake(params) {
4409
- const data = encodeFunctionData20({
5153
+ const data = encodeFunctionData21({
4410
5154
  abi: KINETIQ_ABI,
4411
5155
  functionName: "requestUnstake",
4412
5156
  args: [params.amount]
@@ -4421,7 +5165,7 @@ var init_dist3 = __esm({
4421
5165
  }
4422
5166
  async getInfo() {
4423
5167
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4424
- const client = createPublicClient18({ transport: http18(this.rpcUrl) });
5168
+ const client = createPublicClient17({ transport: http17(this.rpcUrl) });
4425
5169
  const totalStaked = await client.readContract({
4426
5170
  address: this.staking,
4427
5171
  abi: KINETIQ_ABI,
@@ -4492,7 +5236,7 @@ var init_dist3 = __esm({
4492
5236
  );
4493
5237
  }
4494
5238
  };
4495
- HLP_ABI = parseAbi23([
5239
+ HLP_ABI = parseAbi24([
4496
5240
  "function deposit(uint256 amount) external returns (uint256)",
4497
5241
  "function withdraw(uint256 shares) external returns (uint256)"
4498
5242
  ]);
@@ -4509,7 +5253,7 @@ var init_dist3 = __esm({
4509
5253
  return this.protocolName;
4510
5254
  }
4511
5255
  async buildOpenPosition(params) {
4512
- const data = encodeFunctionData21({
5256
+ const data = encodeFunctionData222({
4513
5257
  abi: HLP_ABI,
4514
5258
  functionName: "deposit",
4515
5259
  args: [params.collateral]
@@ -4523,7 +5267,7 @@ var init_dist3 = __esm({
4523
5267
  };
4524
5268
  }
4525
5269
  async buildClosePosition(params) {
4526
- const data = encodeFunctionData21({
5270
+ const data = encodeFunctionData222({
4527
5271
  abi: HLP_ABI,
4528
5272
  functionName: "withdraw",
4529
5273
  args: [params.size]
@@ -4558,7 +5302,7 @@ var init_dist3 = __esm({
4558
5302
  );
4559
5303
  }
4560
5304
  };
4561
- RYSK_ABI = parseAbi24([
5305
+ RYSK_ABI = parseAbi25([
4562
5306
  "function openOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 premium)",
4563
5307
  "function closeOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 payout)"
4564
5308
  ]);
@@ -4575,7 +5319,7 @@ var init_dist3 = __esm({
4575
5319
  return this.protocolName;
4576
5320
  }
4577
5321
  async buildBuy(params) {
4578
- const data = encodeFunctionData222({
5322
+ const data = encodeFunctionData23({
4579
5323
  abi: RYSK_ABI,
4580
5324
  functionName: "openOption",
4581
5325
  args: [
@@ -4595,7 +5339,7 @@ var init_dist3 = __esm({
4595
5339
  };
4596
5340
  }
4597
5341
  async buildSell(params) {
4598
- const data = encodeFunctionData222({
5342
+ const data = encodeFunctionData23({
4599
5343
  abi: RYSK_ABI,
4600
5344
  functionName: "closeOption",
4601
5345
  args: [
@@ -4636,7 +5380,7 @@ var init_dist3 = __esm({
4636
5380
  );
4637
5381
  }
4638
5382
  };
4639
- ERC721_ABI = parseAbi25([
5383
+ ERC721_ABI = parseAbi26([
4640
5384
  "function name() returns (string)",
4641
5385
  "function symbol() returns (string)",
4642
5386
  "function totalSupply() returns (uint256)",
@@ -4656,7 +5400,7 @@ var init_dist3 = __esm({
4656
5400
  }
4657
5401
  async getCollectionInfo(collection) {
4658
5402
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4659
- const client = createPublicClient19({ transport: http19(this.rpcUrl) });
5403
+ const client = createPublicClient18({ transport: http18(this.rpcUrl) });
4660
5404
  const [collectionName, symbol, totalSupply] = await Promise.all([
4661
5405
  client.readContract({ address: collection, abi: ERC721_ABI, functionName: "name" }).catch((e) => {
4662
5406
  throw DefiError.rpcError(`[${this.protocolName}] name failed: ${e}`);
@@ -4675,7 +5419,7 @@ var init_dist3 = __esm({
4675
5419
  }
4676
5420
  async getTokenInfo(collection, tokenId) {
4677
5421
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4678
- const client = createPublicClient19({ transport: http19(this.rpcUrl) });
5422
+ const client = createPublicClient18({ transport: http18(this.rpcUrl) });
4679
5423
  const [owner, tokenUri] = await Promise.all([
4680
5424
  client.readContract({ address: collection, abi: ERC721_ABI, functionName: "ownerOf", args: [tokenId] }).catch((e) => {
4681
5425
  throw DefiError.rpcError(`[${this.protocolName}] ownerOf failed: ${e}`);
@@ -4691,7 +5435,7 @@ var init_dist3 = __esm({
4691
5435
  }
4692
5436
  async getBalance(owner, collection) {
4693
5437
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4694
- const client = createPublicClient19({ transport: http19(this.rpcUrl) });
5438
+ const client = createPublicClient18({ transport: http18(this.rpcUrl) });
4695
5439
  return client.readContract({ address: collection, abi: ERC721_ABI, functionName: "balanceOf", args: [owner] }).catch((e) => {
4696
5440
  throw DefiError.rpcError(`[${this.protocolName}] balanceOf failed: ${e}`);
4697
5441
  });
@@ -4747,10 +5491,16 @@ import { z } from "zod";
4747
5491
 
4748
5492
  // src/executor.ts
4749
5493
  init_dist2();
4750
- import { createPublicClient as createPublicClient20, createWalletClient, http as http20 } from "viem";
5494
+ init_dist2();
5495
+ import { createPublicClient as createPublicClient19, createWalletClient, http as http19, parseAbi as parseAbi27, encodeFunctionData as encodeFunctionData24 } from "viem";
4751
5496
  import { privateKeyToAccount } from "viem/accounts";
5497
+ var ERC20_ABI4 = parseAbi27([
5498
+ "function allowance(address owner, address spender) external view returns (uint256)",
5499
+ "function approve(address spender, uint256 amount) external returns (bool)"
5500
+ ]);
4752
5501
  var GAS_BUFFER_BPS = 12000n;
4753
- var DEFAULT_PRIORITY_FEE_WEI = 100000000n;
5502
+ var DEFAULT_PRIORITY_FEE_WEI = 20000000000n;
5503
+ var MAX_GAS_LIMIT = 5000000000n;
4754
5504
  var Executor = class _Executor {
4755
5505
  dryRun;
4756
5506
  rpcUrl;
@@ -4764,10 +5514,66 @@ var Executor = class _Executor {
4764
5514
  static applyGasBuffer(gas) {
4765
5515
  return gas * GAS_BUFFER_BPS / 10000n;
4766
5516
  }
5517
+ /**
5518
+ * Check allowance for a single token/spender pair and send an approve tx if needed.
5519
+ * Only called in broadcast mode (not dry-run).
5520
+ */
5521
+ async checkAndApprove(token, spender, amount, owner, publicClient, walletClient) {
5522
+ const allowance = await publicClient.readContract({
5523
+ address: token,
5524
+ abi: ERC20_ABI4,
5525
+ functionName: "allowance",
5526
+ args: [owner, spender]
5527
+ });
5528
+ if (allowance >= amount) return;
5529
+ process.stderr.write(
5530
+ ` Approving ${amount} of ${token} for ${spender}...
5531
+ `
5532
+ );
5533
+ const approveData = encodeFunctionData24({
5534
+ abi: ERC20_ABI4,
5535
+ functionName: "approve",
5536
+ args: [spender, amount]
5537
+ });
5538
+ const rpcUrl = this.rpcUrl;
5539
+ const gasLimit = await (async () => {
5540
+ try {
5541
+ const estimated = await publicClient.estimateGas({
5542
+ to: token,
5543
+ data: approveData,
5544
+ account: owner
5545
+ });
5546
+ const buffered = _Executor.applyGasBuffer(estimated);
5547
+ return buffered > MAX_GAS_LIMIT ? MAX_GAS_LIMIT : buffered;
5548
+ } catch {
5549
+ return 80000n;
5550
+ }
5551
+ })();
5552
+ const [maxFeePerGas, maxPriorityFeePerGas] = await this.fetchEip1559Fees(rpcUrl);
5553
+ const approveTxHash = await walletClient.sendTransaction({
5554
+ chain: null,
5555
+ account: walletClient.account,
5556
+ to: token,
5557
+ data: approveData,
5558
+ gas: gasLimit > 0n ? gasLimit : void 0,
5559
+ maxFeePerGas: maxFeePerGas > 0n ? maxFeePerGas : void 0,
5560
+ maxPriorityFeePerGas: maxPriorityFeePerGas > 0n ? maxPriorityFeePerGas : void 0
5561
+ });
5562
+ const approveTxUrl = this.explorerUrl ? `${this.explorerUrl}/tx/${approveTxHash}` : void 0;
5563
+ process.stderr.write(` Approve tx: ${approveTxHash}
5564
+ `);
5565
+ if (approveTxUrl) process.stderr.write(` Explorer: ${approveTxUrl}
5566
+ `);
5567
+ await publicClient.waitForTransactionReceipt({ hash: approveTxHash });
5568
+ process.stderr.write(
5569
+ ` Approved ${amount} of ${token} for ${spender}
5570
+ `
5571
+ );
5572
+ }
4767
5573
  /** Fetch EIP-1559 fee params from the network. Returns [maxFeePerGas, maxPriorityFeePerGas]. */
4768
5574
  async fetchEip1559Fees(rpcUrl) {
4769
5575
  try {
4770
- const client = createPublicClient20({ transport: http20(rpcUrl) });
5576
+ const client = createPublicClient19({ transport: http19(rpcUrl) });
4771
5577
  const gasPrice = await client.getGasPrice();
4772
5578
  let priorityFee = DEFAULT_PRIORITY_FEE_WEI;
4773
5579
  try {
@@ -4783,14 +5589,17 @@ var Executor = class _Executor {
4783
5589
  /** Estimate gas dynamically with buffer, falling back to a hardcoded estimate */
4784
5590
  async estimateGasWithBuffer(rpcUrl, tx, from) {
4785
5591
  try {
4786
- const client = createPublicClient20({ transport: http20(rpcUrl) });
5592
+ const client = createPublicClient19({ transport: http19(rpcUrl) });
4787
5593
  const estimated = await client.estimateGas({
4788
5594
  to: tx.to,
4789
5595
  data: tx.data,
4790
5596
  value: tx.value,
4791
5597
  account: from
4792
5598
  });
4793
- if (estimated > 0n) return _Executor.applyGasBuffer(estimated);
5599
+ if (estimated > 0n) {
5600
+ const buffered = _Executor.applyGasBuffer(estimated);
5601
+ return buffered > MAX_GAS_LIMIT ? MAX_GAS_LIMIT : buffered;
5602
+ }
4794
5603
  } catch {
4795
5604
  }
4796
5605
  return tx.gas_estimate ? BigInt(tx.gas_estimate) : 0n;
@@ -4801,9 +5610,49 @@ var Executor = class _Executor {
4801
5610
  if (!rpcUrl) {
4802
5611
  throw DefiError.rpcError("No RPC URL \u2014 cannot simulate. Set HYPEREVM_RPC_URL.");
4803
5612
  }
4804
- const client = createPublicClient20({ transport: http20(rpcUrl) });
5613
+ const client = createPublicClient19({ transport: http19(rpcUrl) });
4805
5614
  const privateKey = process.env["DEFI_PRIVATE_KEY"];
4806
5615
  const from = privateKey ? privateKeyToAccount(privateKey).address : "0x0000000000000000000000000000000000000001";
5616
+ if (tx.approvals && tx.approvals.length > 0) {
5617
+ const pendingApprovals = [];
5618
+ for (const approval of tx.approvals) {
5619
+ try {
5620
+ const allowance = await client.readContract({
5621
+ address: approval.token,
5622
+ abi: ERC20_ABI4,
5623
+ functionName: "allowance",
5624
+ args: [from, approval.spender]
5625
+ });
5626
+ if (allowance < approval.amount) {
5627
+ pendingApprovals.push({
5628
+ token: approval.token,
5629
+ spender: approval.spender,
5630
+ needed: approval.amount.toString(),
5631
+ current: allowance.toString()
5632
+ });
5633
+ }
5634
+ } catch {
5635
+ }
5636
+ }
5637
+ if (pendingApprovals.length > 0) {
5638
+ return {
5639
+ tx_hash: void 0,
5640
+ status: TxStatus.NeedsApproval,
5641
+ gas_used: tx.gas_estimate,
5642
+ description: tx.description,
5643
+ details: {
5644
+ to: tx.to,
5645
+ from,
5646
+ data: tx.data,
5647
+ value: tx.value.toString(),
5648
+ mode: "simulated",
5649
+ result: "needs_approval",
5650
+ pending_approvals: pendingApprovals,
5651
+ hint: "Use --broadcast to auto-approve and execute"
5652
+ }
5653
+ };
5654
+ }
5655
+ }
4807
5656
  try {
4808
5657
  await client.call({ to: tx.to, data: tx.data, value: tx.value, account: from });
4809
5658
  const gasEstimate = await this.estimateGasWithBuffer(rpcUrl, tx, from);
@@ -4874,8 +5723,20 @@ var Executor = class _Executor {
4874
5723
  if (!rpcUrl) {
4875
5724
  throw DefiError.rpcError("No RPC URL configured for broadcasting");
4876
5725
  }
4877
- const publicClient = createPublicClient20({ transport: http20(rpcUrl) });
4878
- const walletClient = createWalletClient({ account, transport: http20(rpcUrl) });
5726
+ const publicClient = createPublicClient19({ transport: http19(rpcUrl) });
5727
+ const walletClient = createWalletClient({ account, transport: http19(rpcUrl) });
5728
+ if (tx.approvals && tx.approvals.length > 0) {
5729
+ for (const approval of tx.approvals) {
5730
+ await this.checkAndApprove(
5731
+ approval.token,
5732
+ approval.spender,
5733
+ approval.amount,
5734
+ account.address,
5735
+ publicClient,
5736
+ walletClient
5737
+ );
5738
+ }
5739
+ }
4879
5740
  const gasLimit = await this.estimateGasWithBuffer(rpcUrl, tx, account.address);
4880
5741
  const [maxFeePerGas, maxPriorityFeePerGas] = await this.fetchEip1559Fees(rpcUrl);
4881
5742
  process.stderr.write(`Broadcasting transaction to ${rpcUrl}...
@@ -5502,8 +6363,8 @@ server.tool(
5502
6363
  const user = address;
5503
6364
  const { ProtocolCategory: ProtocolCategory2, multicallRead: multicallRead2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
5504
6365
  const { createLending: _createLending } = await Promise.resolve().then(() => (init_dist3(), dist_exports2));
5505
- const { encodeFunctionData: encodeFunctionData23, parseAbi: parseAbi26 } = await import("viem");
5506
- const POOL_ABI3 = parseAbi26([
6366
+ const { encodeFunctionData: encodeFunctionData25, parseAbi: parseAbi28 } = await import("viem");
6367
+ const POOL_ABI3 = parseAbi28([
5507
6368
  "function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
5508
6369
  ]);
5509
6370
  const lendingProtos = registry.getProtocolsForChain(chainName).filter((p) => p.category === ProtocolCategory2.Lending);
@@ -5512,7 +6373,7 @@ server.tool(
5512
6373
  const poolAddr = p.contracts?.pool;
5513
6374
  if (!poolAddr) continue;
5514
6375
  try {
5515
- const callData = encodeFunctionData23({ abi: POOL_ABI3, functionName: "getUserAccountData", args: [user] });
6376
+ const callData = encodeFunctionData25({ abi: POOL_ABI3, functionName: "getUserAccountData", args: [user] });
5516
6377
  const results = await multicallRead2(rpcUrl, [[poolAddr, callData]]);
5517
6378
  const raw = results[0];
5518
6379
  if (!raw || raw.length < 2 + 6 * 64) continue;