@hypurrquant/defi-cli 0.2.5 → 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.
package/dist/index.js CHANGED
@@ -703,6 +703,16 @@ function parse(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
703
703
 
704
704
  // ../defi-core/dist/index.js
705
705
  import { existsSync } from "fs";
706
+ var TxStatus = /* @__PURE__ */ ((TxStatus2) => {
707
+ TxStatus2["DryRun"] = "dry_run";
708
+ TxStatus2["Simulated"] = "simulated";
709
+ TxStatus2["SimulationFailed"] = "simulation_failed";
710
+ TxStatus2["NeedsApproval"] = "needs_approval";
711
+ TxStatus2["Pending"] = "pending";
712
+ TxStatus2["Confirmed"] = "confirmed";
713
+ TxStatus2["Failed"] = "failed";
714
+ return TxStatus2;
715
+ })(TxStatus || {});
706
716
  var InterestRateMode = /* @__PURE__ */ ((InterestRateMode2) => {
707
717
  InterestRateMode2["Variable"] = "variable";
708
718
  InterestRateMode2["Stable"] = "stable";
@@ -864,6 +874,10 @@ async function multicallRead(rpcUrl, calls) {
864
874
  });
865
875
  return decoded.map((r) => r.success ? r.returnData : null);
866
876
  }
877
+ function decodeU256(data) {
878
+ if (!data || data.length < 66) return 0n;
879
+ return BigInt(data.slice(0, 66));
880
+ }
867
881
  var ChainConfig = class {
868
882
  name;
869
883
  chain_id;
@@ -1127,6 +1141,46 @@ var Executor = class _Executor {
1127
1141
  const client = createPublicClient2({ transport: http2(rpcUrl) });
1128
1142
  const privateKey = process.env["DEFI_PRIVATE_KEY"];
1129
1143
  const from = privateKey ? privateKeyToAccount(privateKey).address : "0x0000000000000000000000000000000000000001";
1144
+ if (tx.approvals && tx.approvals.length > 0) {
1145
+ const pendingApprovals = [];
1146
+ for (const approval of tx.approvals) {
1147
+ try {
1148
+ const allowance = await client.readContract({
1149
+ address: approval.token,
1150
+ abi: ERC20_ABI,
1151
+ functionName: "allowance",
1152
+ args: [from, approval.spender]
1153
+ });
1154
+ if (allowance < approval.amount) {
1155
+ pendingApprovals.push({
1156
+ token: approval.token,
1157
+ spender: approval.spender,
1158
+ needed: approval.amount.toString(),
1159
+ current: allowance.toString()
1160
+ });
1161
+ }
1162
+ } catch {
1163
+ }
1164
+ }
1165
+ if (pendingApprovals.length > 0) {
1166
+ return {
1167
+ tx_hash: void 0,
1168
+ status: TxStatus.NeedsApproval,
1169
+ gas_used: tx.gas_estimate,
1170
+ description: tx.description,
1171
+ details: {
1172
+ to: tx.to,
1173
+ from,
1174
+ data: tx.data,
1175
+ value: tx.value.toString(),
1176
+ mode: "simulated",
1177
+ result: "needs_approval",
1178
+ pending_approvals: pendingApprovals,
1179
+ hint: "Use --broadcast to auto-approve and execute"
1180
+ }
1181
+ };
1182
+ }
1183
+ }
1130
1184
  try {
1131
1185
  await client.call({ to: tx.to, data: tx.data, value: tx.value, account: from });
1132
1186
  const gasEstimate = await this.estimateGasWithBuffer(rpcUrl, tx, from);
@@ -1792,26 +1846,33 @@ import { encodeFunctionData as encodeFunctionData22, parseAbi as parseAbi22, cre
1792
1846
  import { encodeFunctionData as encodeFunctionData32, parseAbi as parseAbi32, createPublicClient as createPublicClient32, http as http32, decodeAbiParameters as decodeAbiParameters3, concatHex, zeroAddress } from "viem";
1793
1847
  import { encodeFunctionData as encodeFunctionData42, parseAbi as parseAbi42, zeroAddress as zeroAddress2 } from "viem";
1794
1848
  import { encodeFunctionData as encodeFunctionData5, parseAbi as parseAbi5 } from "viem";
1795
- import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6, createPublicClient as createPublicClient42, http as http42, decodeAbiParameters as decodeAbiParameters4 } from "viem";
1849
+ import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6, decodeAbiParameters as decodeAbiParameters4 } from "viem";
1796
1850
  import { encodeFunctionData as encodeFunctionData7, parseAbi as parseAbi7, zeroAddress as zeroAddress3 } from "viem";
1797
- import { createPublicClient as createPublicClient5, encodeFunctionData as encodeFunctionData8, http as http5, parseAbi as parseAbi8, zeroAddress as zeroAddress4 } from "viem";
1798
- import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9, createPublicClient as createPublicClient6, http as http6 } from "viem";
1799
- import { createPublicClient as createPublicClient7, http as http7, parseAbi as parseAbi10, encodeFunctionData as encodeFunctionData10, zeroAddress as zeroAddress5 } from "viem";
1800
- import { createPublicClient as createPublicClient8, http as http8, parseAbi as parseAbi11, encodeFunctionData as encodeFunctionData11, zeroAddress as zeroAddress6 } from "viem";
1801
- import { createPublicClient as createPublicClient9, http as http9, parseAbi as parseAbi12 } from "viem";
1802
- import { createPublicClient as createPublicClient10, http as http10, parseAbi as parseAbi13, encodeFunctionData as encodeFunctionData12 } from "viem";
1803
- import { createPublicClient as createPublicClient11, http as http11, parseAbi as parseAbi14, encodeFunctionData as encodeFunctionData13 } from "viem";
1804
- import { createPublicClient as createPublicClient12, http as http12, parseAbi as parseAbi15, encodeFunctionData as encodeFunctionData14 } from "viem";
1805
- import { createPublicClient as createPublicClient13, http as http13, parseAbi as parseAbi16, encodeFunctionData as encodeFunctionData15, zeroAddress as zeroAddress7 } from "viem";
1806
- import { createPublicClient as createPublicClient14, http as http14, parseAbi as parseAbi17, encodeFunctionData as encodeFunctionData16, zeroAddress as zeroAddress8 } from "viem";
1807
- import { createPublicClient as createPublicClient15, http as http15, parseAbi as parseAbi18 } from "viem";
1808
- import { createPublicClient as createPublicClient16, http as http16, parseAbi as parseAbi19, encodeFunctionData as encodeFunctionData17 } from "viem";
1809
- import { parseAbi as parseAbi20, encodeFunctionData as encodeFunctionData18 } from "viem";
1810
- import { createPublicClient as createPublicClient17, http as http17, parseAbi as parseAbi21, encodeFunctionData as encodeFunctionData19, zeroAddress as zeroAddress9 } from "viem";
1811
- import { createPublicClient as createPublicClient18, http as http18, parseAbi as parseAbi222, encodeFunctionData as encodeFunctionData20, zeroAddress as zeroAddress10 } from "viem";
1812
- import { parseAbi as parseAbi23, encodeFunctionData as encodeFunctionData21 } from "viem";
1851
+ import { createPublicClient as createPublicClient42, encodeFunctionData as encodeFunctionData8, http as http42, parseAbi as parseAbi8, zeroAddress as zeroAddress4 } from "viem";
1852
+ import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9, createPublicClient as createPublicClient5, http as http5 } from "viem";
1853
+ import {
1854
+ encodeFunctionData as encodeFunctionData10,
1855
+ decodeFunctionResult as decodeFunctionResult22,
1856
+ parseAbi as parseAbi10,
1857
+ createPublicClient as createPublicClient6,
1858
+ http as http6
1859
+ } from "viem";
1860
+ import { createPublicClient as createPublicClient7, http as http7, parseAbi as parseAbi11, encodeFunctionData as encodeFunctionData11, decodeFunctionResult as decodeFunctionResult3, zeroAddress as zeroAddress5 } from "viem";
1861
+ import { createPublicClient as createPublicClient8, http as http8, parseAbi as parseAbi12, encodeFunctionData as encodeFunctionData12, zeroAddress as zeroAddress6 } from "viem";
1862
+ import { createPublicClient as createPublicClient9, http as http9, parseAbi as parseAbi13 } from "viem";
1863
+ import { createPublicClient as createPublicClient10, http as http10, parseAbi as parseAbi14, encodeFunctionData as encodeFunctionData13 } from "viem";
1864
+ import { createPublicClient as createPublicClient11, http as http11, parseAbi as parseAbi15, encodeFunctionData as encodeFunctionData14 } from "viem";
1865
+ import { createPublicClient as createPublicClient12, http as http12, parseAbi as parseAbi16, encodeFunctionData as encodeFunctionData15 } from "viem";
1866
+ import { parseAbi as parseAbi17, encodeFunctionData as encodeFunctionData16, decodeFunctionResult as decodeFunctionResult4, zeroAddress as zeroAddress7 } from "viem";
1867
+ import { createPublicClient as createPublicClient13, http as http13, parseAbi as parseAbi18, encodeFunctionData as encodeFunctionData17, zeroAddress as zeroAddress8 } from "viem";
1868
+ import { createPublicClient as createPublicClient14, http as http14, parseAbi as parseAbi19 } from "viem";
1869
+ import { createPublicClient as createPublicClient15, http as http15, parseAbi as parseAbi20, encodeFunctionData as encodeFunctionData18 } from "viem";
1870
+ import { parseAbi as parseAbi21, encodeFunctionData as encodeFunctionData19 } from "viem";
1871
+ import { createPublicClient as createPublicClient16, http as http16, parseAbi as parseAbi222, encodeFunctionData as encodeFunctionData20, zeroAddress as zeroAddress9 } from "viem";
1872
+ import { createPublicClient as createPublicClient17, http as http17, parseAbi as parseAbi23, encodeFunctionData as encodeFunctionData21, zeroAddress as zeroAddress10 } from "viem";
1813
1873
  import { parseAbi as parseAbi24, encodeFunctionData as encodeFunctionData222 } from "viem";
1814
- import { createPublicClient as createPublicClient19, http as http19, parseAbi as parseAbi25 } from "viem";
1874
+ import { parseAbi as parseAbi25, encodeFunctionData as encodeFunctionData23 } from "viem";
1875
+ import { createPublicClient as createPublicClient18, http as http18, parseAbi as parseAbi26 } from "viem";
1815
1876
  var DEFAULT_FEE = 3e3;
1816
1877
  var swapRouterAbi = parseAbi4([
1817
1878
  "struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; }",
@@ -2628,15 +2689,6 @@ var SolidlyAdapter = class {
2628
2689
  approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
2629
2690
  };
2630
2691
  }
2631
- async callGetAmountsOut(client, callData) {
2632
- const result = await client.call({ to: this.router, data: callData });
2633
- if (!result.data) return 0n;
2634
- const [amounts] = decodeAbiParameters4(
2635
- [{ name: "amounts", type: "uint256[]" }],
2636
- result.data
2637
- );
2638
- return amounts.length >= 2 ? amounts[amounts.length - 1] : 0n;
2639
- }
2640
2692
  encodeV1(params, stable) {
2641
2693
  return encodeFunctionData6({
2642
2694
  abi: abi4,
@@ -2653,7 +2705,6 @@ var SolidlyAdapter = class {
2653
2705
  }
2654
2706
  async quote(params) {
2655
2707
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
2656
- const client = createPublicClient42({ transport: http42(this.rpcUrl) });
2657
2708
  const candidates = [
2658
2709
  { callData: this.encodeV1(params, false), stable: false },
2659
2710
  { callData: this.encodeV1(params, true), stable: true }
@@ -2664,16 +2715,26 @@ var SolidlyAdapter = class {
2664
2715
  { callData: this.encodeV2(params, true), stable: true }
2665
2716
  );
2666
2717
  }
2667
- const results = await Promise.allSettled(
2668
- candidates.map((c) => this.callGetAmountsOut(client, c.callData))
2718
+ const rawResults = await multicallRead(
2719
+ this.rpcUrl,
2720
+ candidates.map((c) => [this.router, c.callData])
2669
2721
  );
2670
2722
  let bestOut = 0n;
2671
2723
  let bestStable = false;
2672
- for (let i = 0; i < results.length; i++) {
2673
- const r = results[i];
2674
- if (r.status === "fulfilled" && r.value > bestOut) {
2675
- bestOut = r.value;
2676
- bestStable = candidates[i].stable;
2724
+ for (let i = 0; i < rawResults.length; i++) {
2725
+ const raw = rawResults[i];
2726
+ if (!raw) continue;
2727
+ try {
2728
+ const [amounts] = decodeAbiParameters4(
2729
+ [{ name: "amounts", type: "uint256[]" }],
2730
+ raw
2731
+ );
2732
+ const out = amounts.length >= 2 ? amounts[amounts.length - 1] : 0n;
2733
+ if (out > bestOut) {
2734
+ bestOut = out;
2735
+ bestStable = candidates[i].stable;
2736
+ }
2737
+ } catch {
2677
2738
  }
2678
2739
  }
2679
2740
  if (bestOut === 0n) {
@@ -2885,7 +2946,7 @@ var SolidlyGaugeAdapter = class {
2885
2946
  async buildClaimRewards(gauge, account) {
2886
2947
  if (account && this.rpcUrl) {
2887
2948
  try {
2888
- const client = createPublicClient5({ transport: http5(this.rpcUrl) });
2949
+ const client = createPublicClient42({ transport: http42(this.rpcUrl) });
2889
2950
  const listLen = await client.readContract({
2890
2951
  address: gauge,
2891
2952
  abi: gaugeAbi,
@@ -3143,7 +3204,7 @@ var MasterChefAdapter = class {
3143
3204
  if (!this.rpcUrl) {
3144
3205
  throw DefiError.unsupported(`[${this.protocolName}] getPendingRewards requires RPC`);
3145
3206
  }
3146
- const client = createPublicClient6({ transport: http6(this.rpcUrl) });
3207
+ const client = createPublicClient5({ transport: http5(this.rpcUrl) });
3147
3208
  const rewards = await client.readContract({
3148
3209
  address: this.masterchef,
3149
3210
  abi: masterchefAbi,
@@ -3157,7 +3218,682 @@ var MasterChefAdapter = class {
3157
3218
  }));
3158
3219
  }
3159
3220
  };
3160
- var POOL_ABI = parseAbi10([
3221
+ var lbRouterAbi = parseAbi10([
3222
+ "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; }",
3223
+ "function addLiquidity(LiquidityParameters calldata liquidityParameters) external returns (uint256 amountXAdded, uint256 amountYAdded, uint256 amountXLeft, uint256 amountYLeft, uint256[] memory depositIds, uint256[] memory liquidityMinted)",
3224
+ "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)"
3225
+ ]);
3226
+ var lbFactoryAbi = parseAbi10([
3227
+ "function getNumberOfLBPairs() external view returns (uint256)",
3228
+ "function getLBPairAtIndex(uint256 index) external view returns (address)"
3229
+ ]);
3230
+ var lbPairAbi = parseAbi10([
3231
+ "function getLBHooksParameters() external view returns (bytes32)",
3232
+ "function getActiveId() external view returns (uint24)",
3233
+ "function getBinStep() external view returns (uint16)",
3234
+ "function getTokenX() external view returns (address)",
3235
+ "function getTokenY() external view returns (address)",
3236
+ "function balanceOf(address account, uint256 id) external view returns (uint256)",
3237
+ "function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory)"
3238
+ ]);
3239
+ var lbRewarderAbi = parseAbi10([
3240
+ "function getRewardToken() external view returns (address)",
3241
+ "function getRewardedRange() external view returns (uint256 minBinId, uint256 maxBinId)",
3242
+ "function getPendingRewards(address user, uint256[] calldata ids) external view returns (uint256 pendingRewards)",
3243
+ "function claim(address user, uint256[] calldata ids) external",
3244
+ "function getPid() external view returns (uint256)",
3245
+ "function isStopped() external view returns (bool)",
3246
+ "function getLBPair() external view returns (address)",
3247
+ "function getMasterChef() external view returns (address)"
3248
+ ]);
3249
+ var masterChefAbi = parseAbi10([
3250
+ "function getMoePerSecond() external view returns (uint256)",
3251
+ "function getTreasuryShare() external view returns (uint256)",
3252
+ "function getStaticShare() external view returns (uint256)",
3253
+ "function getVeMoe() external view returns (address)"
3254
+ ]);
3255
+ var veMoeAbi = parseAbi10([
3256
+ "function getWeight(uint256 pid) external view returns (uint256)",
3257
+ "function getTotalWeight() external view returns (uint256)",
3258
+ "function getTopPoolIds() external view returns (uint256[] memory)"
3259
+ ]);
3260
+ var lbPairBinAbi = parseAbi10([
3261
+ "function getBin(uint24 id) external view returns (uint128 reserveX, uint128 reserveY)",
3262
+ "function getActiveId() external view returns (uint24)"
3263
+ ]);
3264
+ var lbQuoterAbi2 = parseAbi10([
3265
+ "function findBestPathFromAmountIn(address[] calldata route, uint128 amountIn) external view returns ((address[] route, address[] pairs, uint256[] binSteps, uint256[] versions, uint128[] amounts, uint128[] virtualAmountsWithoutSlippage, uint128[] fees))"
3266
+ ]);
3267
+ var erc20Abi2 = parseAbi10([
3268
+ "function symbol() external view returns (string)"
3269
+ ]);
3270
+ var _addressAbi = parseAbi10(["function f() external view returns (address)"]);
3271
+ function decodeAddressResult(data) {
3272
+ if (!data) return null;
3273
+ try {
3274
+ return decodeFunctionResult22({ abi: _addressAbi, functionName: "f", data });
3275
+ } catch {
3276
+ return null;
3277
+ }
3278
+ }
3279
+ var _uint256Abi = parseAbi10(["function f() external view returns (uint256)"]);
3280
+ function decodeUint256Result(data) {
3281
+ if (!data) return null;
3282
+ try {
3283
+ return decodeFunctionResult22({ abi: _uint256Abi, functionName: "f", data });
3284
+ } catch {
3285
+ return null;
3286
+ }
3287
+ }
3288
+ var _boolAbi = parseAbi10(["function f() external view returns (bool)"]);
3289
+ function decodeBoolResult(data) {
3290
+ if (!data) return null;
3291
+ try {
3292
+ return decodeFunctionResult22({ abi: _boolAbi, functionName: "f", data });
3293
+ } catch {
3294
+ return null;
3295
+ }
3296
+ }
3297
+ function decodeStringResult(data) {
3298
+ if (!data) return "?";
3299
+ try {
3300
+ return decodeFunctionResult22({ abi: erc20Abi2, functionName: "symbol", data });
3301
+ } catch {
3302
+ return "?";
3303
+ }
3304
+ }
3305
+ var _rangeAbi = parseAbi10(["function f() external view returns (uint256 minBinId, uint256 maxBinId)"]);
3306
+ function decodeRangeResult(data) {
3307
+ if (!data) return null;
3308
+ try {
3309
+ return decodeFunctionResult22({ abi: _rangeAbi, functionName: "f", data });
3310
+ } catch {
3311
+ return null;
3312
+ }
3313
+ }
3314
+ var _binAbi = parseAbi10(["function f() external view returns (uint128 reserveX, uint128 reserveY)"]);
3315
+ function decodeBinResult(data) {
3316
+ if (!data) return null;
3317
+ try {
3318
+ return decodeFunctionResult22({ abi: _binAbi, functionName: "f", data });
3319
+ } catch {
3320
+ return null;
3321
+ }
3322
+ }
3323
+ var _uint256ArrayAbi = parseAbi10(["function f() external view returns (uint256[] memory)"]);
3324
+ function decodeUint256ArrayResult(data) {
3325
+ if (!data) return null;
3326
+ try {
3327
+ return decodeFunctionResult22({ abi: _uint256ArrayAbi, functionName: "f", data });
3328
+ } catch {
3329
+ return null;
3330
+ }
3331
+ }
3332
+ function extractRewarderAddress(hooksParams) {
3333
+ if (!hooksParams || hooksParams === "0x0000000000000000000000000000000000000000000000000000000000000000") {
3334
+ return null;
3335
+ }
3336
+ const hex = hooksParams.slice(2);
3337
+ if (hex.length < 64) return null;
3338
+ const addrHex = hex.slice(24, 64);
3339
+ if (addrHex === "0000000000000000000000000000000000000000") return null;
3340
+ return `0x${addrHex}`;
3341
+ }
3342
+ function buildUniformDistribution(deltaIds) {
3343
+ const PRECISION = 10n ** 18n;
3344
+ const n = deltaIds.length;
3345
+ const xBins = deltaIds.filter((d) => d >= 0).length;
3346
+ const yBins = deltaIds.filter((d) => d <= 0).length;
3347
+ const distributionX = [];
3348
+ const distributionY = [];
3349
+ for (const delta of deltaIds) {
3350
+ const xShare = delta >= 0 && xBins > 0 ? PRECISION / BigInt(xBins) : 0n;
3351
+ const yShare = delta <= 0 && yBins > 0 ? PRECISION / BigInt(yBins) : 0n;
3352
+ distributionX.push(xShare);
3353
+ distributionY.push(yShare);
3354
+ }
3355
+ const xSum = distributionX.reduce((a, b) => a + b, 0n);
3356
+ const ySum = distributionY.reduce((a, b) => a + b, 0n);
3357
+ if (xSum > 0n && xSum !== PRECISION) {
3358
+ const firstX = distributionX.findIndex((v) => v > 0n);
3359
+ if (firstX !== -1) distributionX[firstX] += PRECISION - xSum;
3360
+ }
3361
+ if (ySum > 0n && ySum !== PRECISION) {
3362
+ const firstY = distributionY.findIndex((v) => v > 0n);
3363
+ if (firstY !== -1) distributionY[firstY] += PRECISION - ySum;
3364
+ }
3365
+ return { distributionX, distributionY };
3366
+ }
3367
+ var MerchantMoeLBAdapter = class {
3368
+ protocolName;
3369
+ lbRouter;
3370
+ lbFactory;
3371
+ lbQuoter;
3372
+ rpcUrl;
3373
+ /** WMNT address (lb_mid_wmnt in config) used for MOE price routing */
3374
+ wmnt;
3375
+ /** USDT address (lb_mid_usdt in config) used for MNT/USD price routing */
3376
+ usdt;
3377
+ constructor(entry, rpcUrl) {
3378
+ this.protocolName = entry.name;
3379
+ const lbRouter = entry.contracts?.["lb_router"];
3380
+ if (!lbRouter) {
3381
+ throw new DefiError("CONTRACT_ERROR", "Missing 'lb_router' contract address");
3382
+ }
3383
+ const lbFactory = entry.contracts?.["lb_factory"];
3384
+ if (!lbFactory) {
3385
+ throw new DefiError("CONTRACT_ERROR", "Missing 'lb_factory' contract address");
3386
+ }
3387
+ this.lbRouter = lbRouter;
3388
+ this.lbFactory = lbFactory;
3389
+ this.lbQuoter = entry.contracts?.["lb_quoter"];
3390
+ this.wmnt = entry.contracts?.["lb_mid_wmnt"];
3391
+ this.usdt = entry.contracts?.["lb_mid_usdt"];
3392
+ this.rpcUrl = rpcUrl;
3393
+ }
3394
+ name() {
3395
+ return this.protocolName;
3396
+ }
3397
+ requireRpc() {
3398
+ if (!this.rpcUrl) {
3399
+ throw DefiError.rpcError(`[${this.protocolName}] RPC URL required`);
3400
+ }
3401
+ return this.rpcUrl;
3402
+ }
3403
+ /**
3404
+ * Build an addLiquidity transaction for a Liquidity Book pair.
3405
+ * Distributes tokenX/tokenY uniformly across active bin ± numBins.
3406
+ */
3407
+ async buildAddLiquidity(params) {
3408
+ const numBins = params.numBins ?? 5;
3409
+ const deadline = params.deadline ?? BigInt("18446744073709551615");
3410
+ let activeIdDesired = params.activeIdDesired;
3411
+ if (activeIdDesired === void 0) {
3412
+ const rpcUrl = this.requireRpc();
3413
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3414
+ const activeId = await client.readContract({
3415
+ address: params.pool,
3416
+ abi: lbPairAbi,
3417
+ functionName: "getActiveId"
3418
+ });
3419
+ activeIdDesired = activeId;
3420
+ }
3421
+ const deltaIds = [];
3422
+ for (let d = -numBins; d <= numBins; d++) {
3423
+ deltaIds.push(d);
3424
+ }
3425
+ const { distributionX, distributionY } = buildUniformDistribution(deltaIds);
3426
+ const data = encodeFunctionData10({
3427
+ abi: lbRouterAbi,
3428
+ functionName: "addLiquidity",
3429
+ args: [
3430
+ {
3431
+ tokenX: params.tokenX,
3432
+ tokenY: params.tokenY,
3433
+ binStep: BigInt(params.binStep),
3434
+ amountX: params.amountX,
3435
+ amountY: params.amountY,
3436
+ amountXMin: 0n,
3437
+ amountYMin: 0n,
3438
+ activeIdDesired: BigInt(activeIdDesired),
3439
+ idSlippage: BigInt(numBins + 2),
3440
+ deltaIds: deltaIds.map(BigInt),
3441
+ distributionX,
3442
+ distributionY,
3443
+ to: params.recipient,
3444
+ refundTo: params.recipient,
3445
+ deadline
3446
+ }
3447
+ ]
3448
+ });
3449
+ return {
3450
+ description: `[${this.protocolName}] LB addLiquidity ${params.amountX} tokenX + ${params.amountY} tokenY across ${deltaIds.length} bins`,
3451
+ to: this.lbRouter,
3452
+ data,
3453
+ value: 0n,
3454
+ gas_estimate: 8e5,
3455
+ approvals: [
3456
+ { token: params.tokenX, spender: this.lbRouter, amount: params.amountX },
3457
+ { token: params.tokenY, spender: this.lbRouter, amount: params.amountY }
3458
+ ]
3459
+ };
3460
+ }
3461
+ /**
3462
+ * Build a removeLiquidity transaction for specific LB bins.
3463
+ */
3464
+ async buildRemoveLiquidity(params) {
3465
+ const deadline = params.deadline ?? BigInt("18446744073709551615");
3466
+ const data = encodeFunctionData10({
3467
+ abi: lbRouterAbi,
3468
+ functionName: "removeLiquidity",
3469
+ args: [
3470
+ params.tokenX,
3471
+ params.tokenY,
3472
+ params.binStep,
3473
+ params.amountXMin ?? 0n,
3474
+ params.amountYMin ?? 0n,
3475
+ params.binIds.map(BigInt),
3476
+ params.amounts,
3477
+ params.recipient,
3478
+ deadline
3479
+ ]
3480
+ });
3481
+ return {
3482
+ description: `[${this.protocolName}] LB removeLiquidity from ${params.binIds.length} bins`,
3483
+ to: this.lbRouter,
3484
+ data,
3485
+ value: 0n,
3486
+ gas_estimate: 6e5
3487
+ };
3488
+ }
3489
+ /**
3490
+ * Auto-detect bin IDs for a pool from the rewarder's rewarded range.
3491
+ * Falls back to active bin ± 50 scan if no rewarder exists.
3492
+ */
3493
+ async autoDetectBins(pool) {
3494
+ const rpcUrl = this.requireRpc();
3495
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3496
+ const hooksParams = await client.readContract({
3497
+ address: pool,
3498
+ abi: lbPairAbi,
3499
+ functionName: "getLBHooksParameters"
3500
+ });
3501
+ const rewarder = extractRewarderAddress(hooksParams);
3502
+ if (rewarder) {
3503
+ const range = await client.readContract({
3504
+ address: rewarder,
3505
+ abi: lbRewarderAbi,
3506
+ functionName: "getRewardedRange"
3507
+ });
3508
+ const min = Number(range[0]);
3509
+ const max = Number(range[1]);
3510
+ const ids2 = [];
3511
+ for (let b = min; b <= max; b++) ids2.push(b);
3512
+ return ids2;
3513
+ }
3514
+ const activeId = await client.readContract({
3515
+ address: pool,
3516
+ abi: lbPairAbi,
3517
+ functionName: "getActiveId"
3518
+ });
3519
+ const ids = [];
3520
+ for (let b = activeId - 50; b <= activeId + 50; b++) ids.push(b);
3521
+ return ids;
3522
+ }
3523
+ /**
3524
+ * Get pending MOE rewards for a user across specified bin IDs.
3525
+ * If binIds is omitted, auto-detects from the rewarder's rewarded range.
3526
+ * Reads the rewarder address from the pool's hooks parameters.
3527
+ */
3528
+ async getPendingRewards(user, pool, binIds) {
3529
+ const rpcUrl = this.requireRpc();
3530
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3531
+ const hooksParams = await client.readContract({
3532
+ address: pool,
3533
+ abi: lbPairAbi,
3534
+ functionName: "getLBHooksParameters"
3535
+ });
3536
+ const rewarder = extractRewarderAddress(hooksParams);
3537
+ if (!rewarder) {
3538
+ return [];
3539
+ }
3540
+ let resolvedBinIds = binIds;
3541
+ if (!resolvedBinIds || resolvedBinIds.length === 0) {
3542
+ const range = await client.readContract({
3543
+ address: rewarder,
3544
+ abi: lbRewarderAbi,
3545
+ functionName: "getRewardedRange"
3546
+ });
3547
+ const min = Number(range[0]);
3548
+ const max = Number(range[1]);
3549
+ resolvedBinIds = [];
3550
+ for (let b = min; b <= max; b++) resolvedBinIds.push(b);
3551
+ }
3552
+ const [pending, rewardToken] = await Promise.all([
3553
+ client.readContract({
3554
+ address: rewarder,
3555
+ abi: lbRewarderAbi,
3556
+ functionName: "getPendingRewards",
3557
+ args: [user, resolvedBinIds.map(BigInt)]
3558
+ }),
3559
+ client.readContract({
3560
+ address: rewarder,
3561
+ abi: lbRewarderAbi,
3562
+ functionName: "getRewardToken"
3563
+ })
3564
+ ]);
3565
+ return [
3566
+ {
3567
+ token: rewardToken,
3568
+ symbol: "MOE",
3569
+ amount: pending
3570
+ }
3571
+ ];
3572
+ }
3573
+ /**
3574
+ * Build a claim rewards transaction for specific LB bins.
3575
+ * If binIds is omitted, auto-detects from the rewarder's rewarded range.
3576
+ */
3577
+ async buildClaimRewards(user, pool, binIds) {
3578
+ const rpcUrl = this.requireRpc();
3579
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3580
+ const hooksParams = await client.readContract({
3581
+ address: pool,
3582
+ abi: lbPairAbi,
3583
+ functionName: "getLBHooksParameters"
3584
+ });
3585
+ const rewarder = extractRewarderAddress(hooksParams);
3586
+ if (!rewarder) {
3587
+ throw new DefiError("CONTRACT_ERROR", `[${this.protocolName}] Pool ${pool} has no active rewarder`);
3588
+ }
3589
+ let resolvedBinIds = binIds;
3590
+ if (!resolvedBinIds || resolvedBinIds.length === 0) {
3591
+ const range = await client.readContract({
3592
+ address: rewarder,
3593
+ abi: lbRewarderAbi,
3594
+ functionName: "getRewardedRange"
3595
+ });
3596
+ const min = Number(range[0]);
3597
+ const max = Number(range[1]);
3598
+ resolvedBinIds = [];
3599
+ for (let b = min; b <= max; b++) resolvedBinIds.push(b);
3600
+ }
3601
+ const data = encodeFunctionData10({
3602
+ abi: lbRewarderAbi,
3603
+ functionName: "claim",
3604
+ args: [user, resolvedBinIds.map(BigInt)]
3605
+ });
3606
+ return {
3607
+ description: `[${this.protocolName}] LB claim rewards for ${resolvedBinIds.length} bins`,
3608
+ to: rewarder,
3609
+ data,
3610
+ value: 0n,
3611
+ gas_estimate: 3e5
3612
+ };
3613
+ }
3614
+ /**
3615
+ * Discover all active rewarded LB pools by iterating the factory.
3616
+ * Uses 7 multicall batches to minimise RPC round-trips and avoid 429s.
3617
+ *
3618
+ * Batch 1: getNumberOfLBPairs(), then getLBPairAtIndex(i) for all i
3619
+ * Batch 2: getLBHooksParameters() for all pairs → extract rewarder addresses
3620
+ * Batch 3: isStopped/getRewardedRange/getRewardToken/getPid/getMasterChef for each rewarder
3621
+ * Batch 4: getTokenX/getTokenY for each rewarded pair, then symbol() for unique tokens
3622
+ * Batch 5: Bootstrap MasterChef→VeMoe, then getMoePerSecond/getTreasuryShare/getStaticShare/getTotalWeight/getTopPoolIds
3623
+ * Batch 6: VeMoe.getWeight(pid) for each rewarded pool
3624
+ * Batch 7: Pool.getBin(binId) for all bins in rewarded range of each pool
3625
+ * Price: LB Quoter findBestPathFromAmountIn for MOE/WMNT and WMNT/USDT prices
3626
+ */
3627
+ async discoverRewardedPools() {
3628
+ const rpcUrl = this.requireRpc();
3629
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3630
+ const pairCount = await client.readContract({
3631
+ address: this.lbFactory,
3632
+ abi: lbFactoryAbi,
3633
+ functionName: "getNumberOfLBPairs"
3634
+ });
3635
+ const count = Number(pairCount);
3636
+ if (count === 0) return [];
3637
+ const batch1Calls = Array.from({ length: count }, (_, i) => [
3638
+ this.lbFactory,
3639
+ encodeFunctionData10({ abi: lbFactoryAbi, functionName: "getLBPairAtIndex", args: [BigInt(i)] })
3640
+ ]);
3641
+ const batch1Results = await multicallRead(rpcUrl, batch1Calls);
3642
+ const pairAddresses = batch1Results.map((r) => decodeAddressResult(r)).filter((a) => a !== null);
3643
+ if (pairAddresses.length === 0) return [];
3644
+ const batch2Calls = pairAddresses.map((pair) => [
3645
+ pair,
3646
+ encodeFunctionData10({ abi: lbPairAbi, functionName: "getLBHooksParameters" })
3647
+ ]);
3648
+ const batch2Results = await multicallRead(rpcUrl, batch2Calls);
3649
+ const rewardedPairs = [];
3650
+ for (let i = 0; i < pairAddresses.length; i++) {
3651
+ const raw = batch2Results[i];
3652
+ if (!raw) continue;
3653
+ let hooksBytes;
3654
+ try {
3655
+ const _bytes32Abi = parseAbi10(["function f() external view returns (bytes32)"]);
3656
+ hooksBytes = decodeFunctionResult22({ abi: _bytes32Abi, functionName: "f", data: raw });
3657
+ } catch {
3658
+ continue;
3659
+ }
3660
+ const rewarder = extractRewarderAddress(hooksBytes);
3661
+ if (rewarder) {
3662
+ rewardedPairs.push({ pool: pairAddresses[i], rewarder });
3663
+ }
3664
+ }
3665
+ if (rewardedPairs.length === 0) return [];
3666
+ const batch3Calls = [];
3667
+ for (const { rewarder } of rewardedPairs) {
3668
+ batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "isStopped" })]);
3669
+ batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getRewardedRange" })]);
3670
+ batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getRewardToken" })]);
3671
+ batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getPid" })]);
3672
+ batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getMasterChef" })]);
3673
+ }
3674
+ const batch3Results = await multicallRead(rpcUrl, batch3Calls);
3675
+ const batch4aCalls = [];
3676
+ for (const { pool } of rewardedPairs) {
3677
+ batch4aCalls.push([pool, encodeFunctionData10({ abi: lbPairAbi, functionName: "getTokenX" })]);
3678
+ batch4aCalls.push([pool, encodeFunctionData10({ abi: lbPairAbi, functionName: "getTokenY" })]);
3679
+ }
3680
+ const batch4aResults = await multicallRead(rpcUrl, batch4aCalls);
3681
+ const tokenXAddresses = [];
3682
+ const tokenYAddresses = [];
3683
+ for (let i = 0; i < rewardedPairs.length; i++) {
3684
+ tokenXAddresses.push(decodeAddressResult(batch4aResults[i * 2] ?? null));
3685
+ tokenYAddresses.push(decodeAddressResult(batch4aResults[i * 2 + 1] ?? null));
3686
+ }
3687
+ const uniqueTokens = Array.from(
3688
+ new Set([...tokenXAddresses, ...tokenYAddresses].filter((a) => a !== null))
3689
+ );
3690
+ const batch4bCalls = uniqueTokens.map((token) => [
3691
+ token,
3692
+ encodeFunctionData10({ abi: erc20Abi2, functionName: "symbol" })
3693
+ ]);
3694
+ const batch4bResults = await multicallRead(rpcUrl, batch4bCalls);
3695
+ const symbolMap = /* @__PURE__ */ new Map();
3696
+ for (let i = 0; i < uniqueTokens.length; i++) {
3697
+ symbolMap.set(uniqueTokens[i], decodeStringResult(batch4bResults[i] ?? null));
3698
+ }
3699
+ const STRIDE3 = 5;
3700
+ const poolData = [];
3701
+ for (let i = 0; i < rewardedPairs.length; i++) {
3702
+ const base = i * STRIDE3;
3703
+ poolData.push({
3704
+ stopped: decodeBoolResult(batch3Results[base] ?? null) ?? false,
3705
+ range: decodeRangeResult(batch3Results[base + 1] ?? null),
3706
+ rewardToken: decodeAddressResult(batch3Results[base + 2] ?? null),
3707
+ pid: Number(decodeUint256Result(batch3Results[base + 3] ?? null) ?? 0n),
3708
+ masterChef: decodeAddressResult(batch3Results[base + 4] ?? null)
3709
+ });
3710
+ }
3711
+ const masterChefAddr = poolData.map((d) => d.masterChef).find((a) => a !== null) ?? null;
3712
+ let moePerDay = 0;
3713
+ let topPoolIds = /* @__PURE__ */ new Set();
3714
+ let totalWeightRaw = 0n;
3715
+ let veMoeAddr = null;
3716
+ if (masterChefAddr) {
3717
+ veMoeAddr = await client.readContract({
3718
+ address: masterChefAddr,
3719
+ abi: masterChefAbi,
3720
+ functionName: "getVeMoe"
3721
+ });
3722
+ const batch5Calls = [
3723
+ [masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getMoePerSecond" })],
3724
+ [masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getTreasuryShare" })],
3725
+ [masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getStaticShare" })],
3726
+ [veMoeAddr, encodeFunctionData10({ abi: veMoeAbi, functionName: "getTotalWeight" })],
3727
+ [veMoeAddr, encodeFunctionData10({ abi: veMoeAbi, functionName: "getTopPoolIds" })]
3728
+ ];
3729
+ const batch5Results = await multicallRead(rpcUrl, batch5Calls);
3730
+ const moePerSecRaw = decodeUint256Result(batch5Results[0] ?? null) ?? 0n;
3731
+ const treasuryShareRaw = decodeUint256Result(batch5Results[1] ?? null) ?? 0n;
3732
+ const staticShareRaw = decodeUint256Result(batch5Results[2] ?? null) ?? 0n;
3733
+ totalWeightRaw = decodeUint256Result(batch5Results[3] ?? null) ?? 0n;
3734
+ const topPoolIdsRaw = decodeUint256ArrayResult(batch5Results[4] ?? null) ?? [];
3735
+ topPoolIds = new Set(topPoolIdsRaw.map(Number));
3736
+ const PRECISION = 10n ** 18n;
3737
+ const netPerSec = moePerSecRaw * (PRECISION - treasuryShareRaw) / PRECISION * (PRECISION - staticShareRaw) / PRECISION;
3738
+ moePerDay = Number(netPerSec * 86400n) / 1e18;
3739
+ }
3740
+ const weightByPid = /* @__PURE__ */ new Map();
3741
+ if (veMoeAddr && rewardedPairs.length > 0) {
3742
+ const batch6Calls = poolData.map((d) => [
3743
+ veMoeAddr,
3744
+ encodeFunctionData10({ abi: veMoeAbi, functionName: "getWeight", args: [BigInt(d.pid)] })
3745
+ ]);
3746
+ const batch6Results = await multicallRead(rpcUrl, batch6Calls);
3747
+ for (let i = 0; i < poolData.length; i++) {
3748
+ weightByPid.set(poolData[i].pid, decodeUint256Result(batch6Results[i] ?? null) ?? 0n);
3749
+ }
3750
+ }
3751
+ let moePriceUsd = 0;
3752
+ let wmntPriceUsd = 0;
3753
+ const MOE_ADDR = "0x4515A45337F461A11Ff0FE8aBF3c606AE5dC00c9";
3754
+ if (this.lbQuoter && this.wmnt && this.usdt) {
3755
+ try {
3756
+ const [moeWmntQuote, wmntUsdtQuote] = await Promise.all([
3757
+ client.readContract({
3758
+ address: this.lbQuoter,
3759
+ abi: lbQuoterAbi2,
3760
+ functionName: "findBestPathFromAmountIn",
3761
+ args: [[MOE_ADDR, this.wmnt], 10n ** 18n]
3762
+ }),
3763
+ client.readContract({
3764
+ address: this.lbQuoter,
3765
+ abi: lbQuoterAbi2,
3766
+ functionName: "findBestPathFromAmountIn",
3767
+ args: [[this.wmnt, this.usdt], 10n ** 18n]
3768
+ })
3769
+ ]);
3770
+ const moeInWmnt = Number(moeWmntQuote.amounts.at(-1) ?? 0n) / 1e18;
3771
+ wmntPriceUsd = Number(wmntUsdtQuote.amounts.at(-1) ?? 0n) / 1e6;
3772
+ moePriceUsd = moeInWmnt * wmntPriceUsd;
3773
+ } catch {
3774
+ }
3775
+ }
3776
+ const binRequests = [];
3777
+ for (let i = 0; i < rewardedPairs.length; i++) {
3778
+ const range = poolData[i].range;
3779
+ if (!range) continue;
3780
+ const minBin = Number(range[0]);
3781
+ const maxBin = Number(range[1]);
3782
+ for (let b = minBin; b <= maxBin; b++) {
3783
+ binRequests.push({ poolIdx: i, binId: b });
3784
+ }
3785
+ }
3786
+ const binReservesX = /* @__PURE__ */ new Map();
3787
+ const binReservesY = /* @__PURE__ */ new Map();
3788
+ if (binRequests.length > 0) {
3789
+ const batch7Calls = binRequests.map(({ poolIdx, binId }) => [
3790
+ rewardedPairs[poolIdx].pool,
3791
+ encodeFunctionData10({ abi: lbPairBinAbi, functionName: "getBin", args: [binId] })
3792
+ ]);
3793
+ const batch7Results = await multicallRead(rpcUrl, batch7Calls);
3794
+ for (let j = 0; j < binRequests.length; j++) {
3795
+ const { poolIdx, binId } = binRequests[j];
3796
+ const decoded = decodeBinResult(batch7Results[j] ?? null);
3797
+ if (!decoded) continue;
3798
+ if (!binReservesX.has(poolIdx)) {
3799
+ binReservesX.set(poolIdx, /* @__PURE__ */ new Map());
3800
+ binReservesY.set(poolIdx, /* @__PURE__ */ new Map());
3801
+ }
3802
+ binReservesX.get(poolIdx).set(binId, decoded[0]);
3803
+ binReservesY.get(poolIdx).set(binId, decoded[1]);
3804
+ }
3805
+ }
3806
+ const stableSymbols = /* @__PURE__ */ new Set(["USDT", "USDC", "MUSD", "AUSD", "USDY", "FDUSD"]);
3807
+ const mntSymbols = /* @__PURE__ */ new Set(["WMNT", "MNT"]);
3808
+ const moeSymbols = /* @__PURE__ */ new Set(["MOE"]);
3809
+ const sixDecimalStables = /* @__PURE__ */ new Set(["USDT", "USDC", "FDUSD"]);
3810
+ const getTokenPriceUsd = (sym) => {
3811
+ if (stableSymbols.has(sym)) return 1;
3812
+ if (mntSymbols.has(sym)) return wmntPriceUsd;
3813
+ if (moeSymbols.has(sym)) return moePriceUsd;
3814
+ return 0;
3815
+ };
3816
+ const getTokenDecimals = (sym) => {
3817
+ return sixDecimalStables.has(sym) ? 6 : 18;
3818
+ };
3819
+ const results = [];
3820
+ for (let i = 0; i < rewardedPairs.length; i++) {
3821
+ const { pool, rewarder } = rewardedPairs[i];
3822
+ const data = poolData[i];
3823
+ const tokenX = tokenXAddresses[i] ?? "0x0000000000000000000000000000000000000000";
3824
+ const tokenY = tokenYAddresses[i] ?? "0x0000000000000000000000000000000000000000";
3825
+ const symX = symbolMap.get(tokenX) ?? "?";
3826
+ const symY = symbolMap.get(tokenY) ?? "?";
3827
+ const isTopPool = topPoolIds.has(data.pid);
3828
+ const weight = weightByPid.get(data.pid) ?? 0n;
3829
+ let poolMoePerDay = 0;
3830
+ if (isTopPool && totalWeightRaw > 0n && weight > 0n) {
3831
+ poolMoePerDay = moePerDay * (Number(weight) / Number(totalWeightRaw));
3832
+ }
3833
+ const rxMap = binReservesX.get(i);
3834
+ const ryMap = binReservesY.get(i);
3835
+ const range = data.range;
3836
+ let rangeTvlUsd = 0;
3837
+ let rewardedBins = 0;
3838
+ if (range) {
3839
+ const minBin = Number(range[0]);
3840
+ const maxBin = Number(range[1]);
3841
+ rewardedBins = maxBin - minBin + 1;
3842
+ if (rxMap && ryMap) {
3843
+ const priceX = getTokenPriceUsd(symX);
3844
+ const priceY = getTokenPriceUsd(symY);
3845
+ const decX = getTokenDecimals(symX);
3846
+ const decY = getTokenDecimals(symY);
3847
+ for (let b = minBin; b <= maxBin; b++) {
3848
+ const rx = rxMap.get(b) ?? 0n;
3849
+ const ry = ryMap.get(b) ?? 0n;
3850
+ rangeTvlUsd += Number(rx) / 10 ** decX * priceX;
3851
+ rangeTvlUsd += Number(ry) / 10 ** decY * priceY;
3852
+ }
3853
+ }
3854
+ }
3855
+ const aprPercent = rangeTvlUsd > 0 && moePriceUsd > 0 ? poolMoePerDay * moePriceUsd * 365 / rangeTvlUsd * 100 : 0;
3856
+ results.push({
3857
+ pool,
3858
+ rewarder,
3859
+ rewardToken: data.rewardToken ?? "0x0000000000000000000000000000000000000000",
3860
+ minBinId: range ? Number(range[0]) : 0,
3861
+ maxBinId: range ? Number(range[1]) : 0,
3862
+ pid: data.pid,
3863
+ stopped: data.stopped,
3864
+ tokenX,
3865
+ tokenY,
3866
+ symbolX: symX,
3867
+ symbolY: symY,
3868
+ isTopPool,
3869
+ moePerDay: poolMoePerDay,
3870
+ rangeTvlUsd,
3871
+ aprPercent,
3872
+ rewardedBins
3873
+ });
3874
+ }
3875
+ return results;
3876
+ }
3877
+ /**
3878
+ * Get a user's LB positions (bin balances) across a range of bin IDs.
3879
+ * If binIds is omitted, auto-detects from the rewarder's rewarded range (or active ± 50).
3880
+ */
3881
+ async getUserPositions(user, pool, binIds) {
3882
+ const rpcUrl = this.requireRpc();
3883
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3884
+ const resolvedBinIds = binIds && binIds.length > 0 ? binIds : await this.autoDetectBins(pool);
3885
+ const accounts = resolvedBinIds.map(() => user);
3886
+ const ids = resolvedBinIds.map(BigInt);
3887
+ const balances = await client.readContract({
3888
+ address: pool,
3889
+ abi: lbPairAbi,
3890
+ functionName: "balanceOfBatch",
3891
+ args: [accounts, ids]
3892
+ });
3893
+ return resolvedBinIds.map((binId, i) => ({ binId, balance: balances[i] ?? 0n })).filter((p) => p.balance > 0n);
3894
+ }
3895
+ };
3896
+ var POOL_ABI = parseAbi11([
3161
3897
  "function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
3162
3898
  "function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
3163
3899
  "function repay(address asset, uint256 amount, uint256 interestRateMode, address onBehalfOf) external returns (uint256)",
@@ -3165,27 +3901,27 @@ var POOL_ABI = parseAbi10([
3165
3901
  "function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)",
3166
3902
  "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)"
3167
3903
  ]);
3168
- var ERC20_ABI2 = parseAbi10([
3904
+ var ERC20_ABI2 = parseAbi11([
3169
3905
  "function totalSupply() external view returns (uint256)"
3170
3906
  ]);
3171
- var INCENTIVES_ABI = parseAbi10([
3907
+ var INCENTIVES_ABI = parseAbi11([
3172
3908
  "function getIncentivesController() external view returns (address)"
3173
3909
  ]);
3174
- var REWARDS_CONTROLLER_ABI = parseAbi10([
3910
+ var REWARDS_CONTROLLER_ABI = parseAbi11([
3175
3911
  "function getRewardsByAsset(address asset) external view returns (address[])",
3176
3912
  "function getRewardsData(address asset, address reward) external view returns (uint256 index, uint256 emissionsPerSecond, uint256 lastUpdateTimestamp, uint256 distributionEnd)"
3177
3913
  ]);
3178
- var POOL_PROVIDER_ABI = parseAbi10([
3914
+ var POOL_PROVIDER_ABI = parseAbi11([
3179
3915
  "function ADDRESSES_PROVIDER() external view returns (address)"
3180
3916
  ]);
3181
- var ADDRESSES_PROVIDER_ABI = parseAbi10([
3917
+ var ADDRESSES_PROVIDER_ABI = parseAbi11([
3182
3918
  "function getPriceOracle() external view returns (address)"
3183
3919
  ]);
3184
- var ORACLE_ABI = parseAbi10([
3920
+ var ORACLE_ABI = parseAbi11([
3185
3921
  "function getAssetPrice(address asset) external view returns (uint256)",
3186
3922
  "function BASE_CURRENCY_UNIT() external view returns (uint256)"
3187
3923
  ]);
3188
- var ERC20_DECIMALS_ABI = parseAbi10([
3924
+ var ERC20_DECIMALS_ABI = parseAbi11([
3189
3925
  "function decimals() external view returns (uint8)"
3190
3926
  ]);
3191
3927
  function u256ToF64(v) {
@@ -3193,6 +3929,46 @@ function u256ToF64(v) {
3193
3929
  if (v > MAX_U128) return Infinity;
3194
3930
  return Number(v);
3195
3931
  }
3932
+ function decodeAddress(data) {
3933
+ if (!data || data.length < 66) return null;
3934
+ return `0x${data.slice(26, 66)}`;
3935
+ }
3936
+ function decodeAddressArray(data) {
3937
+ if (!data) return [];
3938
+ try {
3939
+ return decodeFunctionResult3({
3940
+ abi: REWARDS_CONTROLLER_ABI,
3941
+ functionName: "getRewardsByAsset",
3942
+ data
3943
+ });
3944
+ } catch {
3945
+ return [];
3946
+ }
3947
+ }
3948
+ function decodeReserveData(data) {
3949
+ if (!data) return null;
3950
+ try {
3951
+ return decodeFunctionResult3({
3952
+ abi: POOL_ABI,
3953
+ functionName: "getReserveData",
3954
+ data
3955
+ });
3956
+ } catch {
3957
+ return null;
3958
+ }
3959
+ }
3960
+ function decodeRewardsData(data) {
3961
+ if (!data) return null;
3962
+ try {
3963
+ return decodeFunctionResult3({
3964
+ abi: REWARDS_CONTROLLER_ABI,
3965
+ functionName: "getRewardsData",
3966
+ data
3967
+ });
3968
+ } catch {
3969
+ return null;
3970
+ }
3971
+ }
3196
3972
  var AaveV3Adapter = class {
3197
3973
  protocolName;
3198
3974
  pool;
@@ -3208,7 +3984,7 @@ var AaveV3Adapter = class {
3208
3984
  return this.protocolName;
3209
3985
  }
3210
3986
  async buildSupply(params) {
3211
- const data = encodeFunctionData10({
3987
+ const data = encodeFunctionData11({
3212
3988
  abi: POOL_ABI,
3213
3989
  functionName: "supply",
3214
3990
  args: [params.asset, params.amount, params.on_behalf_of, 0]
@@ -3224,7 +4000,7 @@ var AaveV3Adapter = class {
3224
4000
  }
3225
4001
  async buildBorrow(params) {
3226
4002
  const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
3227
- const data = encodeFunctionData10({
4003
+ const data = encodeFunctionData11({
3228
4004
  abi: POOL_ABI,
3229
4005
  functionName: "borrow",
3230
4006
  args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
@@ -3239,7 +4015,7 @@ var AaveV3Adapter = class {
3239
4015
  }
3240
4016
  async buildRepay(params) {
3241
4017
  const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
3242
- const data = encodeFunctionData10({
4018
+ const data = encodeFunctionData11({
3243
4019
  abi: POOL_ABI,
3244
4020
  functionName: "repay",
3245
4021
  args: [params.asset, params.amount, rateMode, params.on_behalf_of]
@@ -3254,7 +4030,7 @@ var AaveV3Adapter = class {
3254
4030
  };
3255
4031
  }
3256
4032
  async buildWithdraw(params) {
3257
- const data = encodeFunctionData10({
4033
+ const data = encodeFunctionData11({
3258
4034
  abi: POOL_ABI,
3259
4035
  functionName: "withdraw",
3260
4036
  args: [params.asset, params.amount, params.to]
@@ -3269,15 +4045,21 @@ var AaveV3Adapter = class {
3269
4045
  }
3270
4046
  async getRates(asset) {
3271
4047
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
3272
- const client = createPublicClient7({ transport: http7(this.rpcUrl) });
3273
- const result = await client.readContract({
3274
- address: this.pool,
4048
+ const reserveCallData = encodeFunctionData11({
3275
4049
  abi: POOL_ABI,
3276
4050
  functionName: "getReserveData",
3277
4051
  args: [asset]
3278
- }).catch((e) => {
4052
+ });
4053
+ const [reserveRaw] = await multicallRead(this.rpcUrl, [
4054
+ [this.pool, reserveCallData]
4055
+ ]).catch((e) => {
3279
4056
  throw DefiError.rpcError(`[${this.protocolName}] getReserveData failed: ${e}`);
3280
4057
  });
4058
+ const reserveDecoded = decodeReserveData(reserveRaw ?? null);
4059
+ if (!reserveDecoded) {
4060
+ throw DefiError.rpcError(`[${this.protocolName}] getReserveData returned no data`);
4061
+ }
4062
+ const result = reserveDecoded;
3281
4063
  const RAY = 1e27;
3282
4064
  const SECONDS_PER_YEAR4 = 31536e3;
3283
4065
  const toApy = (rayRate) => {
@@ -3289,74 +4071,56 @@ var AaveV3Adapter = class {
3289
4071
  const stableRate = toApy(result[5]);
3290
4072
  const aTokenAddress = result[8];
3291
4073
  const variableDebtTokenAddress = result[10];
3292
- const [totalSupply, totalBorrow] = await Promise.all([
3293
- client.readContract({
3294
- address: aTokenAddress,
3295
- abi: ERC20_ABI2,
3296
- functionName: "totalSupply"
3297
- }).catch(() => 0n),
3298
- client.readContract({
3299
- address: variableDebtTokenAddress,
3300
- abi: ERC20_ABI2,
3301
- functionName: "totalSupply"
3302
- }).catch(() => 0n)
4074
+ const [supplyRaw, borrowRaw] = await multicallRead(this.rpcUrl, [
4075
+ [aTokenAddress, encodeFunctionData11({ abi: ERC20_ABI2, functionName: "totalSupply" })],
4076
+ [variableDebtTokenAddress, encodeFunctionData11({ abi: ERC20_ABI2, functionName: "totalSupply" })]
3303
4077
  ]);
4078
+ const totalSupply = decodeU256(supplyRaw ?? null);
4079
+ const totalBorrow = decodeU256(borrowRaw ?? null);
3304
4080
  const utilization = totalSupply > 0n ? Number(totalBorrow * 10000n / totalSupply) / 100 : 0;
3305
4081
  const supplyRewardTokens = [];
3306
4082
  const borrowRewardTokens = [];
3307
4083
  const supplyEmissions = [];
3308
4084
  const borrowEmissions = [];
3309
4085
  try {
3310
- const controllerAddr = await client.readContract({
3311
- address: aTokenAddress,
3312
- abi: INCENTIVES_ABI,
3313
- functionName: "getIncentivesController"
3314
- });
4086
+ const [controllerRaw] = await multicallRead(this.rpcUrl, [
4087
+ [aTokenAddress, encodeFunctionData11({ abi: INCENTIVES_ABI, functionName: "getIncentivesController" })]
4088
+ ]);
4089
+ const controllerAddr = decodeAddress(controllerRaw ?? null);
3315
4090
  if (controllerAddr && controllerAddr !== zeroAddress5) {
3316
- const [supplyRewards, borrowRewards] = await Promise.all([
3317
- client.readContract({
3318
- address: controllerAddr,
3319
- abi: REWARDS_CONTROLLER_ABI,
3320
- functionName: "getRewardsByAsset",
3321
- args: [aTokenAddress]
3322
- }).catch(() => []),
3323
- client.readContract({
3324
- address: controllerAddr,
3325
- abi: REWARDS_CONTROLLER_ABI,
3326
- functionName: "getRewardsByAsset",
3327
- args: [variableDebtTokenAddress]
3328
- }).catch(() => [])
4091
+ const [supplyRewardsRaw, borrowRewardsRaw] = await multicallRead(this.rpcUrl, [
4092
+ [controllerAddr, encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [aTokenAddress] })],
4093
+ [controllerAddr, encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [variableDebtTokenAddress] })]
3329
4094
  ]);
3330
- const supplyDataPromises = supplyRewards.map(
3331
- (reward) => client.readContract({
3332
- address: controllerAddr,
3333
- abi: REWARDS_CONTROLLER_ABI,
3334
- functionName: "getRewardsData",
3335
- args: [aTokenAddress, reward]
3336
- }).catch(() => null)
3337
- );
3338
- const supplyData = await Promise.all(supplyDataPromises);
3339
- for (let i = 0; i < supplyRewards.length; i++) {
3340
- const data = supplyData[i];
3341
- if (data && data[1] > 0n) {
3342
- supplyRewardTokens.push(supplyRewards[i]);
3343
- supplyEmissions.push(data[1].toString());
4095
+ const supplyRewards = decodeAddressArray(supplyRewardsRaw ?? null);
4096
+ const borrowRewards = decodeAddressArray(borrowRewardsRaw ?? null);
4097
+ const rewardsDataCalls = [
4098
+ ...supplyRewards.map((reward) => [
4099
+ controllerAddr,
4100
+ encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [aTokenAddress, reward] })
4101
+ ]),
4102
+ ...borrowRewards.map((reward) => [
4103
+ controllerAddr,
4104
+ encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [variableDebtTokenAddress, reward] })
4105
+ ])
4106
+ ];
4107
+ if (rewardsDataCalls.length > 0) {
4108
+ const rewardsDataResults = await multicallRead(this.rpcUrl, rewardsDataCalls);
4109
+ const supplyDataResults = rewardsDataResults.slice(0, supplyRewards.length);
4110
+ const borrowDataResults = rewardsDataResults.slice(supplyRewards.length);
4111
+ for (let i = 0; i < supplyRewards.length; i++) {
4112
+ const data = decodeRewardsData(supplyDataResults[i] ?? null);
4113
+ if (data && data[1] > 0n) {
4114
+ supplyRewardTokens.push(supplyRewards[i]);
4115
+ supplyEmissions.push(data[1].toString());
4116
+ }
3344
4117
  }
3345
- }
3346
- const borrowDataPromises = borrowRewards.map(
3347
- (reward) => client.readContract({
3348
- address: controllerAddr,
3349
- abi: REWARDS_CONTROLLER_ABI,
3350
- functionName: "getRewardsData",
3351
- args: [variableDebtTokenAddress, reward]
3352
- }).catch(() => null)
3353
- );
3354
- const borrowData = await Promise.all(borrowDataPromises);
3355
- for (let i = 0; i < borrowRewards.length; i++) {
3356
- const data = borrowData[i];
3357
- if (data && data[1] > 0n) {
3358
- borrowRewardTokens.push(borrowRewards[i]);
3359
- borrowEmissions.push(data[1].toString());
4118
+ for (let i = 0; i < borrowRewards.length; i++) {
4119
+ const data = decodeRewardsData(borrowDataResults[i] ?? null);
4120
+ if (data && data[1] > 0n) {
4121
+ borrowRewardTokens.push(borrowRewards[i]);
4122
+ borrowEmissions.push(data[1].toString());
4123
+ }
3360
4124
  }
3361
4125
  }
3362
4126
  }
@@ -3368,55 +4132,49 @@ var AaveV3Adapter = class {
3368
4132
  const hasBorrowRewards = borrowRewardTokens.length > 0;
3369
4133
  if ((hasSupplyRewards || hasBorrowRewards) && totalSupply > 0n) {
3370
4134
  try {
3371
- const providerAddr = await client.readContract({
3372
- address: this.pool,
3373
- abi: POOL_PROVIDER_ABI,
3374
- functionName: "ADDRESSES_PROVIDER"
3375
- });
3376
- const oracleAddr = await client.readContract({
3377
- address: providerAddr,
3378
- abi: ADDRESSES_PROVIDER_ABI,
3379
- functionName: "getPriceOracle"
3380
- });
3381
- const [assetPrice, baseCurrencyUnit, assetDecimals] = await Promise.all([
3382
- client.readContract({
3383
- address: oracleAddr,
3384
- abi: ORACLE_ABI,
3385
- functionName: "getAssetPrice",
3386
- args: [asset]
3387
- }),
3388
- client.readContract({
3389
- address: oracleAddr,
3390
- abi: ORACLE_ABI,
3391
- functionName: "BASE_CURRENCY_UNIT"
3392
- }),
3393
- client.readContract({
3394
- address: asset,
3395
- abi: ERC20_DECIMALS_ABI,
3396
- functionName: "decimals"
3397
- }).catch(() => 18)
4135
+ const [providerRaw] = await multicallRead(this.rpcUrl, [
4136
+ [this.pool, encodeFunctionData11({ abi: POOL_PROVIDER_ABI, functionName: "ADDRESSES_PROVIDER" })]
3398
4137
  ]);
3399
- const priceUnit = Number(baseCurrencyUnit);
4138
+ const providerAddr = decodeAddress(providerRaw ?? null);
4139
+ if (!providerAddr) throw new Error("No provider address");
4140
+ const [oracleRaw] = await multicallRead(this.rpcUrl, [
4141
+ [providerAddr, encodeFunctionData11({ abi: ADDRESSES_PROVIDER_ABI, functionName: "getPriceOracle" })]
4142
+ ]);
4143
+ const oracleAddr = decodeAddress(oracleRaw ?? null);
4144
+ if (!oracleAddr) throw new Error("No oracle address");
4145
+ const [assetPriceRaw, baseCurrencyUnitRaw, assetDecimalsRaw] = await multicallRead(this.rpcUrl, [
4146
+ [oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [asset] })],
4147
+ [oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "BASE_CURRENCY_UNIT" })],
4148
+ [asset, encodeFunctionData11({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
4149
+ ]);
4150
+ const assetPrice = decodeU256(assetPriceRaw ?? null);
4151
+ const baseCurrencyUnit = decodeU256(baseCurrencyUnitRaw ?? null);
4152
+ const assetDecimals = assetDecimalsRaw ? Number(decodeU256(assetDecimalsRaw)) : 18;
4153
+ const priceUnit = Number(baseCurrencyUnit) || 1e8;
3400
4154
  const assetPriceF = Number(assetPrice) / priceUnit;
3401
4155
  const assetDecimalsDivisor = 10 ** assetDecimals;
4156
+ const allRewardTokens = Array.from(/* @__PURE__ */ new Set([...supplyRewardTokens, ...borrowRewardTokens]));
4157
+ const rewardPriceCalls = allRewardTokens.flatMap((token) => [
4158
+ [oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [token] })],
4159
+ [token, encodeFunctionData11({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
4160
+ ]);
4161
+ const rewardPriceResults = rewardPriceCalls.length > 0 ? await multicallRead(this.rpcUrl, rewardPriceCalls) : [];
4162
+ const rewardPriceMap = /* @__PURE__ */ new Map();
4163
+ for (let i = 0; i < allRewardTokens.length; i++) {
4164
+ const priceRaw = rewardPriceResults[i * 2] ?? null;
4165
+ const decimalsRaw = rewardPriceResults[i * 2 + 1] ?? null;
4166
+ const price = decodeU256(priceRaw);
4167
+ const decimals = decimalsRaw ? Number(decodeU256(decimalsRaw)) : 18;
4168
+ rewardPriceMap.set(allRewardTokens[i].toLowerCase(), { price, decimals });
4169
+ }
3402
4170
  if (hasSupplyRewards) {
3403
4171
  let totalSupplyIncentiveUsdPerYear = 0;
3404
4172
  const totalSupplyUsd = Number(totalSupply) / assetDecimalsDivisor * assetPriceF;
3405
4173
  for (let i = 0; i < supplyRewardTokens.length; i++) {
3406
4174
  const emissionPerSec = BigInt(supplyEmissions[i]);
3407
- const [rewardPrice, rewardDecimals] = await Promise.all([
3408
- client.readContract({
3409
- address: oracleAddr,
3410
- abi: ORACLE_ABI,
3411
- functionName: "getAssetPrice",
3412
- args: [supplyRewardTokens[i]]
3413
- }).catch(() => 0n),
3414
- client.readContract({
3415
- address: supplyRewardTokens[i],
3416
- abi: ERC20_DECIMALS_ABI,
3417
- functionName: "decimals"
3418
- }).catch(() => 18)
3419
- ]);
4175
+ const entry = rewardPriceMap.get(supplyRewardTokens[i].toLowerCase());
4176
+ const rewardPrice = entry?.price ?? 0n;
4177
+ const rewardDecimals = entry?.decimals ?? 18;
3420
4178
  if (rewardPrice > 0n) {
3421
4179
  const rewardPriceF = Number(rewardPrice) / priceUnit;
3422
4180
  const emissionPerYear = Number(emissionPerSec) / 10 ** rewardDecimals * SECONDS_PER_YEAR4;
@@ -3432,19 +4190,9 @@ var AaveV3Adapter = class {
3432
4190
  const totalBorrowUsd = Number(totalBorrow) / assetDecimalsDivisor * assetPriceF;
3433
4191
  for (let i = 0; i < borrowRewardTokens.length; i++) {
3434
4192
  const emissionPerSec = BigInt(borrowEmissions[i]);
3435
- const [rewardPrice, rewardDecimals] = await Promise.all([
3436
- client.readContract({
3437
- address: oracleAddr,
3438
- abi: ORACLE_ABI,
3439
- functionName: "getAssetPrice",
3440
- args: [borrowRewardTokens[i]]
3441
- }).catch(() => 0n),
3442
- client.readContract({
3443
- address: borrowRewardTokens[i],
3444
- abi: ERC20_DECIMALS_ABI,
3445
- functionName: "decimals"
3446
- }).catch(() => 18)
3447
- ]);
4193
+ const entry = rewardPriceMap.get(borrowRewardTokens[i].toLowerCase());
4194
+ const rewardPrice = entry?.price ?? 0n;
4195
+ const rewardDecimals = entry?.decimals ?? 18;
3448
4196
  if (rewardPrice > 0n) {
3449
4197
  const rewardPriceF = Number(rewardPrice) / priceUnit;
3450
4198
  const emissionPerYear = Number(emissionPerSec) / 10 ** rewardDecimals * SECONDS_PER_YEAR4;
@@ -3508,7 +4256,7 @@ var AaveV3Adapter = class {
3508
4256
  };
3509
4257
  }
3510
4258
  };
3511
- var POOL_ABI2 = parseAbi11([
4259
+ var POOL_ABI2 = parseAbi12([
3512
4260
  "function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
3513
4261
  "function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
3514
4262
  "function repay(address asset, uint256 amount, uint256 rateMode, address onBehalfOf) external returns (uint256)",
@@ -3521,7 +4269,7 @@ var POOL_ABI2 = parseAbi11([
3521
4269
  // [9]=variableDebtTokenAddress, [10]=interestRateStrategyAddress, [11]=id
3522
4270
  "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)"
3523
4271
  ]);
3524
- var ERC20_ABI22 = parseAbi11([
4272
+ var ERC20_ABI22 = parseAbi12([
3525
4273
  "function totalSupply() external view returns (uint256)"
3526
4274
  ]);
3527
4275
  function u256ToF642(v) {
@@ -3544,7 +4292,7 @@ var AaveV2Adapter = class {
3544
4292
  return this.protocolName;
3545
4293
  }
3546
4294
  async buildSupply(params) {
3547
- const data = encodeFunctionData11({
4295
+ const data = encodeFunctionData12({
3548
4296
  abi: POOL_ABI2,
3549
4297
  functionName: "deposit",
3550
4298
  args: [params.asset, params.amount, params.on_behalf_of, 0]
@@ -3560,7 +4308,7 @@ var AaveV2Adapter = class {
3560
4308
  }
3561
4309
  async buildBorrow(params) {
3562
4310
  const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
3563
- const data = encodeFunctionData11({
4311
+ const data = encodeFunctionData12({
3564
4312
  abi: POOL_ABI2,
3565
4313
  functionName: "borrow",
3566
4314
  args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
@@ -3575,7 +4323,7 @@ var AaveV2Adapter = class {
3575
4323
  }
3576
4324
  async buildRepay(params) {
3577
4325
  const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
3578
- const data = encodeFunctionData11({
4326
+ const data = encodeFunctionData12({
3579
4327
  abi: POOL_ABI2,
3580
4328
  functionName: "repay",
3581
4329
  args: [params.asset, params.amount, rateMode, params.on_behalf_of]
@@ -3590,7 +4338,7 @@ var AaveV2Adapter = class {
3590
4338
  };
3591
4339
  }
3592
4340
  async buildWithdraw(params) {
3593
- const data = encodeFunctionData11({
4341
+ const data = encodeFunctionData12({
3594
4342
  abi: POOL_ABI2,
3595
4343
  functionName: "withdraw",
3596
4344
  args: [params.asset, params.amount, params.to]
@@ -3678,7 +4426,7 @@ var AaveV2Adapter = class {
3678
4426
  };
3679
4427
  }
3680
4428
  };
3681
- var ORACLE_ABI2 = parseAbi12([
4429
+ var ORACLE_ABI2 = parseAbi13([
3682
4430
  "function getAssetPrice(address asset) external view returns (uint256)",
3683
4431
  "function getAssetsPrices(address[] calldata assets) external view returns (uint256[] memory)",
3684
4432
  "function BASE_CURRENCY_UNIT() external view returns (uint256)"
@@ -3755,7 +4503,7 @@ var AaveOracleAdapter = class {
3755
4503
  });
3756
4504
  }
3757
4505
  };
3758
- var CTOKEN_ABI = parseAbi13([
4506
+ var CTOKEN_ABI = parseAbi14([
3759
4507
  "function supplyRatePerBlock() external view returns (uint256)",
3760
4508
  "function borrowRatePerBlock() external view returns (uint256)",
3761
4509
  "function totalSupply() external view returns (uint256)",
@@ -3782,7 +4530,7 @@ var CompoundV2Adapter = class {
3782
4530
  return this.protocolName;
3783
4531
  }
3784
4532
  async buildSupply(params) {
3785
- const data = encodeFunctionData12({
4533
+ const data = encodeFunctionData13({
3786
4534
  abi: CTOKEN_ABI,
3787
4535
  functionName: "mint",
3788
4536
  args: [params.amount]
@@ -3796,7 +4544,7 @@ var CompoundV2Adapter = class {
3796
4544
  };
3797
4545
  }
3798
4546
  async buildBorrow(params) {
3799
- const data = encodeFunctionData12({
4547
+ const data = encodeFunctionData13({
3800
4548
  abi: CTOKEN_ABI,
3801
4549
  functionName: "borrow",
3802
4550
  args: [params.amount]
@@ -3810,7 +4558,7 @@ var CompoundV2Adapter = class {
3810
4558
  };
3811
4559
  }
3812
4560
  async buildRepay(params) {
3813
- const data = encodeFunctionData12({
4561
+ const data = encodeFunctionData13({
3814
4562
  abi: CTOKEN_ABI,
3815
4563
  functionName: "repayBorrow",
3816
4564
  args: [params.amount]
@@ -3824,7 +4572,7 @@ var CompoundV2Adapter = class {
3824
4572
  };
3825
4573
  }
3826
4574
  async buildWithdraw(params) {
3827
- const data = encodeFunctionData12({
4575
+ const data = encodeFunctionData13({
3828
4576
  abi: CTOKEN_ABI,
3829
4577
  functionName: "redeem",
3830
4578
  args: [params.amount]
@@ -3873,7 +4621,7 @@ var CompoundV2Adapter = class {
3873
4621
  );
3874
4622
  }
3875
4623
  };
3876
- var COMET_ABI = parseAbi14([
4624
+ var COMET_ABI = parseAbi15([
3877
4625
  "function getUtilization() external view returns (uint256)",
3878
4626
  "function getSupplyRate(uint256 utilization) external view returns (uint64)",
3879
4627
  "function getBorrowRate(uint256 utilization) external view returns (uint64)",
@@ -3899,7 +4647,7 @@ var CompoundV3Adapter = class {
3899
4647
  return this.protocolName;
3900
4648
  }
3901
4649
  async buildSupply(params) {
3902
- const data = encodeFunctionData13({
4650
+ const data = encodeFunctionData14({
3903
4651
  abi: COMET_ABI,
3904
4652
  functionName: "supply",
3905
4653
  args: [params.asset, params.amount]
@@ -3913,7 +4661,7 @@ var CompoundV3Adapter = class {
3913
4661
  };
3914
4662
  }
3915
4663
  async buildBorrow(params) {
3916
- const data = encodeFunctionData13({
4664
+ const data = encodeFunctionData14({
3917
4665
  abi: COMET_ABI,
3918
4666
  functionName: "withdraw",
3919
4667
  args: [params.asset, params.amount]
@@ -3927,7 +4675,7 @@ var CompoundV3Adapter = class {
3927
4675
  };
3928
4676
  }
3929
4677
  async buildRepay(params) {
3930
- const data = encodeFunctionData13({
4678
+ const data = encodeFunctionData14({
3931
4679
  abi: COMET_ABI,
3932
4680
  functionName: "supply",
3933
4681
  args: [params.asset, params.amount]
@@ -3941,7 +4689,7 @@ var CompoundV3Adapter = class {
3941
4689
  };
3942
4690
  }
3943
4691
  async buildWithdraw(params) {
3944
- const data = encodeFunctionData13({
4692
+ const data = encodeFunctionData14({
3945
4693
  abi: COMET_ABI,
3946
4694
  functionName: "withdraw",
3947
4695
  args: [params.asset, params.amount]
@@ -3995,7 +4743,7 @@ var CompoundV3Adapter = class {
3995
4743
  );
3996
4744
  }
3997
4745
  };
3998
- var EULER_VAULT_ABI = parseAbi15([
4746
+ var EULER_VAULT_ABI = parseAbi16([
3999
4747
  "function deposit(uint256 amount, address receiver) external returns (uint256)",
4000
4748
  "function withdraw(uint256 amount, address receiver, address owner) external returns (uint256)",
4001
4749
  "function borrow(uint256 amount, address receiver) external returns (uint256)",
@@ -4021,7 +4769,7 @@ var EulerV2Adapter = class {
4021
4769
  return this.protocolName;
4022
4770
  }
4023
4771
  async buildSupply(params) {
4024
- const data = encodeFunctionData14({
4772
+ const data = encodeFunctionData15({
4025
4773
  abi: EULER_VAULT_ABI,
4026
4774
  functionName: "deposit",
4027
4775
  args: [params.amount, params.on_behalf_of]
@@ -4035,7 +4783,7 @@ var EulerV2Adapter = class {
4035
4783
  };
4036
4784
  }
4037
4785
  async buildBorrow(params) {
4038
- const data = encodeFunctionData14({
4786
+ const data = encodeFunctionData15({
4039
4787
  abi: EULER_VAULT_ABI,
4040
4788
  functionName: "borrow",
4041
4789
  args: [params.amount, params.on_behalf_of]
@@ -4049,7 +4797,7 @@ var EulerV2Adapter = class {
4049
4797
  };
4050
4798
  }
4051
4799
  async buildRepay(params) {
4052
- const data = encodeFunctionData14({
4800
+ const data = encodeFunctionData15({
4053
4801
  abi: EULER_VAULT_ABI,
4054
4802
  functionName: "repay",
4055
4803
  args: [params.amount, params.on_behalf_of]
@@ -4063,7 +4811,7 @@ var EulerV2Adapter = class {
4063
4811
  };
4064
4812
  }
4065
4813
  async buildWithdraw(params) {
4066
- const data = encodeFunctionData14({
4814
+ const data = encodeFunctionData15({
4067
4815
  abi: EULER_VAULT_ABI,
4068
4816
  functionName: "withdraw",
4069
4817
  args: [params.amount, params.to, params.to]
@@ -4112,7 +4860,7 @@ var EulerV2Adapter = class {
4112
4860
  );
4113
4861
  }
4114
4862
  };
4115
- var MORPHO_ABI = parseAbi16([
4863
+ var MORPHO_ABI = parseAbi17([
4116
4864
  "function market(bytes32 id) external view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)",
4117
4865
  "function idToMarketParams(bytes32 id) external view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)",
4118
4866
  "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)",
@@ -4120,13 +4868,13 @@ var MORPHO_ABI = parseAbi16([
4120
4868
  "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)",
4121
4869
  "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)"
4122
4870
  ]);
4123
- var META_MORPHO_ABI = parseAbi16([
4871
+ var META_MORPHO_ABI = parseAbi17([
4124
4872
  "function supplyQueueLength() external view returns (uint256)",
4125
4873
  "function supplyQueue(uint256 index) external view returns (bytes32)",
4126
4874
  "function totalAssets() external view returns (uint256)",
4127
4875
  "function totalSupply() external view returns (uint256)"
4128
4876
  ]);
4129
- var IRM_ABI = parseAbi16([
4877
+ var IRM_ABI = parseAbi17([
4130
4878
  "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)"
4131
4879
  ]);
4132
4880
  var SECONDS_PER_YEAR3 = 365.25 * 24 * 3600;
@@ -4139,6 +4887,30 @@ function defaultMarketParams(loanToken = zeroAddress7) {
4139
4887
  lltv: 0n
4140
4888
  };
4141
4889
  }
4890
+ function decodeMarket(data) {
4891
+ if (!data) return null;
4892
+ try {
4893
+ return decodeFunctionResult4({
4894
+ abi: MORPHO_ABI,
4895
+ functionName: "market",
4896
+ data
4897
+ });
4898
+ } catch {
4899
+ return null;
4900
+ }
4901
+ }
4902
+ function decodeMarketParams(data) {
4903
+ if (!data) return null;
4904
+ try {
4905
+ return decodeFunctionResult4({
4906
+ abi: MORPHO_ABI,
4907
+ functionName: "idToMarketParams",
4908
+ data
4909
+ });
4910
+ } catch {
4911
+ return null;
4912
+ }
4913
+ }
4142
4914
  var MorphoBlueAdapter = class {
4143
4915
  protocolName;
4144
4916
  morpho;
@@ -4158,7 +4930,7 @@ var MorphoBlueAdapter = class {
4158
4930
  }
4159
4931
  async buildSupply(params) {
4160
4932
  const market = defaultMarketParams(params.asset);
4161
- const data = encodeFunctionData15({
4933
+ const data = encodeFunctionData16({
4162
4934
  abi: MORPHO_ABI,
4163
4935
  functionName: "supply",
4164
4936
  args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
@@ -4173,7 +4945,7 @@ var MorphoBlueAdapter = class {
4173
4945
  }
4174
4946
  async buildBorrow(params) {
4175
4947
  const market = defaultMarketParams(params.asset);
4176
- const data = encodeFunctionData15({
4948
+ const data = encodeFunctionData16({
4177
4949
  abi: MORPHO_ABI,
4178
4950
  functionName: "borrow",
4179
4951
  args: [market, params.amount, 0n, params.on_behalf_of, params.on_behalf_of]
@@ -4188,7 +4960,7 @@ var MorphoBlueAdapter = class {
4188
4960
  }
4189
4961
  async buildRepay(params) {
4190
4962
  const market = defaultMarketParams(params.asset);
4191
- const data = encodeFunctionData15({
4963
+ const data = encodeFunctionData16({
4192
4964
  abi: MORPHO_ABI,
4193
4965
  functionName: "repay",
4194
4966
  args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
@@ -4203,7 +4975,7 @@ var MorphoBlueAdapter = class {
4203
4975
  }
4204
4976
  async buildWithdraw(params) {
4205
4977
  const market = defaultMarketParams(params.asset);
4206
- const data = encodeFunctionData15({
4978
+ const data = encodeFunctionData16({
4207
4979
  abi: MORPHO_ABI,
4208
4980
  functionName: "withdraw",
4209
4981
  args: [market, params.amount, 0n, params.to, params.to]
@@ -4221,14 +4993,12 @@ var MorphoBlueAdapter = class {
4221
4993
  if (!this.defaultVault) {
4222
4994
  throw DefiError.contractError(`[${this.protocolName}] No MetaMorpho vault configured for rate query`);
4223
4995
  }
4224
- const client = createPublicClient13({ transport: http13(this.rpcUrl) });
4225
- const queueLen = await client.readContract({
4226
- address: this.defaultVault,
4227
- abi: META_MORPHO_ABI,
4228
- functionName: "supplyQueueLength"
4229
- }).catch((e) => {
4996
+ const [queueLenRaw] = await multicallRead(this.rpcUrl, [
4997
+ [this.defaultVault, encodeFunctionData16({ abi: META_MORPHO_ABI, functionName: "supplyQueueLength" })]
4998
+ ]).catch((e) => {
4230
4999
  throw DefiError.rpcError(`[${this.protocolName}] supplyQueueLength failed: ${e}`);
4231
5000
  });
5001
+ const queueLen = decodeU256(queueLenRaw ?? null);
4232
5002
  if (queueLen === 0n) {
4233
5003
  return {
4234
5004
  protocol: this.protocolName,
@@ -4240,45 +5010,40 @@ var MorphoBlueAdapter = class {
4240
5010
  total_borrow: 0n
4241
5011
  };
4242
5012
  }
4243
- const marketId = await client.readContract({
4244
- address: this.defaultVault,
4245
- abi: META_MORPHO_ABI,
4246
- functionName: "supplyQueue",
4247
- args: [0n]
4248
- }).catch((e) => {
5013
+ const [marketIdRaw] = await multicallRead(this.rpcUrl, [
5014
+ [this.defaultVault, encodeFunctionData16({ abi: META_MORPHO_ABI, functionName: "supplyQueue", args: [0n] })]
5015
+ ]).catch((e) => {
4249
5016
  throw DefiError.rpcError(`[${this.protocolName}] supplyQueue(0) failed: ${e}`);
4250
5017
  });
4251
- const mkt = await client.readContract({
4252
- address: this.morpho,
4253
- abi: MORPHO_ABI,
4254
- functionName: "market",
4255
- args: [marketId]
4256
- }).catch((e) => {
4257
- throw DefiError.rpcError(`[${this.protocolName}] market() failed: ${e}`);
5018
+ if (!marketIdRaw || marketIdRaw.length < 66) {
5019
+ throw DefiError.rpcError(`[${this.protocolName}] supplyQueue(0) returned no data`);
5020
+ }
5021
+ const marketId = marketIdRaw.slice(0, 66);
5022
+ const [marketRaw, paramsRaw] = await multicallRead(this.rpcUrl, [
5023
+ [this.morpho, encodeFunctionData16({ abi: MORPHO_ABI, functionName: "market", args: [marketId] })],
5024
+ [this.morpho, encodeFunctionData16({ abi: MORPHO_ABI, functionName: "idToMarketParams", args: [marketId] })]
5025
+ ]).catch((e) => {
5026
+ throw DefiError.rpcError(`[${this.protocolName}] market/idToMarketParams failed: ${e}`);
4258
5027
  });
4259
- const [totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee] = mkt;
5028
+ const mktDecoded = decodeMarket(marketRaw ?? null);
5029
+ if (!mktDecoded) throw DefiError.rpcError(`[${this.protocolName}] market() returned no data`);
5030
+ const [totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee] = mktDecoded;
5031
+ const paramsDecoded = decodeMarketParams(paramsRaw ?? null);
5032
+ if (!paramsDecoded) throw DefiError.rpcError(`[${this.protocolName}] idToMarketParams returned no data`);
5033
+ const [loanToken, collateralToken, oracle, irm, lltv] = paramsDecoded;
4260
5034
  const supplyF = Number(totalSupplyAssets);
4261
5035
  const borrowF = Number(totalBorrowAssets);
4262
5036
  const util = supplyF > 0 ? borrowF / supplyF : 0;
4263
- const params2 = await client.readContract({
4264
- address: this.morpho,
4265
- abi: MORPHO_ABI,
4266
- functionName: "idToMarketParams",
4267
- args: [marketId]
4268
- }).catch((e) => {
4269
- throw DefiError.rpcError(`[${this.protocolName}] idToMarketParams failed: ${e}`);
4270
- });
4271
- const [loanToken, collateralToken, oracle, irm, lltv] = params2;
4272
5037
  const irmMarketParams = { loanToken, collateralToken, oracle, irm, lltv };
4273
5038
  const irmMarket = { totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee };
4274
- const borrowRatePerSec = await client.readContract({
4275
- address: irm,
4276
- abi: IRM_ABI,
4277
- functionName: "borrowRateView",
4278
- args: [irmMarketParams, irmMarket]
4279
- }).catch((e) => {
4280
- throw DefiError.rpcError(`[${this.protocolName}] borrowRateView failed: ${e}`);
4281
- });
5039
+ const borrowRatePerSec = await (async () => {
5040
+ const [borrowRateRaw] = await multicallRead(this.rpcUrl, [
5041
+ [irm, encodeFunctionData16({ abi: IRM_ABI, functionName: "borrowRateView", args: [irmMarketParams, irmMarket] })]
5042
+ ]).catch((e) => {
5043
+ throw DefiError.rpcError(`[${this.protocolName}] borrowRateView failed: ${e}`);
5044
+ });
5045
+ return decodeU256(borrowRateRaw ?? null);
5046
+ })();
4282
5047
  const ratePerSec = Number(borrowRatePerSec) / 1e18;
4283
5048
  const borrowApy = ratePerSec * SECONDS_PER_YEAR3 * 100;
4284
5049
  const feePct = Number(fee) / 1e18;
@@ -4299,18 +5064,18 @@ var MorphoBlueAdapter = class {
4299
5064
  );
4300
5065
  }
4301
5066
  };
4302
- var BORROWER_OPS_ABI = parseAbi17([
5067
+ var BORROWER_OPS_ABI = parseAbi18([
4303
5068
  "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)",
4304
5069
  "function adjustTrove(uint256 _troveId, uint256 _collChange, bool _isCollIncrease, uint256 _debtChange, bool _isDebtIncrease, uint256 _upperHint, uint256 _lowerHint, uint256 _maxUpfrontFee) external",
4305
5070
  "function closeTrove(uint256 _troveId) external"
4306
5071
  ]);
4307
- var TROVE_MANAGER_ABI = parseAbi17([
5072
+ var TROVE_MANAGER_ABI = parseAbi18([
4308
5073
  "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)"
4309
5074
  ]);
4310
- var HINT_HELPERS_ABI = parseAbi17([
5075
+ var HINT_HELPERS_ABI = parseAbi18([
4311
5076
  "function getApproxHint(uint256 _collIndex, uint256 _interestRate, uint256 _numTrials, uint256 _inputRandomSeed) external view returns (uint256 hintId, uint256 diff, uint256 latestRandomSeed)"
4312
5077
  ]);
4313
- var SORTED_TROVES_ABI = parseAbi17([
5078
+ var SORTED_TROVES_ABI = parseAbi18([
4314
5079
  "function findInsertPosition(uint256 _annualInterestRate, uint256 _prevId, uint256 _nextId) external view returns (uint256 prevId, uint256 nextId)"
4315
5080
  ]);
4316
5081
  var FelixCdpAdapter = class {
@@ -4338,7 +5103,7 @@ var FelixCdpAdapter = class {
4338
5103
  if (!this.hintHelpers || !this.sortedTroves || !this.rpcUrl) {
4339
5104
  return [0n, 0n];
4340
5105
  }
4341
- const client = createPublicClient14({ transport: http14(this.rpcUrl) });
5106
+ const client = createPublicClient13({ transport: http13(this.rpcUrl) });
4342
5107
  const approxResult = await client.readContract({
4343
5108
  address: this.hintHelpers,
4344
5109
  abi: HINT_HELPERS_ABI,
@@ -4361,7 +5126,7 @@ var FelixCdpAdapter = class {
4361
5126
  const interestRate = 50000000000000000n;
4362
5127
  const [upperHint, lowerHint] = await this.getHints(interestRate);
4363
5128
  const hasHints = upperHint !== 0n || lowerHint !== 0n;
4364
- const data = encodeFunctionData16({
5129
+ const data = encodeFunctionData17({
4365
5130
  abi: BORROWER_OPS_ABI,
4366
5131
  functionName: "openTrove",
4367
5132
  args: [
@@ -4390,7 +5155,7 @@ var FelixCdpAdapter = class {
4390
5155
  async buildAdjust(params) {
4391
5156
  const collChange = params.collateral_delta ?? 0n;
4392
5157
  const debtChange = params.debt_delta ?? 0n;
4393
- const data = encodeFunctionData16({
5158
+ const data = encodeFunctionData17({
4394
5159
  abi: BORROWER_OPS_ABI,
4395
5160
  functionName: "adjustTrove",
4396
5161
  args: [
@@ -4413,7 +5178,7 @@ var FelixCdpAdapter = class {
4413
5178
  };
4414
5179
  }
4415
5180
  async buildClose(params) {
4416
- const data = encodeFunctionData16({
5181
+ const data = encodeFunctionData17({
4417
5182
  abi: BORROWER_OPS_ABI,
4418
5183
  functionName: "closeTrove",
4419
5184
  args: [params.cdp_id]
@@ -4429,7 +5194,7 @@ var FelixCdpAdapter = class {
4429
5194
  async getCdpInfo(cdpId) {
4430
5195
  if (!this.rpcUrl) throw DefiError.rpcError(`[${this.protocolName}] getCdpInfo requires RPC \u2014 set HYPEREVM_RPC_URL`);
4431
5196
  if (!this.troveManager) throw DefiError.contractError(`[${this.protocolName}] trove_manager contract not configured`);
4432
- const client = createPublicClient14({ transport: http14(this.rpcUrl) });
5197
+ const client = createPublicClient13({ transport: http13(this.rpcUrl) });
4433
5198
  const data = await client.readContract({
4434
5199
  address: this.troveManager,
4435
5200
  abi: TROVE_MANAGER_ABI,
@@ -4462,7 +5227,7 @@ var FelixCdpAdapter = class {
4462
5227
  };
4463
5228
  }
4464
5229
  };
4465
- var PRICE_FEED_ABI = parseAbi18([
5230
+ var PRICE_FEED_ABI = parseAbi19([
4466
5231
  "function fetchPrice() external view returns (uint256 price, bool isNewOracleFailureDetected)",
4467
5232
  "function lastGoodPrice() external view returns (uint256)"
4468
5233
  ]);
@@ -4488,7 +5253,7 @@ var FelixOracleAdapter = class {
4488
5253
  if (asset !== this.asset && this.asset !== "0x0000000000000000000000000000000000000000") {
4489
5254
  throw DefiError.unsupported(`[${this.protocolName}] Felix PriceFeed only supports asset ${this.asset}`);
4490
5255
  }
4491
- const client = createPublicClient15({ transport: http15(this.rpcUrl) });
5256
+ const client = createPublicClient14({ transport: http14(this.rpcUrl) });
4492
5257
  let priceVal;
4493
5258
  try {
4494
5259
  const result = await client.readContract({
@@ -4527,7 +5292,7 @@ var FelixOracleAdapter = class {
4527
5292
  return results;
4528
5293
  }
4529
5294
  };
4530
- var ERC4626_ABI = parseAbi19([
5295
+ var ERC4626_ABI = parseAbi20([
4531
5296
  "function asset() external view returns (address)",
4532
5297
  "function totalAssets() external view returns (uint256)",
4533
5298
  "function totalSupply() external view returns (uint256)",
@@ -4551,7 +5316,7 @@ var ERC4626VaultAdapter = class {
4551
5316
  return this.protocolName;
4552
5317
  }
4553
5318
  async buildDeposit(assets, receiver) {
4554
- const data = encodeFunctionData17({
5319
+ const data = encodeFunctionData18({
4555
5320
  abi: ERC4626_ABI,
4556
5321
  functionName: "deposit",
4557
5322
  args: [assets, receiver]
@@ -4565,7 +5330,7 @@ var ERC4626VaultAdapter = class {
4565
5330
  };
4566
5331
  }
4567
5332
  async buildWithdraw(assets, receiver, owner) {
4568
- const data = encodeFunctionData17({
5333
+ const data = encodeFunctionData18({
4569
5334
  abi: ERC4626_ABI,
4570
5335
  functionName: "withdraw",
4571
5336
  args: [assets, receiver, owner]
@@ -4580,7 +5345,7 @@ var ERC4626VaultAdapter = class {
4580
5345
  }
4581
5346
  async totalAssets() {
4582
5347
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4583
- const client = createPublicClient16({ transport: http16(this.rpcUrl) });
5348
+ const client = createPublicClient15({ transport: http15(this.rpcUrl) });
4584
5349
  return client.readContract({
4585
5350
  address: this.vaultAddress,
4586
5351
  abi: ERC4626_ABI,
@@ -4591,7 +5356,7 @@ var ERC4626VaultAdapter = class {
4591
5356
  }
4592
5357
  async convertToShares(assets) {
4593
5358
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4594
- const client = createPublicClient16({ transport: http16(this.rpcUrl) });
5359
+ const client = createPublicClient15({ transport: http15(this.rpcUrl) });
4595
5360
  return client.readContract({
4596
5361
  address: this.vaultAddress,
4597
5362
  abi: ERC4626_ABI,
@@ -4603,7 +5368,7 @@ var ERC4626VaultAdapter = class {
4603
5368
  }
4604
5369
  async convertToAssets(shares) {
4605
5370
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4606
- const client = createPublicClient16({ transport: http16(this.rpcUrl) });
5371
+ const client = createPublicClient15({ transport: http15(this.rpcUrl) });
4607
5372
  return client.readContract({
4608
5373
  address: this.vaultAddress,
4609
5374
  abi: ERC4626_ABI,
@@ -4615,7 +5380,7 @@ var ERC4626VaultAdapter = class {
4615
5380
  }
4616
5381
  async getVaultInfo() {
4617
5382
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4618
- const client = createPublicClient16({ transport: http16(this.rpcUrl) });
5383
+ const client = createPublicClient15({ transport: http15(this.rpcUrl) });
4619
5384
  const [totalAssets, totalSupply, asset] = await Promise.all([
4620
5385
  client.readContract({ address: this.vaultAddress, abi: ERC4626_ABI, functionName: "totalAssets" }).catch((e) => {
4621
5386
  throw DefiError.rpcError(`[${this.protocolName}] totalAssets failed: ${e}`);
@@ -4636,7 +5401,7 @@ var ERC4626VaultAdapter = class {
4636
5401
  };
4637
5402
  }
4638
5403
  };
4639
- var GENERIC_LST_ABI = parseAbi20([
5404
+ var GENERIC_LST_ABI = parseAbi21([
4640
5405
  "function stake() external payable returns (uint256)",
4641
5406
  "function unstake(uint256 amount) external returns (uint256)"
4642
5407
  ]);
@@ -4653,7 +5418,7 @@ var GenericLstAdapter = class {
4653
5418
  return this.protocolName;
4654
5419
  }
4655
5420
  async buildStake(params) {
4656
- const data = encodeFunctionData18({ abi: GENERIC_LST_ABI, functionName: "stake" });
5421
+ const data = encodeFunctionData19({ abi: GENERIC_LST_ABI, functionName: "stake" });
4657
5422
  return {
4658
5423
  description: `[${this.protocolName}] Stake ${params.amount} HYPE`,
4659
5424
  to: this.staking,
@@ -4663,7 +5428,7 @@ var GenericLstAdapter = class {
4663
5428
  };
4664
5429
  }
4665
5430
  async buildUnstake(params) {
4666
- const data = encodeFunctionData18({
5431
+ const data = encodeFunctionData19({
4667
5432
  abi: GENERIC_LST_ABI,
4668
5433
  functionName: "unstake",
4669
5434
  args: [params.amount]
@@ -4680,11 +5445,11 @@ var GenericLstAdapter = class {
4680
5445
  throw DefiError.unsupported(`[${this.protocolName}] getInfo requires RPC`);
4681
5446
  }
4682
5447
  };
4683
- var STHYPE_ABI = parseAbi21([
5448
+ var STHYPE_ABI = parseAbi222([
4684
5449
  "function submit(address referral) external payable returns (uint256)",
4685
5450
  "function requestWithdrawals(uint256[] amounts, address owner) external returns (uint256[] requestIds)"
4686
5451
  ]);
4687
- var ERC20_ABI3 = parseAbi21([
5452
+ var ERC20_ABI3 = parseAbi222([
4688
5453
  "function totalSupply() external view returns (uint256)"
4689
5454
  ]);
4690
5455
  var StHypeAdapter = class {
@@ -4704,7 +5469,7 @@ var StHypeAdapter = class {
4704
5469
  return this.protocolName;
4705
5470
  }
4706
5471
  async buildStake(params) {
4707
- const data = encodeFunctionData19({
5472
+ const data = encodeFunctionData20({
4708
5473
  abi: STHYPE_ABI,
4709
5474
  functionName: "submit",
4710
5475
  args: [zeroAddress9]
@@ -4718,7 +5483,7 @@ var StHypeAdapter = class {
4718
5483
  };
4719
5484
  }
4720
5485
  async buildUnstake(params) {
4721
- const data = encodeFunctionData19({
5486
+ const data = encodeFunctionData20({
4722
5487
  abi: STHYPE_ABI,
4723
5488
  functionName: "requestWithdrawals",
4724
5489
  args: [[params.amount], params.recipient]
@@ -4733,7 +5498,7 @@ var StHypeAdapter = class {
4733
5498
  }
4734
5499
  async getInfo() {
4735
5500
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4736
- const client = createPublicClient17({ transport: http17(this.rpcUrl) });
5501
+ const client = createPublicClient16({ transport: http16(this.rpcUrl) });
4737
5502
  const tokenAddr = this.sthypeToken ?? this.staking;
4738
5503
  const totalSupply = await client.readContract({
4739
5504
  address: tokenAddr,
@@ -4751,12 +5516,12 @@ var StHypeAdapter = class {
4751
5516
  };
4752
5517
  }
4753
5518
  };
4754
- var KINETIQ_ABI = parseAbi222([
5519
+ var KINETIQ_ABI = parseAbi23([
4755
5520
  "function stake() external payable returns (uint256)",
4756
5521
  "function requestUnstake(uint256 amount) external returns (uint256)",
4757
5522
  "function totalStaked() external view returns (uint256)"
4758
5523
  ]);
4759
- var ORACLE_ABI3 = parseAbi222([
5524
+ var ORACLE_ABI3 = parseAbi23([
4760
5525
  "function getAssetPrice(address asset) external view returns (uint256)"
4761
5526
  ]);
4762
5527
  var WHYPE = "0x5555555555555555555555555555555555555555";
@@ -4778,7 +5543,7 @@ var KinetiqAdapter = class {
4778
5543
  return this.protocolName;
4779
5544
  }
4780
5545
  async buildStake(params) {
4781
- const data = encodeFunctionData20({ abi: KINETIQ_ABI, functionName: "stake" });
5546
+ const data = encodeFunctionData21({ abi: KINETIQ_ABI, functionName: "stake" });
4782
5547
  return {
4783
5548
  description: `[${this.protocolName}] Stake ${params.amount} HYPE for kHYPE`,
4784
5549
  to: this.staking,
@@ -4788,7 +5553,7 @@ var KinetiqAdapter = class {
4788
5553
  };
4789
5554
  }
4790
5555
  async buildUnstake(params) {
4791
- const data = encodeFunctionData20({
5556
+ const data = encodeFunctionData21({
4792
5557
  abi: KINETIQ_ABI,
4793
5558
  functionName: "requestUnstake",
4794
5559
  args: [params.amount]
@@ -4803,7 +5568,7 @@ var KinetiqAdapter = class {
4803
5568
  }
4804
5569
  async getInfo() {
4805
5570
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4806
- const client = createPublicClient18({ transport: http18(this.rpcUrl) });
5571
+ const client = createPublicClient17({ transport: http17(this.rpcUrl) });
4807
5572
  const totalStaked = await client.readContract({
4808
5573
  address: this.staking,
4809
5574
  abi: KINETIQ_ABI,
@@ -4825,15 +5590,15 @@ var KinetiqAdapter = class {
4825
5590
  };
4826
5591
  }
4827
5592
  };
4828
- var HLP_ABI = parseAbi23([
5593
+ var HLP_ABI = parseAbi24([
4829
5594
  "function deposit(uint256 amount) external returns (uint256)",
4830
5595
  "function withdraw(uint256 shares) external returns (uint256)"
4831
5596
  ]);
4832
- var RYSK_ABI = parseAbi24([
5597
+ var RYSK_ABI = parseAbi25([
4833
5598
  "function openOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 premium)",
4834
5599
  "function closeOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 payout)"
4835
5600
  ]);
4836
- var ERC721_ABI = parseAbi25([
5601
+ var ERC721_ABI = parseAbi26([
4837
5602
  "function name() returns (string)",
4838
5603
  "function symbol() returns (string)",
4839
5604
  "function totalSupply() returns (uint256)",
@@ -4853,7 +5618,7 @@ var ERC721Adapter = class {
4853
5618
  }
4854
5619
  async getCollectionInfo(collection) {
4855
5620
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4856
- const client = createPublicClient19({ transport: http19(this.rpcUrl) });
5621
+ const client = createPublicClient18({ transport: http18(this.rpcUrl) });
4857
5622
  const [collectionName, symbol, totalSupply] = await Promise.all([
4858
5623
  client.readContract({ address: collection, abi: ERC721_ABI, functionName: "name" }).catch((e) => {
4859
5624
  throw DefiError.rpcError(`[${this.protocolName}] name failed: ${e}`);
@@ -4872,7 +5637,7 @@ var ERC721Adapter = class {
4872
5637
  }
4873
5638
  async getTokenInfo(collection, tokenId) {
4874
5639
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4875
- const client = createPublicClient19({ transport: http19(this.rpcUrl) });
5640
+ const client = createPublicClient18({ transport: http18(this.rpcUrl) });
4876
5641
  const [owner, tokenUri] = await Promise.all([
4877
5642
  client.readContract({ address: collection, abi: ERC721_ABI, functionName: "ownerOf", args: [tokenId] }).catch((e) => {
4878
5643
  throw DefiError.rpcError(`[${this.protocolName}] ownerOf failed: ${e}`);
@@ -4888,7 +5653,7 @@ var ERC721Adapter = class {
4888
5653
  }
4889
5654
  async getBalance(owner, collection) {
4890
5655
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4891
- const client = createPublicClient19({ transport: http19(this.rpcUrl) });
5656
+ const client = createPublicClient18({ transport: http18(this.rpcUrl) });
4892
5657
  return client.readContract({ address: collection, abi: ERC721_ABI, functionName: "balanceOf", args: [owner] }).catch((e) => {
4893
5658
  throw DefiError.rpcError(`[${this.protocolName}] balanceOf failed: ${e}`);
4894
5659
  });
@@ -5009,6 +5774,9 @@ function createOracleFromCdp(entry, _asset, rpcUrl) {
5009
5774
  throw DefiError.unsupported(`Oracle not available for CDP interface '${entry.interface}'`);
5010
5775
  }
5011
5776
  }
5777
+ function createMerchantMoeLB(entry, rpcUrl) {
5778
+ return new MerchantMoeLBAdapter(entry, rpcUrl);
5779
+ }
5012
5780
  var DexSpotPrice = class {
5013
5781
  /**
5014
5782
  * Get the spot price for `token` denominated in `quoteToken` (e.g. USDC).
@@ -6016,20 +6784,20 @@ function registerYield(parent, getOpts, makeExecutor2) {
6016
6784
  }
6017
6785
 
6018
6786
  // src/commands/portfolio.ts
6019
- import { encodeFunctionData as encodeFunctionData24, parseAbi as parseAbi27 } from "viem";
6787
+ import { encodeFunctionData as encodeFunctionData25, parseAbi as parseAbi28 } from "viem";
6020
6788
 
6021
6789
  // src/portfolio-tracker.ts
6022
6790
  import { mkdirSync, writeFileSync, readdirSync as readdirSync2, readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
6023
6791
  import { homedir } from "os";
6024
6792
  import { resolve as resolve2 } from "path";
6025
- import { encodeFunctionData as encodeFunctionData23, parseAbi as parseAbi26 } from "viem";
6026
- var ERC20_ABI4 = parseAbi26([
6793
+ import { encodeFunctionData as encodeFunctionData24, parseAbi as parseAbi27 } from "viem";
6794
+ var ERC20_ABI4 = parseAbi27([
6027
6795
  "function balanceOf(address owner) external view returns (uint256)"
6028
6796
  ]);
6029
- var ORACLE_ABI4 = parseAbi26([
6797
+ var ORACLE_ABI4 = parseAbi27([
6030
6798
  "function getAssetPrice(address asset) external view returns (uint256)"
6031
6799
  ]);
6032
- var POOL_ABI3 = parseAbi26([
6800
+ var POOL_ABI3 = parseAbi27([
6033
6801
  "function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
6034
6802
  ]);
6035
6803
  function decodeU256Word(data, wordOffset = 0) {
@@ -6058,7 +6826,7 @@ async function takeSnapshot(chainName, wallet, registry) {
6058
6826
  tokenEntries.push({ symbol: t.symbol, address: entry.address, decimals: entry.decimals });
6059
6827
  calls.push([
6060
6828
  entry.address,
6061
- encodeFunctionData23({ abi: ERC20_ABI4, functionName: "balanceOf", args: [user] })
6829
+ encodeFunctionData24({ abi: ERC20_ABI4, functionName: "balanceOf", args: [user] })
6062
6830
  ]);
6063
6831
  callLabels.push(`balance:${t.symbol}`);
6064
6832
  }
@@ -6066,7 +6834,7 @@ async function takeSnapshot(chainName, wallet, registry) {
6066
6834
  for (const p of lendingProtocols) {
6067
6835
  calls.push([
6068
6836
  p.contracts["pool"],
6069
- encodeFunctionData23({ abi: POOL_ABI3, functionName: "getUserAccountData", args: [user] })
6837
+ encodeFunctionData24({ abi: POOL_ABI3, functionName: "getUserAccountData", args: [user] })
6070
6838
  ]);
6071
6839
  callLabels.push(`lending:${p.name}`);
6072
6840
  }
@@ -6076,7 +6844,7 @@ async function takeSnapshot(chainName, wallet, registry) {
6076
6844
  if (oracleAddr) {
6077
6845
  calls.push([
6078
6846
  oracleAddr,
6079
- encodeFunctionData23({ abi: ORACLE_ABI4, functionName: "getAssetPrice", args: [wrappedNative] })
6847
+ encodeFunctionData24({ abi: ORACLE_ABI4, functionName: "getAssetPrice", args: [wrappedNative] })
6080
6848
  ]);
6081
6849
  callLabels.push("price:native");
6082
6850
  }
@@ -6214,16 +6982,16 @@ function calculatePnL(current, previous) {
6214
6982
  }
6215
6983
 
6216
6984
  // src/commands/portfolio.ts
6217
- var ERC20_ABI5 = parseAbi27([
6985
+ var ERC20_ABI5 = parseAbi28([
6218
6986
  "function balanceOf(address owner) external view returns (uint256)"
6219
6987
  ]);
6220
- var POOL_ABI4 = parseAbi27([
6988
+ var POOL_ABI4 = parseAbi28([
6221
6989
  "function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
6222
6990
  ]);
6223
- var ORACLE_ABI5 = parseAbi27([
6991
+ var ORACLE_ABI5 = parseAbi28([
6224
6992
  "function getAssetPrice(address asset) external view returns (uint256)"
6225
6993
  ]);
6226
- function decodeU256(data, wordOffset = 0) {
6994
+ function decodeU2562(data, wordOffset = 0) {
6227
6995
  if (!data || data.length < 2 + (wordOffset + 1) * 64) return 0n;
6228
6996
  const hex = data.slice(2 + wordOffset * 64, 2 + wordOffset * 64 + 64);
6229
6997
  return BigInt("0x" + hex);
@@ -6260,7 +7028,7 @@ function registerPortfolio(parent, getOpts) {
6260
7028
  if (entry.address === "0x0000000000000000000000000000000000000000") continue;
6261
7029
  calls.push([
6262
7030
  entry.address,
6263
- encodeFunctionData24({ abi: ERC20_ABI5, functionName: "balanceOf", args: [user] })
7031
+ encodeFunctionData25({ abi: ERC20_ABI5, functionName: "balanceOf", args: [user] })
6264
7032
  ]);
6265
7033
  callLabels.push(`balance:${symbol}`);
6266
7034
  }
@@ -6268,7 +7036,7 @@ function registerPortfolio(parent, getOpts) {
6268
7036
  for (const p of lendingProtocols) {
6269
7037
  calls.push([
6270
7038
  p.contracts["pool"],
6271
- encodeFunctionData24({ abi: POOL_ABI4, functionName: "getUserAccountData", args: [user] })
7039
+ encodeFunctionData25({ abi: POOL_ABI4, functionName: "getUserAccountData", args: [user] })
6272
7040
  ]);
6273
7041
  callLabels.push(`lending:${p.name}`);
6274
7042
  }
@@ -6278,7 +7046,7 @@ function registerPortfolio(parent, getOpts) {
6278
7046
  if (oracleAddr) {
6279
7047
  calls.push([
6280
7048
  oracleAddr,
6281
- encodeFunctionData24({ abi: ORACLE_ABI5, functionName: "getAssetPrice", args: [wrappedNative] })
7049
+ encodeFunctionData25({ abi: ORACLE_ABI5, functionName: "getAssetPrice", args: [wrappedNative] })
6282
7050
  ]);
6283
7051
  callLabels.push("price:native");
6284
7052
  }
@@ -6303,7 +7071,7 @@ function registerPortfolio(parent, getOpts) {
6303
7071
  let nativePriceUsd = 0;
6304
7072
  if (oracleAddr) {
6305
7073
  const priceData = results[results.length - 1] ?? null;
6306
- nativePriceUsd = Number(decodeU256(priceData)) / 1e8;
7074
+ nativePriceUsd = Number(decodeU2562(priceData)) / 1e8;
6307
7075
  }
6308
7076
  let totalValueUsd = 0;
6309
7077
  let idx = 0;
@@ -6317,7 +7085,7 @@ function registerPortfolio(parent, getOpts) {
6317
7085
  }
6318
7086
  if (entry.address === "0x0000000000000000000000000000000000000000") continue;
6319
7087
  if (idx >= results.length) break;
6320
- const balance = decodeU256(results[idx] ?? null);
7088
+ const balance = decodeU2562(results[idx] ?? null);
6321
7089
  if (balance > 0n) {
6322
7090
  const decimals = entry.decimals;
6323
7091
  const balF64 = Number(balance) / 10 ** decimals;
@@ -6337,9 +7105,9 @@ function registerPortfolio(parent, getOpts) {
6337
7105
  if (idx >= results.length) break;
6338
7106
  const data = results[idx] ?? null;
6339
7107
  if (data && data.length >= 2 + 192 * 2) {
6340
- const collateral = Number(decodeU256(data, 0)) / 1e8;
6341
- const debt = Number(decodeU256(data, 1)) / 1e8;
6342
- const hfRaw = decodeU256(data, 5);
7108
+ const collateral = Number(decodeU2562(data, 0)) / 1e8;
7109
+ const debt = Number(decodeU2562(data, 1)) / 1e8;
7110
+ const hfRaw = decodeU2562(data, 5);
6343
7111
  let hf = null;
6344
7112
  if (hfRaw <= BigInt("0xffffffffffffffffffffffffffffffff")) {
6345
7113
  const v = Number(hfRaw) / 1e18;
@@ -6640,14 +7408,14 @@ function registerAlert(parent, getOpts) {
6640
7408
  }
6641
7409
 
6642
7410
  // src/commands/scan.ts
6643
- import { encodeFunctionData as encodeFunctionData25, parseAbi as parseAbi28 } from "viem";
6644
- var AAVE_ORACLE_ABI = parseAbi28([
7411
+ import { encodeFunctionData as encodeFunctionData26, parseAbi as parseAbi29 } from "viem";
7412
+ var AAVE_ORACLE_ABI = parseAbi29([
6645
7413
  "function getAssetPrice(address asset) external view returns (uint256)"
6646
7414
  ]);
6647
- var UNIV2_ROUTER_ABI = parseAbi28([
7415
+ var UNIV2_ROUTER_ABI = parseAbi29([
6648
7416
  "function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory)"
6649
7417
  ]);
6650
- var VTOKEN_ABI = parseAbi28([
7418
+ var VTOKEN_ABI = parseAbi29([
6651
7419
  "function exchangeRateStored() external view returns (uint256)"
6652
7420
  ]);
6653
7421
  var STABLECOINS = /* @__PURE__ */ new Set(["USDC", "USDT", "DAI", "USDT0"]);
@@ -6757,7 +7525,7 @@ function registerScan(parent, getOpts) {
6757
7525
  callTypes.push({ kind: "oracle", oracle: oracle.name, token: token.symbol, oracleDecimals: oracle.decimals });
6758
7526
  calls.push([
6759
7527
  oracle.addr,
6760
- encodeFunctionData25({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })
7528
+ encodeFunctionData26({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })
6761
7529
  ]);
6762
7530
  }
6763
7531
  }
@@ -6768,7 +7536,7 @@ function registerScan(parent, getOpts) {
6768
7536
  callTypes.push({ kind: "dex", token: token.symbol, outDecimals: quoteStable.decimals });
6769
7537
  calls.push([
6770
7538
  dexRouter,
6771
- encodeFunctionData25({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [amountIn, path] })
7539
+ encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [amountIn, path] })
6772
7540
  ]);
6773
7541
  }
6774
7542
  }
@@ -6777,7 +7545,7 @@ function registerScan(parent, getOpts) {
6777
7545
  callTypes.push({ kind: "stable", from: "USDC", to: "USDT", outDecimals: usdt.decimals });
6778
7546
  calls.push([
6779
7547
  dexRouter,
6780
- encodeFunctionData25({
7548
+ encodeFunctionData26({
6781
7549
  abi: UNIV2_ROUTER_ABI,
6782
7550
  functionName: "getAmountsOut",
6783
7551
  args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]]
@@ -6786,7 +7554,7 @@ function registerScan(parent, getOpts) {
6786
7554
  callTypes.push({ kind: "stable", from: "USDT", to: "USDC", outDecimals: usdc.decimals });
6787
7555
  calls.push([
6788
7556
  dexRouter,
6789
- encodeFunctionData25({
7557
+ encodeFunctionData26({
6790
7558
  abi: UNIV2_ROUTER_ABI,
6791
7559
  functionName: "getAmountsOut",
6792
7560
  args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]]
@@ -6797,7 +7565,7 @@ function registerScan(parent, getOpts) {
6797
7565
  for (const fork of compoundForks) {
6798
7566
  for (const { key, addr } of fork.vtokens) {
6799
7567
  callTypes.push({ kind: "exchangeRate", protocol: fork.name, vtoken: key });
6800
- calls.push([addr, encodeFunctionData25({ abi: VTOKEN_ABI, functionName: "exchangeRateStored", args: [] })]);
7568
+ calls.push([addr, encodeFunctionData26({ abi: VTOKEN_ABI, functionName: "exchangeRateStored", args: [] })]);
6801
7569
  }
6802
7570
  }
6803
7571
  }
@@ -7015,22 +7783,22 @@ async function runAllChains(registry, patterns, oracleThreshold, stableThreshold
7015
7783
  for (const oracle of oracles) {
7016
7784
  for (const token of scanTokens) {
7017
7785
  cts.push({ kind: "oracle", oracle: oracle.name, token: token.symbol, dec: oracle.decimals });
7018
- calls.push([oracle.addr, encodeFunctionData25({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })]);
7786
+ calls.push([oracle.addr, encodeFunctionData26({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })]);
7019
7787
  }
7020
7788
  }
7021
7789
  if (dexRouter) {
7022
7790
  for (const token of scanTokens) {
7023
7791
  const path = wrappedNative && token.address.toLowerCase() === wrappedNative.toLowerCase() ? [token.address, quoteStable.address] : wrappedNative ? [token.address, wrappedNative, quoteStable.address] : [token.address, quoteStable.address];
7024
7792
  cts.push({ kind: "dex", token: token.symbol, dec: quoteStable.decimals });
7025
- calls.push([dexRouter, encodeFunctionData25({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(token.decimals), path] })]);
7793
+ calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(token.decimals), path] })]);
7026
7794
  }
7027
7795
  }
7028
7796
  }
7029
7797
  if (doStable && usdc && usdt && dexRouter) {
7030
7798
  cts.push({ kind: "stable", from: "USDC", to: "USDT", dec: usdt.decimals });
7031
- calls.push([dexRouter, encodeFunctionData25({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]] })]);
7799
+ calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]] })]);
7032
7800
  cts.push({ kind: "stable", from: "USDT", to: "USDC", dec: usdc.decimals });
7033
- calls.push([dexRouter, encodeFunctionData25({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]] })]);
7801
+ calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]] })]);
7034
7802
  }
7035
7803
  if (calls.length === 0) return null;
7036
7804
  const ct0 = Date.now();
@@ -7158,14 +7926,14 @@ function registerArb(parent, getOpts, makeExecutor2) {
7158
7926
  }
7159
7927
 
7160
7928
  // src/commands/positions.ts
7161
- import { encodeFunctionData as encodeFunctionData26, parseAbi as parseAbi29 } from "viem";
7162
- var ERC20_ABI6 = parseAbi29([
7929
+ import { encodeFunctionData as encodeFunctionData27, parseAbi as parseAbi30 } from "viem";
7930
+ var ERC20_ABI6 = parseAbi30([
7163
7931
  "function balanceOf(address owner) external view returns (uint256)"
7164
7932
  ]);
7165
- var POOL_ABI5 = parseAbi29([
7933
+ var POOL_ABI5 = parseAbi30([
7166
7934
  "function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
7167
7935
  ]);
7168
- var ORACLE_ABI6 = parseAbi29([
7936
+ var ORACLE_ABI6 = parseAbi30([
7169
7937
  "function getAssetPrice(address asset) external view returns (uint256)"
7170
7938
  ]);
7171
7939
  function round22(x) {
@@ -7181,7 +7949,7 @@ function estimateTokenValue(symbol, balance, nativePrice) {
7181
7949
  if (["WETH", "ETH", "METH", "CBETH", "WSTETH"].includes(s)) return balance * 2350;
7182
7950
  return balance * nativePrice;
7183
7951
  }
7184
- function decodeU2562(data, offset = 0) {
7952
+ function decodeU2563(data, offset = 0) {
7185
7953
  if (!data || data.length < 2 + (offset + 32) * 2) return 0n;
7186
7954
  const hex = data.slice(2 + offset * 64, 2 + offset * 64 + 64);
7187
7955
  return BigInt("0x" + hex);
@@ -7194,7 +7962,7 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
7194
7962
  callTypes.push({ kind: "token", symbol: token.symbol, decimals: token.decimals });
7195
7963
  calls.push([
7196
7964
  token.address,
7197
- encodeFunctionData26({ abi: ERC20_ABI6, functionName: "balanceOf", args: [user] })
7965
+ encodeFunctionData27({ abi: ERC20_ABI6, functionName: "balanceOf", args: [user] })
7198
7966
  ]);
7199
7967
  }
7200
7968
  }
@@ -7202,14 +7970,14 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
7202
7970
  callTypes.push({ kind: "lending", protocol: name, iface });
7203
7971
  calls.push([
7204
7972
  pool,
7205
- encodeFunctionData26({ abi: POOL_ABI5, functionName: "getUserAccountData", args: [user] })
7973
+ encodeFunctionData27({ abi: POOL_ABI5, functionName: "getUserAccountData", args: [user] })
7206
7974
  ]);
7207
7975
  }
7208
7976
  if (oracleAddr) {
7209
7977
  callTypes.push({ kind: "native_price" });
7210
7978
  calls.push([
7211
7979
  oracleAddr,
7212
- encodeFunctionData26({ abi: ORACLE_ABI6, functionName: "getAssetPrice", args: [wrappedNative] })
7980
+ encodeFunctionData27({ abi: ORACLE_ABI6, functionName: "getAssetPrice", args: [wrappedNative] })
7213
7981
  ]);
7214
7982
  }
7215
7983
  if (calls.length === 0) return null;
@@ -7219,7 +7987,7 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
7219
7987
  } catch {
7220
7988
  return null;
7221
7989
  }
7222
- const nativePrice = oracleAddr ? Number(decodeU2562(results[results.length - 1])) / 1e8 : 0;
7990
+ const nativePrice = oracleAddr ? Number(decodeU2563(results[results.length - 1])) / 1e8 : 0;
7223
7991
  const tokenBalances = [];
7224
7992
  const lendingPositions = [];
7225
7993
  let chainValue = 0;
@@ -7229,7 +7997,7 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
7229
7997
  const ct = callTypes[i];
7230
7998
  const data = results[i] ?? null;
7231
7999
  if (ct.kind === "token") {
7232
- const balance = decodeU2562(data);
8000
+ const balance = decodeU2563(data);
7233
8001
  if (balance > 0n) {
7234
8002
  const balF64 = Number(balance) / 10 ** ct.decimals;
7235
8003
  const valueUsd = estimateTokenValue(ct.symbol, balF64, nativePrice);
@@ -7246,9 +8014,9 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
7246
8014
  if (data && data.length >= 2 + 192 * 2) {
7247
8015
  const priceDecimals = ct.iface === "aave_v2" ? 18 : 8;
7248
8016
  const divisor = 10 ** priceDecimals;
7249
- const collateral = Number(decodeU2562(data, 0)) / divisor;
7250
- const debt = Number(decodeU2562(data, 1)) / divisor;
7251
- const hfRaw = decodeU2562(data, 5);
8017
+ const collateral = Number(decodeU2563(data, 0)) / divisor;
8018
+ const debt = Number(decodeU2563(data, 1)) / divisor;
8019
+ const hfRaw = decodeU2563(data, 5);
7252
8020
  let hf = null;
7253
8021
  if (hfRaw <= BigInt("0xffffffffffffffffffffffffffffffff")) {
7254
8022
  const v = Number(hfRaw) / 1e18;
@@ -7502,14 +8270,14 @@ function registerPrice(parent, getOpts) {
7502
8270
  }
7503
8271
 
7504
8272
  // src/commands/wallet.ts
7505
- import { createPublicClient as createPublicClient20, http as http20, formatEther } from "viem";
8273
+ import { createPublicClient as createPublicClient19, http as http19, formatEther } from "viem";
7506
8274
  function registerWallet(parent, getOpts) {
7507
8275
  const wallet = parent.command("wallet").description("Wallet management");
7508
8276
  wallet.command("balance").description("Show native token balance").requiredOption("--address <address>", "Wallet address to query").action(async (opts) => {
7509
8277
  const chainName = parent.opts().chain ?? "hyperevm";
7510
8278
  const registry = Registry.loadEmbedded();
7511
8279
  const chain = registry.getChain(chainName);
7512
- const client = createPublicClient20({ transport: http20(chain.effectiveRpcUrl()) });
8280
+ const client = createPublicClient19({ transport: http19(chain.effectiveRpcUrl()) });
7513
8281
  const balance = await client.getBalance({ address: opts.address });
7514
8282
  printOutput({
7515
8283
  chain: chain.name,
@@ -7526,14 +8294,14 @@ function registerWallet(parent, getOpts) {
7526
8294
  }
7527
8295
 
7528
8296
  // src/commands/token.ts
7529
- import { createPublicClient as createPublicClient21, http as http21, maxUint256 } from "viem";
8297
+ import { createPublicClient as createPublicClient20, http as http20, maxUint256 } from "viem";
7530
8298
  function registerToken(parent, getOpts, makeExecutor2) {
7531
8299
  const token = parent.command("token").description("Token operations: approve, allowance, transfer, balance");
7532
8300
  token.command("balance").description("Query token balance for an address").requiredOption("--token <token>", "Token symbol or address").requiredOption("--owner <address>", "Wallet address to query").action(async (opts) => {
7533
8301
  const chainName = parent.opts().chain ?? "hyperevm";
7534
8302
  const registry = Registry.loadEmbedded();
7535
8303
  const chain = registry.getChain(chainName);
7536
- const client = createPublicClient21({ transport: http21(chain.effectiveRpcUrl()) });
8304
+ const client = createPublicClient20({ transport: http20(chain.effectiveRpcUrl()) });
7537
8305
  const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
7538
8306
  const [balance, symbol, decimals] = await Promise.all([
7539
8307
  client.readContract({ address: tokenAddr, abi: erc20Abi, functionName: "balanceOf", args: [opts.owner] }),
@@ -7562,7 +8330,7 @@ function registerToken(parent, getOpts, makeExecutor2) {
7562
8330
  const chainName = parent.opts().chain ?? "hyperevm";
7563
8331
  const registry = Registry.loadEmbedded();
7564
8332
  const chain = registry.getChain(chainName);
7565
- const client = createPublicClient21({ transport: http21(chain.effectiveRpcUrl()) });
8333
+ const client = createPublicClient20({ transport: http20(chain.effectiveRpcUrl()) });
7566
8334
  const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
7567
8335
  const allowance = await client.readContract({
7568
8336
  address: tokenAddr,
@@ -7584,8 +8352,8 @@ function registerToken(parent, getOpts, makeExecutor2) {
7584
8352
  }
7585
8353
 
7586
8354
  // src/commands/whales.ts
7587
- import { encodeFunctionData as encodeFunctionData27, parseAbi as parseAbi30 } from "viem";
7588
- var POOL_ABI6 = parseAbi30([
8355
+ import { encodeFunctionData as encodeFunctionData28, parseAbi as parseAbi31 } from "viem";
8356
+ var POOL_ABI6 = parseAbi31([
7589
8357
  "function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
7590
8358
  ]);
7591
8359
  function round24(x) {
@@ -7594,7 +8362,7 @@ function round24(x) {
7594
8362
  function round43(x) {
7595
8363
  return Math.round(x * 1e4) / 1e4;
7596
8364
  }
7597
- function decodeU2563(data, wordOffset = 0) {
8365
+ function decodeU2564(data, wordOffset = 0) {
7598
8366
  if (!data || data.length < 2 + (wordOffset + 1) * 64) return 0n;
7599
8367
  const hex = data.slice(2 + wordOffset * 64, 2 + wordOffset * 64 + 64);
7600
8368
  return BigInt("0x" + hex);
@@ -7696,7 +8464,7 @@ function registerWhales(parent, getOpts) {
7696
8464
  for (const { pool } of lendingPools) {
7697
8465
  calls.push([
7698
8466
  pool,
7699
- encodeFunctionData27({ abi: POOL_ABI6, functionName: "getUserAccountData", args: [whale.address] })
8467
+ encodeFunctionData28({ abi: POOL_ABI6, functionName: "getUserAccountData", args: [whale.address] })
7700
8468
  ]);
7701
8469
  }
7702
8470
  }
@@ -7719,9 +8487,9 @@ function registerWhales(parent, getOpts) {
7719
8487
  if (data && data.length >= 2 + 192 * 2) {
7720
8488
  const dec = iface === "aave_v2" ? 18 : 8;
7721
8489
  const divisor = 10 ** dec;
7722
- const collateral = Number(decodeU2563(data, 0)) / divisor;
7723
- const debt = Number(decodeU2563(data, 1)) / divisor;
7724
- const hfRaw = decodeU2563(data, 5);
8490
+ const collateral = Number(decodeU2564(data, 0)) / divisor;
8491
+ const debt = Number(decodeU2564(data, 1)) / divisor;
8492
+ const hfRaw = decodeU2564(data, 5);
7725
8493
  let hf = null;
7726
8494
  if (hfRaw <= BigInt("0xffffffffffffffffffffffffffffffff")) {
7727
8495
  const v = Number(hfRaw) / 1e18;
@@ -8124,11 +8892,11 @@ function registerBridge(parent, getOpts) {
8124
8892
  const amountUsdc = Number(BigInt(opts.amount)) / 1e6;
8125
8893
  const { fee, maxFeeSubunits } = await getCctpFeeEstimate(srcDomain, dstDomain, amountUsdc);
8126
8894
  const recipientPadded = `0x${"0".repeat(24)}${recipient.replace("0x", "").toLowerCase()}`;
8127
- const { encodeFunctionData: encodeFunctionData28, parseAbi: parseAbi31 } = await import("viem");
8128
- const tokenMessengerAbi = parseAbi31([
8895
+ const { encodeFunctionData: encodeFunctionData29, parseAbi: parseAbi33 } = await import("viem");
8896
+ const tokenMessengerAbi = parseAbi33([
8129
8897
  "function depositForBurn(uint256 amount, uint32 destinationDomain, bytes32 mintRecipient, address burnToken, bytes32 destinationCaller, uint256 maxFee, uint32 minFinalityThreshold) external returns (uint64 nonce)"
8130
8898
  ]);
8131
- const data = encodeFunctionData28({
8899
+ const data = encodeFunctionData29({
8132
8900
  abi: tokenMessengerAbi,
8133
8901
  functionName: "depositForBurn",
8134
8902
  args: [
@@ -8465,6 +9233,107 @@ function registerSetup(program2) {
8465
9233
  });
8466
9234
  }
8467
9235
 
9236
+ // src/commands/lb.ts
9237
+ function registerLB(parent, getOpts, makeExecutor2) {
9238
+ const lb = parent.command("lb").description("Merchant Moe Liquidity Book: add/remove liquidity, rewards, positions");
9239
+ lb.command("add").description("Add liquidity to a Liquidity Book pair").requiredOption("--protocol <protocol>", "Protocol slug (e.g. merchantmoe-mantle)").requiredOption("--pool <address>", "LB pair address").requiredOption("--token-x <address>", "Token X address").requiredOption("--token-y <address>", "Token Y address").requiredOption("--bin-step <step>", "Bin step of the pair").option("--amount-x <wei>", "Amount of token X in wei", "0").option("--amount-y <wei>", "Amount of token Y in wei", "0").option("--bins <N>", "Number of bins on each side of active bin", "5").option("--active-id <id>", "Active bin id (defaults to on-chain query)").option("--recipient <address>", "Recipient address").action(async (opts) => {
9240
+ const executor = makeExecutor2();
9241
+ const registry = Registry.loadEmbedded();
9242
+ const protocol = registry.getProtocol(opts.protocol);
9243
+ const chainName = parent.opts().chain;
9244
+ const chain = registry.getChain(chainName ?? "mantle");
9245
+ const rpcUrl = chain.effectiveRpcUrl();
9246
+ const adapter = createMerchantMoeLB(protocol, rpcUrl);
9247
+ const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
9248
+ const tx = await adapter.buildAddLiquidity({
9249
+ pool: opts.pool,
9250
+ tokenX: opts.tokenX,
9251
+ tokenY: opts.tokenY,
9252
+ binStep: parseInt(opts.binStep),
9253
+ amountX: BigInt(opts.amountX),
9254
+ amountY: BigInt(opts.amountY),
9255
+ numBins: parseInt(opts.bins),
9256
+ activeIdDesired: opts.activeId ? parseInt(opts.activeId) : void 0,
9257
+ recipient
9258
+ });
9259
+ const result = await executor.execute(tx);
9260
+ printOutput(result, getOpts());
9261
+ });
9262
+ lb.command("remove").description("Remove liquidity from Liquidity Book bins").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--token-x <address>", "Token X address").requiredOption("--token-y <address>", "Token Y address").requiredOption("--bin-step <step>", "Bin step of the pair").requiredOption("--bins <binIds>", "Comma-separated bin IDs to remove from").requiredOption("--amounts <amounts>", "Comma-separated LB token amounts to remove per bin (wei)").option("--recipient <address>", "Recipient address").action(async (opts) => {
9263
+ const executor = makeExecutor2();
9264
+ const registry = Registry.loadEmbedded();
9265
+ const protocol = registry.getProtocol(opts.protocol);
9266
+ const adapter = createMerchantMoeLB(protocol);
9267
+ const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
9268
+ const binIds = opts.bins.split(",").map((s) => parseInt(s.trim()));
9269
+ const amounts = opts.amounts.split(",").map((s) => BigInt(s.trim()));
9270
+ const tx = await adapter.buildRemoveLiquidity({
9271
+ tokenX: opts.tokenX,
9272
+ tokenY: opts.tokenY,
9273
+ binStep: parseInt(opts.binStep),
9274
+ binIds,
9275
+ amounts,
9276
+ recipient
9277
+ });
9278
+ const result = await executor.execute(tx);
9279
+ printOutput(result, getOpts());
9280
+ });
9281
+ lb.command("rewards").description("Show pending MOE rewards for a pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "LB pair address").option("--bins <binIds>", "Comma-separated bin IDs to check (auto-detected from rewarder range if omitted)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
9282
+ const registry = Registry.loadEmbedded();
9283
+ const protocol = registry.getProtocol(opts.protocol);
9284
+ const chainName = parent.opts().chain;
9285
+ const chain = registry.getChain(chainName ?? "mantle");
9286
+ const rpcUrl = chain.effectiveRpcUrl();
9287
+ const adapter = createMerchantMoeLB(protocol, rpcUrl);
9288
+ const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
9289
+ if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
9290
+ const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
9291
+ const rewards = await adapter.getPendingRewards(user, opts.pool, binIds);
9292
+ printOutput(rewards, getOpts());
9293
+ });
9294
+ lb.command("claim").description("Claim pending MOE rewards from a pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "LB pair address").option("--bins <binIds>", "Comma-separated bin IDs to claim from (auto-detected from rewarder range if omitted)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
9295
+ const executor = makeExecutor2();
9296
+ const registry = Registry.loadEmbedded();
9297
+ const protocol = registry.getProtocol(opts.protocol);
9298
+ const chainName = parent.opts().chain;
9299
+ const chain = registry.getChain(chainName ?? "mantle");
9300
+ const rpcUrl = chain.effectiveRpcUrl();
9301
+ const adapter = createMerchantMoeLB(protocol, rpcUrl);
9302
+ const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
9303
+ if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
9304
+ const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
9305
+ const tx = await adapter.buildClaimRewards(user, opts.pool, binIds);
9306
+ const result = await executor.execute(tx);
9307
+ printOutput(result, getOpts());
9308
+ });
9309
+ lb.command("discover").description("Find all rewarded LB pools on chain").requiredOption("--protocol <protocol>", "Protocol slug").option("--active-only", "Only show non-stopped pools").action(async (opts) => {
9310
+ const registry = Registry.loadEmbedded();
9311
+ const protocol = registry.getProtocol(opts.protocol);
9312
+ const chainName = parent.opts().chain;
9313
+ const chain = registry.getChain(chainName ?? "mantle");
9314
+ const rpcUrl = chain.effectiveRpcUrl();
9315
+ const adapter = createMerchantMoeLB(protocol, rpcUrl);
9316
+ let pools = await adapter.discoverRewardedPools();
9317
+ if (opts.activeOnly) {
9318
+ pools = pools.filter((p) => !p.stopped);
9319
+ }
9320
+ printOutput(pools, getOpts());
9321
+ });
9322
+ lb.command("positions").description("Show user positions per bin in a LB pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "LB pair address").option("--bins <binIds>", "Comma-separated bin IDs to query (auto-detected from rewarder range or active \xB1 50 if omitted)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
9323
+ const registry = Registry.loadEmbedded();
9324
+ const protocol = registry.getProtocol(opts.protocol);
9325
+ const chainName = parent.opts().chain;
9326
+ const chain = registry.getChain(chainName ?? "mantle");
9327
+ const rpcUrl = chain.effectiveRpcUrl();
9328
+ const adapter = createMerchantMoeLB(protocol, rpcUrl);
9329
+ const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
9330
+ if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
9331
+ const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
9332
+ const positions = await adapter.getUserPositions(user, opts.pool, binIds);
9333
+ printOutput(positions, getOpts());
9334
+ });
9335
+ }
9336
+
8468
9337
  // src/cli.ts
8469
9338
  var _require = createRequire(import.meta.url);
8470
9339
  var _pkg = _require("../package.json");
@@ -8476,7 +9345,7 @@ var BANNER = `
8476
9345
  \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551
8477
9346
  \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D
8478
9347
 
8479
- 2 chains \xB7 32 protocols \xB7 by HypurrQuant
9348
+ 2 chains \xB7 30 protocols \xB7 by HypurrQuant
8480
9349
 
8481
9350
  Scan exploits, swap tokens, bridge assets, track whales,
8482
9351
  compare yields \u2014 all from your terminal.
@@ -8516,6 +9385,7 @@ registerSwap(program, getOutputMode, makeExecutor);
8516
9385
  registerBridge(program, getOutputMode);
8517
9386
  registerNft(program, getOutputMode);
8518
9387
  registerFarm(program, getOutputMode, makeExecutor);
9388
+ registerLB(program, getOutputMode, makeExecutor);
8519
9389
  registerSetup(program);
8520
9390
  program.command("agent").description("Agent mode: read JSON commands from stdin (for AI agents)").action(async () => {
8521
9391
  const executor = makeExecutor();