@hypurrquant/defi-cli 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -9,7 +9,7 @@ import { Command } from "commander";
9
9
  import { createRequire } from "module";
10
10
 
11
11
  // src/executor.ts
12
- import { createPublicClient as createPublicClient2, createWalletClient, http as http2 } from "viem";
12
+ import { createPublicClient as createPublicClient2, createWalletClient, http as http2, parseAbi as parseAbi3, encodeFunctionData as encodeFunctionData3 } from "viem";
13
13
  import { privateKeyToAccount } from "viem/accounts";
14
14
 
15
15
  // ../defi-core/dist/index.js
@@ -707,6 +707,16 @@ function parse(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
707
707
 
708
708
  // ../defi-core/dist/index.js
709
709
  import { existsSync } from "fs";
710
+ var TxStatus = /* @__PURE__ */ ((TxStatus2) => {
711
+ TxStatus2["DryRun"] = "dry_run";
712
+ TxStatus2["Simulated"] = "simulated";
713
+ TxStatus2["SimulationFailed"] = "simulation_failed";
714
+ TxStatus2["NeedsApproval"] = "needs_approval";
715
+ TxStatus2["Pending"] = "pending";
716
+ TxStatus2["Confirmed"] = "confirmed";
717
+ TxStatus2["Failed"] = "failed";
718
+ return TxStatus2;
719
+ })(TxStatus || {});
710
720
  var InterestRateMode = /* @__PURE__ */ ((InterestRateMode2) => {
711
721
  InterestRateMode2["Variable"] = "variable";
712
722
  InterestRateMode2["Stable"] = "stable";
@@ -1016,8 +1026,13 @@ var Registry = class _Registry {
1016
1026
  };
1017
1027
 
1018
1028
  // src/executor.ts
1029
+ var ERC20_ABI = parseAbi3([
1030
+ "function allowance(address owner, address spender) external view returns (uint256)",
1031
+ "function approve(address spender, uint256 amount) external returns (bool)"
1032
+ ]);
1019
1033
  var GAS_BUFFER_BPS = 12000n;
1020
- var DEFAULT_PRIORITY_FEE_WEI = 100000000n;
1034
+ var DEFAULT_PRIORITY_FEE_WEI = 20000000000n;
1035
+ var MAX_GAS_LIMIT = 5000000000n;
1021
1036
  var Executor = class _Executor {
1022
1037
  dryRun;
1023
1038
  rpcUrl;
@@ -1031,6 +1046,62 @@ var Executor = class _Executor {
1031
1046
  static applyGasBuffer(gas) {
1032
1047
  return gas * GAS_BUFFER_BPS / 10000n;
1033
1048
  }
1049
+ /**
1050
+ * Check allowance for a single token/spender pair and send an approve tx if needed.
1051
+ * Only called in broadcast mode (not dry-run).
1052
+ */
1053
+ async checkAndApprove(token, spender, amount, owner, publicClient, walletClient) {
1054
+ const allowance = await publicClient.readContract({
1055
+ address: token,
1056
+ abi: ERC20_ABI,
1057
+ functionName: "allowance",
1058
+ args: [owner, spender]
1059
+ });
1060
+ if (allowance >= amount) return;
1061
+ process.stderr.write(
1062
+ ` Approving ${amount} of ${token} for ${spender}...
1063
+ `
1064
+ );
1065
+ const approveData = encodeFunctionData3({
1066
+ abi: ERC20_ABI,
1067
+ functionName: "approve",
1068
+ args: [spender, amount]
1069
+ });
1070
+ const rpcUrl = this.rpcUrl;
1071
+ const gasLimit = await (async () => {
1072
+ try {
1073
+ const estimated = await publicClient.estimateGas({
1074
+ to: token,
1075
+ data: approveData,
1076
+ account: owner
1077
+ });
1078
+ const buffered = _Executor.applyGasBuffer(estimated);
1079
+ return buffered > MAX_GAS_LIMIT ? MAX_GAS_LIMIT : buffered;
1080
+ } catch {
1081
+ return 80000n;
1082
+ }
1083
+ })();
1084
+ const [maxFeePerGas, maxPriorityFeePerGas] = await this.fetchEip1559Fees(rpcUrl);
1085
+ const approveTxHash = await walletClient.sendTransaction({
1086
+ chain: null,
1087
+ account: walletClient.account,
1088
+ to: token,
1089
+ data: approveData,
1090
+ gas: gasLimit > 0n ? gasLimit : void 0,
1091
+ maxFeePerGas: maxFeePerGas > 0n ? maxFeePerGas : void 0,
1092
+ maxPriorityFeePerGas: maxPriorityFeePerGas > 0n ? maxPriorityFeePerGas : void 0
1093
+ });
1094
+ const approveTxUrl = this.explorerUrl ? `${this.explorerUrl}/tx/${approveTxHash}` : void 0;
1095
+ process.stderr.write(` Approve tx: ${approveTxHash}
1096
+ `);
1097
+ if (approveTxUrl) process.stderr.write(` Explorer: ${approveTxUrl}
1098
+ `);
1099
+ await publicClient.waitForTransactionReceipt({ hash: approveTxHash });
1100
+ process.stderr.write(
1101
+ ` Approved ${amount} of ${token} for ${spender}
1102
+ `
1103
+ );
1104
+ }
1034
1105
  /** Fetch EIP-1559 fee params from the network. Returns [maxFeePerGas, maxPriorityFeePerGas]. */
1035
1106
  async fetchEip1559Fees(rpcUrl) {
1036
1107
  try {
@@ -1057,7 +1128,10 @@ var Executor = class _Executor {
1057
1128
  value: tx.value,
1058
1129
  account: from
1059
1130
  });
1060
- if (estimated > 0n) return _Executor.applyGasBuffer(estimated);
1131
+ if (estimated > 0n) {
1132
+ const buffered = _Executor.applyGasBuffer(estimated);
1133
+ return buffered > MAX_GAS_LIMIT ? MAX_GAS_LIMIT : buffered;
1134
+ }
1061
1135
  } catch {
1062
1136
  }
1063
1137
  return tx.gas_estimate ? BigInt(tx.gas_estimate) : 0n;
@@ -1071,6 +1145,46 @@ var Executor = class _Executor {
1071
1145
  const client = createPublicClient2({ transport: http2(rpcUrl) });
1072
1146
  const privateKey = process.env["DEFI_PRIVATE_KEY"];
1073
1147
  const from = privateKey ? privateKeyToAccount(privateKey).address : "0x0000000000000000000000000000000000000001";
1148
+ if (tx.approvals && tx.approvals.length > 0) {
1149
+ const pendingApprovals = [];
1150
+ for (const approval of tx.approvals) {
1151
+ try {
1152
+ const allowance = await client.readContract({
1153
+ address: approval.token,
1154
+ abi: ERC20_ABI,
1155
+ functionName: "allowance",
1156
+ args: [from, approval.spender]
1157
+ });
1158
+ if (allowance < approval.amount) {
1159
+ pendingApprovals.push({
1160
+ token: approval.token,
1161
+ spender: approval.spender,
1162
+ needed: approval.amount.toString(),
1163
+ current: allowance.toString()
1164
+ });
1165
+ }
1166
+ } catch {
1167
+ }
1168
+ }
1169
+ if (pendingApprovals.length > 0) {
1170
+ return {
1171
+ tx_hash: void 0,
1172
+ status: TxStatus.NeedsApproval,
1173
+ gas_used: tx.gas_estimate,
1174
+ description: tx.description,
1175
+ details: {
1176
+ to: tx.to,
1177
+ from,
1178
+ data: tx.data,
1179
+ value: tx.value.toString(),
1180
+ mode: "simulated",
1181
+ result: "needs_approval",
1182
+ pending_approvals: pendingApprovals,
1183
+ hint: "Use --broadcast to auto-approve and execute"
1184
+ }
1185
+ };
1186
+ }
1187
+ }
1074
1188
  try {
1075
1189
  await client.call({ to: tx.to, data: tx.data, value: tx.value, account: from });
1076
1190
  const gasEstimate = await this.estimateGasWithBuffer(rpcUrl, tx, from);
@@ -1143,6 +1257,18 @@ var Executor = class _Executor {
1143
1257
  }
1144
1258
  const publicClient = createPublicClient2({ transport: http2(rpcUrl) });
1145
1259
  const walletClient = createWalletClient({ account, transport: http2(rpcUrl) });
1260
+ if (tx.approvals && tx.approvals.length > 0) {
1261
+ for (const approval of tx.approvals) {
1262
+ await this.checkAndApprove(
1263
+ approval.token,
1264
+ approval.spender,
1265
+ approval.amount,
1266
+ account.address,
1267
+ publicClient,
1268
+ walletClient
1269
+ );
1270
+ }
1271
+ }
1146
1272
  const gasLimit = await this.estimateGasWithBuffer(rpcUrl, tx, account.address);
1147
1273
  const [maxFeePerGas, maxPriorityFeePerGas] = await this.fetchEip1559Fees(rpcUrl);
1148
1274
  process.stderr.write(`Broadcasting transaction to ${rpcUrl}...
@@ -1719,45 +1845,52 @@ function registerSchema(parent, getOpts) {
1719
1845
  }
1720
1846
 
1721
1847
  // ../defi-protocols/dist/index.js
1722
- import { encodeFunctionData as encodeFunctionData3, parseAbi as parseAbi3, createPublicClient as createPublicClient4, http as http4, decodeAbiParameters } from "viem";
1848
+ import { encodeFunctionData as encodeFunctionData4, parseAbi as parseAbi4, createPublicClient as createPublicClient4, http as http4, decodeAbiParameters } from "viem";
1723
1849
  import { encodeFunctionData as encodeFunctionData22, parseAbi as parseAbi22, createPublicClient as createPublicClient22, http as http22, decodeFunctionResult as decodeFunctionResult2, decodeAbiParameters as decodeAbiParameters2 } from "viem";
1724
1850
  import { encodeFunctionData as encodeFunctionData32, parseAbi as parseAbi32, createPublicClient as createPublicClient32, http as http32, decodeAbiParameters as decodeAbiParameters3, concatHex, zeroAddress } from "viem";
1725
- import { encodeFunctionData as encodeFunctionData4, parseAbi as parseAbi4, zeroAddress as zeroAddress2 } from "viem";
1851
+ import { encodeFunctionData as encodeFunctionData42, parseAbi as parseAbi42, zeroAddress as zeroAddress2 } from "viem";
1726
1852
  import { encodeFunctionData as encodeFunctionData5, parseAbi as parseAbi5 } from "viem";
1727
- import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6, createPublicClient as createPublicClient42, http as http42, decodeAbiParameters as decodeAbiParameters4 } from "viem";
1853
+ import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6, decodeAbiParameters as decodeAbiParameters4 } from "viem";
1728
1854
  import { encodeFunctionData as encodeFunctionData7, parseAbi as parseAbi7, zeroAddress as zeroAddress3 } from "viem";
1729
- import { createPublicClient as createPublicClient5, encodeFunctionData as encodeFunctionData8, http as http5, parseAbi as parseAbi8, zeroAddress as zeroAddress4 } from "viem";
1730
- import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9, createPublicClient as createPublicClient6, http as http6 } from "viem";
1731
- import { createPublicClient as createPublicClient7, http as http7, parseAbi as parseAbi10, encodeFunctionData as encodeFunctionData10, zeroAddress as zeroAddress5 } from "viem";
1732
- import { createPublicClient as createPublicClient8, http as http8, parseAbi as parseAbi11, encodeFunctionData as encodeFunctionData11, zeroAddress as zeroAddress6 } from "viem";
1733
- import { createPublicClient as createPublicClient9, http as http9, parseAbi as parseAbi12 } from "viem";
1734
- import { createPublicClient as createPublicClient10, http as http10, parseAbi as parseAbi13, encodeFunctionData as encodeFunctionData12 } from "viem";
1735
- import { createPublicClient as createPublicClient11, http as http11, parseAbi as parseAbi14, encodeFunctionData as encodeFunctionData13 } from "viem";
1736
- import { createPublicClient as createPublicClient12, http as http12, parseAbi as parseAbi15, encodeFunctionData as encodeFunctionData14 } from "viem";
1737
- import { createPublicClient as createPublicClient13, http as http13, parseAbi as parseAbi16, encodeFunctionData as encodeFunctionData15, zeroAddress as zeroAddress7 } from "viem";
1738
- import { createPublicClient as createPublicClient14, http as http14, parseAbi as parseAbi17, encodeFunctionData as encodeFunctionData16, zeroAddress as zeroAddress8 } from "viem";
1739
- import { createPublicClient as createPublicClient15, http as http15, parseAbi as parseAbi18 } from "viem";
1740
- import { createPublicClient as createPublicClient16, http as http16, parseAbi as parseAbi19, encodeFunctionData as encodeFunctionData17 } from "viem";
1741
- import { parseAbi as parseAbi20, encodeFunctionData as encodeFunctionData18 } from "viem";
1742
- import { createPublicClient as createPublicClient17, http as http17, parseAbi as parseAbi21, encodeFunctionData as encodeFunctionData19, zeroAddress as zeroAddress9 } from "viem";
1743
- import { createPublicClient as createPublicClient18, http as http18, parseAbi as parseAbi222, encodeFunctionData as encodeFunctionData20, zeroAddress as zeroAddress10 } from "viem";
1744
- import { parseAbi as parseAbi23, encodeFunctionData as encodeFunctionData21 } from "viem";
1855
+ import { createPublicClient as createPublicClient42, encodeFunctionData as encodeFunctionData8, http as http42, parseAbi as parseAbi8, zeroAddress as zeroAddress4 } from "viem";
1856
+ import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9, createPublicClient as createPublicClient5, http as http5 } from "viem";
1857
+ import {
1858
+ encodeFunctionData as encodeFunctionData10,
1859
+ decodeFunctionResult as decodeFunctionResult22,
1860
+ parseAbi as parseAbi10,
1861
+ createPublicClient as createPublicClient6,
1862
+ http as http6
1863
+ } from "viem";
1864
+ import { createPublicClient as createPublicClient7, http as http7, parseAbi as parseAbi11, encodeFunctionData as encodeFunctionData11, decodeFunctionResult as decodeFunctionResult3, zeroAddress as zeroAddress5 } from "viem";
1865
+ import { createPublicClient as createPublicClient8, http as http8, parseAbi as parseAbi12, encodeFunctionData as encodeFunctionData12, zeroAddress as zeroAddress6 } from "viem";
1866
+ import { createPublicClient as createPublicClient9, http as http9, parseAbi as parseAbi13 } from "viem";
1867
+ import { createPublicClient as createPublicClient10, http as http10, parseAbi as parseAbi14, encodeFunctionData as encodeFunctionData13 } from "viem";
1868
+ import { createPublicClient as createPublicClient11, http as http11, parseAbi as parseAbi15, encodeFunctionData as encodeFunctionData14 } from "viem";
1869
+ import { createPublicClient as createPublicClient12, http as http12, parseAbi as parseAbi16, encodeFunctionData as encodeFunctionData15 } from "viem";
1870
+ import { parseAbi as parseAbi17, encodeFunctionData as encodeFunctionData16, decodeFunctionResult as decodeFunctionResult4, zeroAddress as zeroAddress7 } from "viem";
1871
+ import { createPublicClient as createPublicClient13, http as http13, parseAbi as parseAbi18, encodeFunctionData as encodeFunctionData17, zeroAddress as zeroAddress8 } from "viem";
1872
+ import { createPublicClient as createPublicClient14, http as http14, parseAbi as parseAbi19 } from "viem";
1873
+ import { createPublicClient as createPublicClient15, http as http15, parseAbi as parseAbi20, encodeFunctionData as encodeFunctionData18 } from "viem";
1874
+ import { parseAbi as parseAbi21, encodeFunctionData as encodeFunctionData19 } from "viem";
1875
+ import { createPublicClient as createPublicClient16, http as http16, parseAbi as parseAbi222, encodeFunctionData as encodeFunctionData20, zeroAddress as zeroAddress9 } from "viem";
1876
+ import { createPublicClient as createPublicClient17, http as http17, parseAbi as parseAbi23, encodeFunctionData as encodeFunctionData21, zeroAddress as zeroAddress10 } from "viem";
1745
1877
  import { parseAbi as parseAbi24, encodeFunctionData as encodeFunctionData222 } from "viem";
1746
- import { createPublicClient as createPublicClient19, http as http19, parseAbi as parseAbi25 } from "viem";
1878
+ import { parseAbi as parseAbi25, encodeFunctionData as encodeFunctionData23 } from "viem";
1879
+ import { createPublicClient as createPublicClient18, http as http18, parseAbi as parseAbi26 } from "viem";
1747
1880
  var DEFAULT_FEE = 3e3;
1748
- var swapRouterAbi = parseAbi3([
1881
+ var swapRouterAbi = parseAbi4([
1749
1882
  "struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; }",
1750
1883
  "function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut)"
1751
1884
  ]);
1752
- var quoterAbi = parseAbi3([
1885
+ var quoterAbi = parseAbi4([
1753
1886
  "struct QuoteExactInputSingleParams { address tokenIn; address tokenOut; uint256 amountIn; uint24 fee; uint160 sqrtPriceLimitX96; }",
1754
1887
  "function quoteExactInputSingle(QuoteExactInputSingleParams memory params) external returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)"
1755
1888
  ]);
1756
- var ramsesQuoterAbi = parseAbi3([
1889
+ var ramsesQuoterAbi = parseAbi4([
1757
1890
  "struct QuoteExactInputSingleParams { address tokenIn; address tokenOut; uint256 amountIn; int24 tickSpacing; uint160 sqrtPriceLimitX96; }",
1758
1891
  "function quoteExactInputSingle(QuoteExactInputSingleParams memory params) external returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)"
1759
1892
  ]);
1760
- var positionManagerAbi = parseAbi3([
1893
+ var positionManagerAbi = parseAbi4([
1761
1894
  "struct MintParams { address token0; address token1; uint24 fee; int24 tickLower; int24 tickUpper; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; address recipient; uint256 deadline; }",
1762
1895
  "function mint(MintParams calldata params) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1)"
1763
1896
  ]);
@@ -1790,7 +1923,7 @@ var UniswapV3Adapter = class {
1790
1923
  async buildSwap(params) {
1791
1924
  const deadline = BigInt(params.deadline ?? 18446744073709551615n);
1792
1925
  const amountOutMinimum = 0n;
1793
- const data = encodeFunctionData3({
1926
+ const data = encodeFunctionData4({
1794
1927
  abi: swapRouterAbi,
1795
1928
  functionName: "exactInputSingle",
1796
1929
  args: [
@@ -1811,7 +1944,8 @@ var UniswapV3Adapter = class {
1811
1944
  to: this.router,
1812
1945
  data,
1813
1946
  value: 0n,
1814
- gas_estimate: 2e5
1947
+ gas_estimate: 2e5,
1948
+ approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
1815
1949
  };
1816
1950
  }
1817
1951
  async quote(params) {
@@ -1826,7 +1960,7 @@ var UniswapV3Adapter = class {
1826
1960
  tickSpacings.map(async (ts) => {
1827
1961
  const result = await client2.call({
1828
1962
  to: this.quoter,
1829
- data: encodeFunctionData3({
1963
+ data: encodeFunctionData4({
1830
1964
  abi: ramsesQuoterAbi,
1831
1965
  functionName: "quoteExactInputSingle",
1832
1966
  args: [
@@ -1872,7 +2006,7 @@ var UniswapV3Adapter = class {
1872
2006
  feeTiers.map(async (fee) => {
1873
2007
  const result = await client2.call({
1874
2008
  to: this.quoter,
1875
- data: encodeFunctionData3({
2009
+ data: encodeFunctionData4({
1876
2010
  abi: quoterAbi,
1877
2011
  functionName: "quoteExactInputSingle",
1878
2012
  args: [
@@ -1911,7 +2045,7 @@ var UniswapV3Adapter = class {
1911
2045
  }
1912
2046
  }
1913
2047
  const client = createPublicClient4({ transport: http4(this.rpcUrl) });
1914
- const callData = encodeFunctionData3({
2048
+ const callData = encodeFunctionData4({
1915
2049
  abi: swapRouterAbi,
1916
2050
  functionName: "exactInputSingle",
1917
2051
  args: [
@@ -1957,7 +2091,7 @@ var UniswapV3Adapter = class {
1957
2091
  const [token0, token1, rawAmount0, rawAmount1] = params.token_a.toLowerCase() < params.token_b.toLowerCase() ? [params.token_a, params.token_b, params.amount_a, params.amount_b] : [params.token_b, params.token_a, params.amount_b, params.amount_a];
1958
2092
  const amount0 = rawAmount0 === 0n && rawAmount1 > 0n ? 1n : rawAmount0;
1959
2093
  const amount1 = rawAmount1 === 0n && rawAmount0 > 0n ? 1n : rawAmount1;
1960
- const data = encodeFunctionData3({
2094
+ const data = encodeFunctionData4({
1961
2095
  abi: positionManagerAbi,
1962
2096
  functionName: "mint",
1963
2097
  args: [
@@ -1981,7 +2115,11 @@ var UniswapV3Adapter = class {
1981
2115
  to: pm,
1982
2116
  data,
1983
2117
  value: 0n,
1984
- gas_estimate: 5e5
2118
+ gas_estimate: 5e5,
2119
+ approvals: [
2120
+ { token: token0, spender: pm, amount: amount0 },
2121
+ { token: token1, spender: pm, amount: amount1 }
2122
+ ]
1985
2123
  };
1986
2124
  }
1987
2125
  async buildRemoveLiquidity(_params) {
@@ -2040,7 +2178,8 @@ var UniswapV2Adapter = class {
2040
2178
  to: this.router,
2041
2179
  data,
2042
2180
  value: 0n,
2043
- gas_estimate: 15e4
2181
+ gas_estimate: 15e4,
2182
+ approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
2044
2183
  };
2045
2184
  }
2046
2185
  async quote(params) {
@@ -2159,7 +2298,11 @@ var UniswapV2Adapter = class {
2159
2298
  to: this.router,
2160
2299
  data,
2161
2300
  value: 0n,
2162
- gas_estimate: 3e5
2301
+ gas_estimate: 3e5,
2302
+ approvals: [
2303
+ { token: params.token_a, spender: this.router, amount: params.amount_a },
2304
+ { token: params.token_b, spender: this.router, amount: params.amount_b }
2305
+ ]
2163
2306
  };
2164
2307
  }
2165
2308
  async buildRemoveLiquidity(params) {
@@ -2246,7 +2389,8 @@ var AlgebraV3Adapter = class {
2246
2389
  to: this.router,
2247
2390
  data,
2248
2391
  value: 0n,
2249
- gas_estimate: 25e4
2392
+ gas_estimate: 25e4,
2393
+ approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
2250
2394
  };
2251
2395
  }
2252
2396
  async quote(params) {
@@ -2364,7 +2508,11 @@ var AlgebraV3Adapter = class {
2364
2508
  to: pm,
2365
2509
  data,
2366
2510
  value: 0n,
2367
- gas_estimate: 5e5
2511
+ gas_estimate: 5e5,
2512
+ approvals: [
2513
+ { token: token0, spender: pm, amount: amount0 },
2514
+ { token: token1, spender: pm, amount: amount1 }
2515
+ ]
2368
2516
  };
2369
2517
  }
2370
2518
  async buildRemoveLiquidity(_params) {
@@ -2373,7 +2521,7 @@ var AlgebraV3Adapter = class {
2373
2521
  );
2374
2522
  }
2375
2523
  };
2376
- var abi3 = parseAbi4([
2524
+ var abi3 = parseAbi42([
2377
2525
  "function swapSingleTokenExactIn(address pool, address tokenIn, address tokenOut, uint256 exactAmountIn, uint256 minAmountOut, uint256 deadline, bool wethIsEth, bytes calldata userData) external returns (uint256 amountOut)"
2378
2526
  ]);
2379
2527
  var BalancerV3Adapter = class {
@@ -2393,7 +2541,7 @@ var BalancerV3Adapter = class {
2393
2541
  async buildSwap(params) {
2394
2542
  const minAmountOut = 0n;
2395
2543
  const deadline = BigInt(params.deadline ?? 18446744073709551615n);
2396
- const data = encodeFunctionData4({
2544
+ const data = encodeFunctionData42({
2397
2545
  abi: abi3,
2398
2546
  functionName: "swapSingleTokenExactIn",
2399
2547
  args: [
@@ -2541,18 +2689,10 @@ var SolidlyAdapter = class {
2541
2689
  to: this.router,
2542
2690
  data,
2543
2691
  value: 0n,
2544
- gas_estimate: 2e5
2692
+ gas_estimate: 2e5,
2693
+ approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
2545
2694
  };
2546
2695
  }
2547
- async callGetAmountsOut(client, callData) {
2548
- const result = await client.call({ to: this.router, data: callData });
2549
- if (!result.data) return 0n;
2550
- const [amounts] = decodeAbiParameters4(
2551
- [{ name: "amounts", type: "uint256[]" }],
2552
- result.data
2553
- );
2554
- return amounts.length >= 2 ? amounts[amounts.length - 1] : 0n;
2555
- }
2556
2696
  encodeV1(params, stable) {
2557
2697
  return encodeFunctionData6({
2558
2698
  abi: abi4,
@@ -2569,7 +2709,6 @@ var SolidlyAdapter = class {
2569
2709
  }
2570
2710
  async quote(params) {
2571
2711
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
2572
- const client = createPublicClient42({ transport: http42(this.rpcUrl) });
2573
2712
  const candidates = [
2574
2713
  { callData: this.encodeV1(params, false), stable: false },
2575
2714
  { callData: this.encodeV1(params, true), stable: true }
@@ -2580,16 +2719,26 @@ var SolidlyAdapter = class {
2580
2719
  { callData: this.encodeV2(params, true), stable: true }
2581
2720
  );
2582
2721
  }
2583
- const results = await Promise.allSettled(
2584
- candidates.map((c) => this.callGetAmountsOut(client, c.callData))
2722
+ const rawResults = await multicallRead(
2723
+ this.rpcUrl,
2724
+ candidates.map((c) => [this.router, c.callData])
2585
2725
  );
2586
2726
  let bestOut = 0n;
2587
2727
  let bestStable = false;
2588
- for (let i = 0; i < results.length; i++) {
2589
- const r = results[i];
2590
- if (r.status === "fulfilled" && r.value > bestOut) {
2591
- bestOut = r.value;
2592
- bestStable = candidates[i].stable;
2728
+ for (let i = 0; i < rawResults.length; i++) {
2729
+ const raw = rawResults[i];
2730
+ if (!raw) continue;
2731
+ try {
2732
+ const [amounts] = decodeAbiParameters4(
2733
+ [{ name: "amounts", type: "uint256[]" }],
2734
+ raw
2735
+ );
2736
+ const out = amounts.length >= 2 ? amounts[amounts.length - 1] : 0n;
2737
+ if (out > bestOut) {
2738
+ bestOut = out;
2739
+ bestStable = candidates[i].stable;
2740
+ }
2741
+ } catch {
2593
2742
  }
2594
2743
  }
2595
2744
  if (bestOut === 0n) {
@@ -2624,7 +2773,11 @@ var SolidlyAdapter = class {
2624
2773
  to: this.router,
2625
2774
  data,
2626
2775
  value: 0n,
2627
- gas_estimate: 35e4
2776
+ gas_estimate: 35e4,
2777
+ approvals: [
2778
+ { token: params.token_a, spender: this.router, amount: params.amount_a },
2779
+ { token: params.token_b, spender: this.router, amount: params.amount_b }
2780
+ ]
2628
2781
  };
2629
2782
  }
2630
2783
  async buildRemoveLiquidity(params) {
@@ -2750,7 +2903,7 @@ var SolidlyGaugeAdapter = class {
2750
2903
  return this.protocolName;
2751
2904
  }
2752
2905
  // IGauge
2753
- async buildDeposit(gauge, amount, tokenId) {
2906
+ async buildDeposit(gauge, amount, tokenId, lpToken) {
2754
2907
  if (tokenId !== void 0) {
2755
2908
  const data2 = encodeFunctionData8({
2756
2909
  abi: gaugeAbi,
@@ -2762,7 +2915,8 @@ var SolidlyGaugeAdapter = class {
2762
2915
  to: gauge,
2763
2916
  data: data2,
2764
2917
  value: 0n,
2765
- gas_estimate: 2e5
2918
+ gas_estimate: 2e5,
2919
+ approvals: lpToken ? [{ token: lpToken, spender: gauge, amount }] : void 0
2766
2920
  };
2767
2921
  }
2768
2922
  const data = encodeFunctionData8({
@@ -2775,7 +2929,8 @@ var SolidlyGaugeAdapter = class {
2775
2929
  to: gauge,
2776
2930
  data,
2777
2931
  value: 0n,
2778
- gas_estimate: 2e5
2932
+ gas_estimate: 2e5,
2933
+ approvals: lpToken ? [{ token: lpToken, spender: gauge, amount }] : void 0
2779
2934
  };
2780
2935
  }
2781
2936
  async buildWithdraw(gauge, amount) {
@@ -2795,7 +2950,7 @@ var SolidlyGaugeAdapter = class {
2795
2950
  async buildClaimRewards(gauge, account) {
2796
2951
  if (account && this.rpcUrl) {
2797
2952
  try {
2798
- const client = createPublicClient5({ transport: http5(this.rpcUrl) });
2953
+ const client = createPublicClient42({ transport: http42(this.rpcUrl) });
2799
2954
  const listLen = await client.readContract({
2800
2955
  address: gauge,
2801
2956
  abi: gaugeAbi,
@@ -3053,7 +3208,7 @@ var MasterChefAdapter = class {
3053
3208
  if (!this.rpcUrl) {
3054
3209
  throw DefiError.unsupported(`[${this.protocolName}] getPendingRewards requires RPC`);
3055
3210
  }
3056
- const client = createPublicClient6({ transport: http6(this.rpcUrl) });
3211
+ const client = createPublicClient5({ transport: http5(this.rpcUrl) });
3057
3212
  const rewards = await client.readContract({
3058
3213
  address: this.masterchef,
3059
3214
  abi: masterchefAbi,
@@ -3067,7 +3222,682 @@ var MasterChefAdapter = class {
3067
3222
  }));
3068
3223
  }
3069
3224
  };
3070
- var POOL_ABI = parseAbi10([
3225
+ var lbRouterAbi = parseAbi10([
3226
+ "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; }",
3227
+ "function addLiquidity(LiquidityParameters calldata liquidityParameters) external returns (uint256 amountXAdded, uint256 amountYAdded, uint256 amountXLeft, uint256 amountYLeft, uint256[] memory depositIds, uint256[] memory liquidityMinted)",
3228
+ "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)"
3229
+ ]);
3230
+ var lbFactoryAbi = parseAbi10([
3231
+ "function getNumberOfLBPairs() external view returns (uint256)",
3232
+ "function getLBPairAtIndex(uint256 index) external view returns (address)"
3233
+ ]);
3234
+ var lbPairAbi = parseAbi10([
3235
+ "function getLBHooksParameters() external view returns (bytes32)",
3236
+ "function getActiveId() external view returns (uint24)",
3237
+ "function getBinStep() external view returns (uint16)",
3238
+ "function getTokenX() external view returns (address)",
3239
+ "function getTokenY() external view returns (address)",
3240
+ "function balanceOf(address account, uint256 id) external view returns (uint256)",
3241
+ "function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory)"
3242
+ ]);
3243
+ var lbRewarderAbi = parseAbi10([
3244
+ "function getRewardToken() external view returns (address)",
3245
+ "function getRewardedRange() external view returns (uint256 minBinId, uint256 maxBinId)",
3246
+ "function getPendingRewards(address user, uint256[] calldata ids) external view returns (uint256 pendingRewards)",
3247
+ "function claim(address user, uint256[] calldata ids) external",
3248
+ "function getPid() external view returns (uint256)",
3249
+ "function isStopped() external view returns (bool)",
3250
+ "function getLBPair() external view returns (address)",
3251
+ "function getMasterChef() external view returns (address)"
3252
+ ]);
3253
+ var masterChefAbi = parseAbi10([
3254
+ "function getMoePerSecond() external view returns (uint256)",
3255
+ "function getTreasuryShare() external view returns (uint256)",
3256
+ "function getStaticShare() external view returns (uint256)",
3257
+ "function getVeMoe() external view returns (address)"
3258
+ ]);
3259
+ var veMoeAbi = parseAbi10([
3260
+ "function getWeight(uint256 pid) external view returns (uint256)",
3261
+ "function getTotalWeight() external view returns (uint256)",
3262
+ "function getTopPoolIds() external view returns (uint256[] memory)"
3263
+ ]);
3264
+ var lbPairBinAbi = parseAbi10([
3265
+ "function getBin(uint24 id) external view returns (uint128 reserveX, uint128 reserveY)",
3266
+ "function getActiveId() external view returns (uint24)"
3267
+ ]);
3268
+ var lbQuoterAbi2 = parseAbi10([
3269
+ "function findBestPathFromAmountIn(address[] calldata route, uint128 amountIn) external view returns ((address[] route, address[] pairs, uint256[] binSteps, uint256[] versions, uint128[] amounts, uint128[] virtualAmountsWithoutSlippage, uint128[] fees))"
3270
+ ]);
3271
+ var erc20Abi2 = parseAbi10([
3272
+ "function symbol() external view returns (string)"
3273
+ ]);
3274
+ var _addressAbi = parseAbi10(["function f() external view returns (address)"]);
3275
+ function decodeAddressResult(data) {
3276
+ if (!data) return null;
3277
+ try {
3278
+ return decodeFunctionResult22({ abi: _addressAbi, functionName: "f", data });
3279
+ } catch {
3280
+ return null;
3281
+ }
3282
+ }
3283
+ var _uint256Abi = parseAbi10(["function f() external view returns (uint256)"]);
3284
+ function decodeUint256Result(data) {
3285
+ if (!data) return null;
3286
+ try {
3287
+ return decodeFunctionResult22({ abi: _uint256Abi, functionName: "f", data });
3288
+ } catch {
3289
+ return null;
3290
+ }
3291
+ }
3292
+ var _boolAbi = parseAbi10(["function f() external view returns (bool)"]);
3293
+ function decodeBoolResult(data) {
3294
+ if (!data) return null;
3295
+ try {
3296
+ return decodeFunctionResult22({ abi: _boolAbi, functionName: "f", data });
3297
+ } catch {
3298
+ return null;
3299
+ }
3300
+ }
3301
+ function decodeStringResult(data) {
3302
+ if (!data) return "?";
3303
+ try {
3304
+ return decodeFunctionResult22({ abi: erc20Abi2, functionName: "symbol", data });
3305
+ } catch {
3306
+ return "?";
3307
+ }
3308
+ }
3309
+ var _rangeAbi = parseAbi10(["function f() external view returns (uint256 minBinId, uint256 maxBinId)"]);
3310
+ function decodeRangeResult(data) {
3311
+ if (!data) return null;
3312
+ try {
3313
+ return decodeFunctionResult22({ abi: _rangeAbi, functionName: "f", data });
3314
+ } catch {
3315
+ return null;
3316
+ }
3317
+ }
3318
+ var _binAbi = parseAbi10(["function f() external view returns (uint128 reserveX, uint128 reserveY)"]);
3319
+ function decodeBinResult(data) {
3320
+ if (!data) return null;
3321
+ try {
3322
+ return decodeFunctionResult22({ abi: _binAbi, functionName: "f", data });
3323
+ } catch {
3324
+ return null;
3325
+ }
3326
+ }
3327
+ var _uint256ArrayAbi = parseAbi10(["function f() external view returns (uint256[] memory)"]);
3328
+ function decodeUint256ArrayResult(data) {
3329
+ if (!data) return null;
3330
+ try {
3331
+ return decodeFunctionResult22({ abi: _uint256ArrayAbi, functionName: "f", data });
3332
+ } catch {
3333
+ return null;
3334
+ }
3335
+ }
3336
+ function extractRewarderAddress(hooksParams) {
3337
+ if (!hooksParams || hooksParams === "0x0000000000000000000000000000000000000000000000000000000000000000") {
3338
+ return null;
3339
+ }
3340
+ const hex = hooksParams.slice(2);
3341
+ if (hex.length < 64) return null;
3342
+ const addrHex = hex.slice(24, 64);
3343
+ if (addrHex === "0000000000000000000000000000000000000000") return null;
3344
+ return `0x${addrHex}`;
3345
+ }
3346
+ function buildUniformDistribution(deltaIds) {
3347
+ const PRECISION = 10n ** 18n;
3348
+ const n = deltaIds.length;
3349
+ const xBins = deltaIds.filter((d) => d >= 0).length;
3350
+ const yBins = deltaIds.filter((d) => d <= 0).length;
3351
+ const distributionX = [];
3352
+ const distributionY = [];
3353
+ for (const delta of deltaIds) {
3354
+ const xShare = delta >= 0 && xBins > 0 ? PRECISION / BigInt(xBins) : 0n;
3355
+ const yShare = delta <= 0 && yBins > 0 ? PRECISION / BigInt(yBins) : 0n;
3356
+ distributionX.push(xShare);
3357
+ distributionY.push(yShare);
3358
+ }
3359
+ const xSum = distributionX.reduce((a, b) => a + b, 0n);
3360
+ const ySum = distributionY.reduce((a, b) => a + b, 0n);
3361
+ if (xSum > 0n && xSum !== PRECISION) {
3362
+ const firstX = distributionX.findIndex((v) => v > 0n);
3363
+ if (firstX !== -1) distributionX[firstX] += PRECISION - xSum;
3364
+ }
3365
+ if (ySum > 0n && ySum !== PRECISION) {
3366
+ const firstY = distributionY.findIndex((v) => v > 0n);
3367
+ if (firstY !== -1) distributionY[firstY] += PRECISION - ySum;
3368
+ }
3369
+ return { distributionX, distributionY };
3370
+ }
3371
+ var MerchantMoeLBAdapter = class {
3372
+ protocolName;
3373
+ lbRouter;
3374
+ lbFactory;
3375
+ lbQuoter;
3376
+ rpcUrl;
3377
+ /** WMNT address (lb_mid_wmnt in config) used for MOE price routing */
3378
+ wmnt;
3379
+ /** USDT address (lb_mid_usdt in config) used for MNT/USD price routing */
3380
+ usdt;
3381
+ constructor(entry, rpcUrl) {
3382
+ this.protocolName = entry.name;
3383
+ const lbRouter = entry.contracts?.["lb_router"];
3384
+ if (!lbRouter) {
3385
+ throw new DefiError("CONTRACT_ERROR", "Missing 'lb_router' contract address");
3386
+ }
3387
+ const lbFactory = entry.contracts?.["lb_factory"];
3388
+ if (!lbFactory) {
3389
+ throw new DefiError("CONTRACT_ERROR", "Missing 'lb_factory' contract address");
3390
+ }
3391
+ this.lbRouter = lbRouter;
3392
+ this.lbFactory = lbFactory;
3393
+ this.lbQuoter = entry.contracts?.["lb_quoter"];
3394
+ this.wmnt = entry.contracts?.["lb_mid_wmnt"];
3395
+ this.usdt = entry.contracts?.["lb_mid_usdt"];
3396
+ this.rpcUrl = rpcUrl;
3397
+ }
3398
+ name() {
3399
+ return this.protocolName;
3400
+ }
3401
+ requireRpc() {
3402
+ if (!this.rpcUrl) {
3403
+ throw DefiError.rpcError(`[${this.protocolName}] RPC URL required`);
3404
+ }
3405
+ return this.rpcUrl;
3406
+ }
3407
+ /**
3408
+ * Build an addLiquidity transaction for a Liquidity Book pair.
3409
+ * Distributes tokenX/tokenY uniformly across active bin ± numBins.
3410
+ */
3411
+ async buildAddLiquidity(params) {
3412
+ const numBins = params.numBins ?? 5;
3413
+ const deadline = params.deadline ?? BigInt("18446744073709551615");
3414
+ let activeIdDesired = params.activeIdDesired;
3415
+ if (activeIdDesired === void 0) {
3416
+ const rpcUrl = this.requireRpc();
3417
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3418
+ const activeId = await client.readContract({
3419
+ address: params.pool,
3420
+ abi: lbPairAbi,
3421
+ functionName: "getActiveId"
3422
+ });
3423
+ activeIdDesired = activeId;
3424
+ }
3425
+ const deltaIds = [];
3426
+ for (let d = -numBins; d <= numBins; d++) {
3427
+ deltaIds.push(d);
3428
+ }
3429
+ const { distributionX, distributionY } = buildUniformDistribution(deltaIds);
3430
+ const data = encodeFunctionData10({
3431
+ abi: lbRouterAbi,
3432
+ functionName: "addLiquidity",
3433
+ args: [
3434
+ {
3435
+ tokenX: params.tokenX,
3436
+ tokenY: params.tokenY,
3437
+ binStep: BigInt(params.binStep),
3438
+ amountX: params.amountX,
3439
+ amountY: params.amountY,
3440
+ amountXMin: 0n,
3441
+ amountYMin: 0n,
3442
+ activeIdDesired: BigInt(activeIdDesired),
3443
+ idSlippage: BigInt(numBins + 2),
3444
+ deltaIds: deltaIds.map(BigInt),
3445
+ distributionX,
3446
+ distributionY,
3447
+ to: params.recipient,
3448
+ refundTo: params.recipient,
3449
+ deadline
3450
+ }
3451
+ ]
3452
+ });
3453
+ return {
3454
+ description: `[${this.protocolName}] LB addLiquidity ${params.amountX} tokenX + ${params.amountY} tokenY across ${deltaIds.length} bins`,
3455
+ to: this.lbRouter,
3456
+ data,
3457
+ value: 0n,
3458
+ gas_estimate: 8e5,
3459
+ approvals: [
3460
+ { token: params.tokenX, spender: this.lbRouter, amount: params.amountX },
3461
+ { token: params.tokenY, spender: this.lbRouter, amount: params.amountY }
3462
+ ]
3463
+ };
3464
+ }
3465
+ /**
3466
+ * Build a removeLiquidity transaction for specific LB bins.
3467
+ */
3468
+ async buildRemoveLiquidity(params) {
3469
+ const deadline = params.deadline ?? BigInt("18446744073709551615");
3470
+ const data = encodeFunctionData10({
3471
+ abi: lbRouterAbi,
3472
+ functionName: "removeLiquidity",
3473
+ args: [
3474
+ params.tokenX,
3475
+ params.tokenY,
3476
+ params.binStep,
3477
+ params.amountXMin ?? 0n,
3478
+ params.amountYMin ?? 0n,
3479
+ params.binIds.map(BigInt),
3480
+ params.amounts,
3481
+ params.recipient,
3482
+ deadline
3483
+ ]
3484
+ });
3485
+ return {
3486
+ description: `[${this.protocolName}] LB removeLiquidity from ${params.binIds.length} bins`,
3487
+ to: this.lbRouter,
3488
+ data,
3489
+ value: 0n,
3490
+ gas_estimate: 6e5
3491
+ };
3492
+ }
3493
+ /**
3494
+ * Auto-detect bin IDs for a pool from the rewarder's rewarded range.
3495
+ * Falls back to active bin ± 50 scan if no rewarder exists.
3496
+ */
3497
+ async autoDetectBins(pool) {
3498
+ const rpcUrl = this.requireRpc();
3499
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3500
+ const hooksParams = await client.readContract({
3501
+ address: pool,
3502
+ abi: lbPairAbi,
3503
+ functionName: "getLBHooksParameters"
3504
+ });
3505
+ const rewarder = extractRewarderAddress(hooksParams);
3506
+ if (rewarder) {
3507
+ const range = await client.readContract({
3508
+ address: rewarder,
3509
+ abi: lbRewarderAbi,
3510
+ functionName: "getRewardedRange"
3511
+ });
3512
+ const min = Number(range[0]);
3513
+ const max = Number(range[1]);
3514
+ const ids2 = [];
3515
+ for (let b = min; b <= max; b++) ids2.push(b);
3516
+ return ids2;
3517
+ }
3518
+ const activeId = await client.readContract({
3519
+ address: pool,
3520
+ abi: lbPairAbi,
3521
+ functionName: "getActiveId"
3522
+ });
3523
+ const ids = [];
3524
+ for (let b = activeId - 50; b <= activeId + 50; b++) ids.push(b);
3525
+ return ids;
3526
+ }
3527
+ /**
3528
+ * Get pending MOE rewards for a user across specified bin IDs.
3529
+ * If binIds is omitted, auto-detects from the rewarder's rewarded range.
3530
+ * Reads the rewarder address from the pool's hooks parameters.
3531
+ */
3532
+ async getPendingRewards(user, pool, binIds) {
3533
+ const rpcUrl = this.requireRpc();
3534
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3535
+ const hooksParams = await client.readContract({
3536
+ address: pool,
3537
+ abi: lbPairAbi,
3538
+ functionName: "getLBHooksParameters"
3539
+ });
3540
+ const rewarder = extractRewarderAddress(hooksParams);
3541
+ if (!rewarder) {
3542
+ return [];
3543
+ }
3544
+ let resolvedBinIds = binIds;
3545
+ if (!resolvedBinIds || resolvedBinIds.length === 0) {
3546
+ const range = await client.readContract({
3547
+ address: rewarder,
3548
+ abi: lbRewarderAbi,
3549
+ functionName: "getRewardedRange"
3550
+ });
3551
+ const min = Number(range[0]);
3552
+ const max = Number(range[1]);
3553
+ resolvedBinIds = [];
3554
+ for (let b = min; b <= max; b++) resolvedBinIds.push(b);
3555
+ }
3556
+ const [pending, rewardToken] = await Promise.all([
3557
+ client.readContract({
3558
+ address: rewarder,
3559
+ abi: lbRewarderAbi,
3560
+ functionName: "getPendingRewards",
3561
+ args: [user, resolvedBinIds.map(BigInt)]
3562
+ }),
3563
+ client.readContract({
3564
+ address: rewarder,
3565
+ abi: lbRewarderAbi,
3566
+ functionName: "getRewardToken"
3567
+ })
3568
+ ]);
3569
+ return [
3570
+ {
3571
+ token: rewardToken,
3572
+ symbol: "MOE",
3573
+ amount: pending
3574
+ }
3575
+ ];
3576
+ }
3577
+ /**
3578
+ * Build a claim rewards transaction for specific LB bins.
3579
+ * If binIds is omitted, auto-detects from the rewarder's rewarded range.
3580
+ */
3581
+ async buildClaimRewards(user, pool, binIds) {
3582
+ const rpcUrl = this.requireRpc();
3583
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3584
+ const hooksParams = await client.readContract({
3585
+ address: pool,
3586
+ abi: lbPairAbi,
3587
+ functionName: "getLBHooksParameters"
3588
+ });
3589
+ const rewarder = extractRewarderAddress(hooksParams);
3590
+ if (!rewarder) {
3591
+ throw new DefiError("CONTRACT_ERROR", `[${this.protocolName}] Pool ${pool} has no active rewarder`);
3592
+ }
3593
+ let resolvedBinIds = binIds;
3594
+ if (!resolvedBinIds || resolvedBinIds.length === 0) {
3595
+ const range = await client.readContract({
3596
+ address: rewarder,
3597
+ abi: lbRewarderAbi,
3598
+ functionName: "getRewardedRange"
3599
+ });
3600
+ const min = Number(range[0]);
3601
+ const max = Number(range[1]);
3602
+ resolvedBinIds = [];
3603
+ for (let b = min; b <= max; b++) resolvedBinIds.push(b);
3604
+ }
3605
+ const data = encodeFunctionData10({
3606
+ abi: lbRewarderAbi,
3607
+ functionName: "claim",
3608
+ args: [user, resolvedBinIds.map(BigInt)]
3609
+ });
3610
+ return {
3611
+ description: `[${this.protocolName}] LB claim rewards for ${resolvedBinIds.length} bins`,
3612
+ to: rewarder,
3613
+ data,
3614
+ value: 0n,
3615
+ gas_estimate: 3e5
3616
+ };
3617
+ }
3618
+ /**
3619
+ * Discover all active rewarded LB pools by iterating the factory.
3620
+ * Uses 7 multicall batches to minimise RPC round-trips and avoid 429s.
3621
+ *
3622
+ * Batch 1: getNumberOfLBPairs(), then getLBPairAtIndex(i) for all i
3623
+ * Batch 2: getLBHooksParameters() for all pairs → extract rewarder addresses
3624
+ * Batch 3: isStopped/getRewardedRange/getRewardToken/getPid/getMasterChef for each rewarder
3625
+ * Batch 4: getTokenX/getTokenY for each rewarded pair, then symbol() for unique tokens
3626
+ * Batch 5: Bootstrap MasterChef→VeMoe, then getMoePerSecond/getTreasuryShare/getStaticShare/getTotalWeight/getTopPoolIds
3627
+ * Batch 6: VeMoe.getWeight(pid) for each rewarded pool
3628
+ * Batch 7: Pool.getBin(binId) for all bins in rewarded range of each pool
3629
+ * Price: LB Quoter findBestPathFromAmountIn for MOE/WMNT and WMNT/USDT prices
3630
+ */
3631
+ async discoverRewardedPools() {
3632
+ const rpcUrl = this.requireRpc();
3633
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3634
+ const pairCount = await client.readContract({
3635
+ address: this.lbFactory,
3636
+ abi: lbFactoryAbi,
3637
+ functionName: "getNumberOfLBPairs"
3638
+ });
3639
+ const count = Number(pairCount);
3640
+ if (count === 0) return [];
3641
+ const batch1Calls = Array.from({ length: count }, (_, i) => [
3642
+ this.lbFactory,
3643
+ encodeFunctionData10({ abi: lbFactoryAbi, functionName: "getLBPairAtIndex", args: [BigInt(i)] })
3644
+ ]);
3645
+ const batch1Results = await multicallRead(rpcUrl, batch1Calls);
3646
+ const pairAddresses = batch1Results.map((r) => decodeAddressResult(r)).filter((a) => a !== null);
3647
+ if (pairAddresses.length === 0) return [];
3648
+ const batch2Calls = pairAddresses.map((pair) => [
3649
+ pair,
3650
+ encodeFunctionData10({ abi: lbPairAbi, functionName: "getLBHooksParameters" })
3651
+ ]);
3652
+ const batch2Results = await multicallRead(rpcUrl, batch2Calls);
3653
+ const rewardedPairs = [];
3654
+ for (let i = 0; i < pairAddresses.length; i++) {
3655
+ const raw = batch2Results[i];
3656
+ if (!raw) continue;
3657
+ let hooksBytes;
3658
+ try {
3659
+ const _bytes32Abi = parseAbi10(["function f() external view returns (bytes32)"]);
3660
+ hooksBytes = decodeFunctionResult22({ abi: _bytes32Abi, functionName: "f", data: raw });
3661
+ } catch {
3662
+ continue;
3663
+ }
3664
+ const rewarder = extractRewarderAddress(hooksBytes);
3665
+ if (rewarder) {
3666
+ rewardedPairs.push({ pool: pairAddresses[i], rewarder });
3667
+ }
3668
+ }
3669
+ if (rewardedPairs.length === 0) return [];
3670
+ const batch3Calls = [];
3671
+ for (const { rewarder } of rewardedPairs) {
3672
+ batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "isStopped" })]);
3673
+ batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getRewardedRange" })]);
3674
+ batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getRewardToken" })]);
3675
+ batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getPid" })]);
3676
+ batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getMasterChef" })]);
3677
+ }
3678
+ const batch3Results = await multicallRead(rpcUrl, batch3Calls);
3679
+ const batch4aCalls = [];
3680
+ for (const { pool } of rewardedPairs) {
3681
+ batch4aCalls.push([pool, encodeFunctionData10({ abi: lbPairAbi, functionName: "getTokenX" })]);
3682
+ batch4aCalls.push([pool, encodeFunctionData10({ abi: lbPairAbi, functionName: "getTokenY" })]);
3683
+ }
3684
+ const batch4aResults = await multicallRead(rpcUrl, batch4aCalls);
3685
+ const tokenXAddresses = [];
3686
+ const tokenYAddresses = [];
3687
+ for (let i = 0; i < rewardedPairs.length; i++) {
3688
+ tokenXAddresses.push(decodeAddressResult(batch4aResults[i * 2] ?? null));
3689
+ tokenYAddresses.push(decodeAddressResult(batch4aResults[i * 2 + 1] ?? null));
3690
+ }
3691
+ const uniqueTokens = Array.from(
3692
+ new Set([...tokenXAddresses, ...tokenYAddresses].filter((a) => a !== null))
3693
+ );
3694
+ const batch4bCalls = uniqueTokens.map((token) => [
3695
+ token,
3696
+ encodeFunctionData10({ abi: erc20Abi2, functionName: "symbol" })
3697
+ ]);
3698
+ const batch4bResults = await multicallRead(rpcUrl, batch4bCalls);
3699
+ const symbolMap = /* @__PURE__ */ new Map();
3700
+ for (let i = 0; i < uniqueTokens.length; i++) {
3701
+ symbolMap.set(uniqueTokens[i], decodeStringResult(batch4bResults[i] ?? null));
3702
+ }
3703
+ const STRIDE3 = 5;
3704
+ const poolData = [];
3705
+ for (let i = 0; i < rewardedPairs.length; i++) {
3706
+ const base = i * STRIDE3;
3707
+ poolData.push({
3708
+ stopped: decodeBoolResult(batch3Results[base] ?? null) ?? false,
3709
+ range: decodeRangeResult(batch3Results[base + 1] ?? null),
3710
+ rewardToken: decodeAddressResult(batch3Results[base + 2] ?? null),
3711
+ pid: Number(decodeUint256Result(batch3Results[base + 3] ?? null) ?? 0n),
3712
+ masterChef: decodeAddressResult(batch3Results[base + 4] ?? null)
3713
+ });
3714
+ }
3715
+ const masterChefAddr = poolData.map((d) => d.masterChef).find((a) => a !== null) ?? null;
3716
+ let moePerDay = 0;
3717
+ let topPoolIds = /* @__PURE__ */ new Set();
3718
+ let totalWeightRaw = 0n;
3719
+ let veMoeAddr = null;
3720
+ if (masterChefAddr) {
3721
+ veMoeAddr = await client.readContract({
3722
+ address: masterChefAddr,
3723
+ abi: masterChefAbi,
3724
+ functionName: "getVeMoe"
3725
+ });
3726
+ const batch5Calls = [
3727
+ [masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getMoePerSecond" })],
3728
+ [masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getTreasuryShare" })],
3729
+ [masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getStaticShare" })],
3730
+ [veMoeAddr, encodeFunctionData10({ abi: veMoeAbi, functionName: "getTotalWeight" })],
3731
+ [veMoeAddr, encodeFunctionData10({ abi: veMoeAbi, functionName: "getTopPoolIds" })]
3732
+ ];
3733
+ const batch5Results = await multicallRead(rpcUrl, batch5Calls);
3734
+ const moePerSecRaw = decodeUint256Result(batch5Results[0] ?? null) ?? 0n;
3735
+ const treasuryShareRaw = decodeUint256Result(batch5Results[1] ?? null) ?? 0n;
3736
+ const staticShareRaw = decodeUint256Result(batch5Results[2] ?? null) ?? 0n;
3737
+ totalWeightRaw = decodeUint256Result(batch5Results[3] ?? null) ?? 0n;
3738
+ const topPoolIdsRaw = decodeUint256ArrayResult(batch5Results[4] ?? null) ?? [];
3739
+ topPoolIds = new Set(topPoolIdsRaw.map(Number));
3740
+ const PRECISION = 10n ** 18n;
3741
+ const netPerSec = moePerSecRaw * (PRECISION - treasuryShareRaw) / PRECISION * (PRECISION - staticShareRaw) / PRECISION;
3742
+ moePerDay = Number(netPerSec * 86400n) / 1e18;
3743
+ }
3744
+ const weightByPid = /* @__PURE__ */ new Map();
3745
+ if (veMoeAddr && rewardedPairs.length > 0) {
3746
+ const batch6Calls = poolData.map((d) => [
3747
+ veMoeAddr,
3748
+ encodeFunctionData10({ abi: veMoeAbi, functionName: "getWeight", args: [BigInt(d.pid)] })
3749
+ ]);
3750
+ const batch6Results = await multicallRead(rpcUrl, batch6Calls);
3751
+ for (let i = 0; i < poolData.length; i++) {
3752
+ weightByPid.set(poolData[i].pid, decodeUint256Result(batch6Results[i] ?? null) ?? 0n);
3753
+ }
3754
+ }
3755
+ let moePriceUsd = 0;
3756
+ let wmntPriceUsd = 0;
3757
+ const MOE_ADDR = "0x4515A45337F461A11Ff0FE8aBF3c606AE5dC00c9";
3758
+ if (this.lbQuoter && this.wmnt && this.usdt) {
3759
+ try {
3760
+ const [moeWmntQuote, wmntUsdtQuote] = await Promise.all([
3761
+ client.readContract({
3762
+ address: this.lbQuoter,
3763
+ abi: lbQuoterAbi2,
3764
+ functionName: "findBestPathFromAmountIn",
3765
+ args: [[MOE_ADDR, this.wmnt], 10n ** 18n]
3766
+ }),
3767
+ client.readContract({
3768
+ address: this.lbQuoter,
3769
+ abi: lbQuoterAbi2,
3770
+ functionName: "findBestPathFromAmountIn",
3771
+ args: [[this.wmnt, this.usdt], 10n ** 18n]
3772
+ })
3773
+ ]);
3774
+ const moeInWmnt = Number(moeWmntQuote.amounts.at(-1) ?? 0n) / 1e18;
3775
+ wmntPriceUsd = Number(wmntUsdtQuote.amounts.at(-1) ?? 0n) / 1e6;
3776
+ moePriceUsd = moeInWmnt * wmntPriceUsd;
3777
+ } catch {
3778
+ }
3779
+ }
3780
+ const binRequests = [];
3781
+ for (let i = 0; i < rewardedPairs.length; i++) {
3782
+ const range = poolData[i].range;
3783
+ if (!range) continue;
3784
+ const minBin = Number(range[0]);
3785
+ const maxBin = Number(range[1]);
3786
+ for (let b = minBin; b <= maxBin; b++) {
3787
+ binRequests.push({ poolIdx: i, binId: b });
3788
+ }
3789
+ }
3790
+ const binReservesX = /* @__PURE__ */ new Map();
3791
+ const binReservesY = /* @__PURE__ */ new Map();
3792
+ if (binRequests.length > 0) {
3793
+ const batch7Calls = binRequests.map(({ poolIdx, binId }) => [
3794
+ rewardedPairs[poolIdx].pool,
3795
+ encodeFunctionData10({ abi: lbPairBinAbi, functionName: "getBin", args: [binId] })
3796
+ ]);
3797
+ const batch7Results = await multicallRead(rpcUrl, batch7Calls);
3798
+ for (let j = 0; j < binRequests.length; j++) {
3799
+ const { poolIdx, binId } = binRequests[j];
3800
+ const decoded = decodeBinResult(batch7Results[j] ?? null);
3801
+ if (!decoded) continue;
3802
+ if (!binReservesX.has(poolIdx)) {
3803
+ binReservesX.set(poolIdx, /* @__PURE__ */ new Map());
3804
+ binReservesY.set(poolIdx, /* @__PURE__ */ new Map());
3805
+ }
3806
+ binReservesX.get(poolIdx).set(binId, decoded[0]);
3807
+ binReservesY.get(poolIdx).set(binId, decoded[1]);
3808
+ }
3809
+ }
3810
+ const stableSymbols = /* @__PURE__ */ new Set(["USDT", "USDC", "MUSD", "AUSD", "USDY", "FDUSD"]);
3811
+ const mntSymbols = /* @__PURE__ */ new Set(["WMNT", "MNT"]);
3812
+ const moeSymbols = /* @__PURE__ */ new Set(["MOE"]);
3813
+ const sixDecimalStables = /* @__PURE__ */ new Set(["USDT", "USDC", "FDUSD"]);
3814
+ const getTokenPriceUsd = (sym) => {
3815
+ if (stableSymbols.has(sym)) return 1;
3816
+ if (mntSymbols.has(sym)) return wmntPriceUsd;
3817
+ if (moeSymbols.has(sym)) return moePriceUsd;
3818
+ return 0;
3819
+ };
3820
+ const getTokenDecimals = (sym) => {
3821
+ return sixDecimalStables.has(sym) ? 6 : 18;
3822
+ };
3823
+ const results = [];
3824
+ for (let i = 0; i < rewardedPairs.length; i++) {
3825
+ const { pool, rewarder } = rewardedPairs[i];
3826
+ const data = poolData[i];
3827
+ const tokenX = tokenXAddresses[i] ?? "0x0000000000000000000000000000000000000000";
3828
+ const tokenY = tokenYAddresses[i] ?? "0x0000000000000000000000000000000000000000";
3829
+ const symX = symbolMap.get(tokenX) ?? "?";
3830
+ const symY = symbolMap.get(tokenY) ?? "?";
3831
+ const isTopPool = topPoolIds.has(data.pid);
3832
+ const weight = weightByPid.get(data.pid) ?? 0n;
3833
+ let poolMoePerDay = 0;
3834
+ if (isTopPool && totalWeightRaw > 0n && weight > 0n) {
3835
+ poolMoePerDay = moePerDay * (Number(weight) / Number(totalWeightRaw));
3836
+ }
3837
+ const rxMap = binReservesX.get(i);
3838
+ const ryMap = binReservesY.get(i);
3839
+ const range = data.range;
3840
+ let rangeTvlUsd = 0;
3841
+ let rewardedBins = 0;
3842
+ if (range) {
3843
+ const minBin = Number(range[0]);
3844
+ const maxBin = Number(range[1]);
3845
+ rewardedBins = maxBin - minBin + 1;
3846
+ if (rxMap && ryMap) {
3847
+ const priceX = getTokenPriceUsd(symX);
3848
+ const priceY = getTokenPriceUsd(symY);
3849
+ const decX = getTokenDecimals(symX);
3850
+ const decY = getTokenDecimals(symY);
3851
+ for (let b = minBin; b <= maxBin; b++) {
3852
+ const rx = rxMap.get(b) ?? 0n;
3853
+ const ry = ryMap.get(b) ?? 0n;
3854
+ rangeTvlUsd += Number(rx) / 10 ** decX * priceX;
3855
+ rangeTvlUsd += Number(ry) / 10 ** decY * priceY;
3856
+ }
3857
+ }
3858
+ }
3859
+ const aprPercent = rangeTvlUsd > 0 && moePriceUsd > 0 ? poolMoePerDay * moePriceUsd * 365 / rangeTvlUsd * 100 : 0;
3860
+ results.push({
3861
+ pool,
3862
+ rewarder,
3863
+ rewardToken: data.rewardToken ?? "0x0000000000000000000000000000000000000000",
3864
+ minBinId: range ? Number(range[0]) : 0,
3865
+ maxBinId: range ? Number(range[1]) : 0,
3866
+ pid: data.pid,
3867
+ stopped: data.stopped,
3868
+ tokenX,
3869
+ tokenY,
3870
+ symbolX: symX,
3871
+ symbolY: symY,
3872
+ isTopPool,
3873
+ moePerDay: poolMoePerDay,
3874
+ rangeTvlUsd,
3875
+ aprPercent,
3876
+ rewardedBins
3877
+ });
3878
+ }
3879
+ return results;
3880
+ }
3881
+ /**
3882
+ * Get a user's LB positions (bin balances) across a range of bin IDs.
3883
+ * If binIds is omitted, auto-detects from the rewarder's rewarded range (or active ± 50).
3884
+ */
3885
+ async getUserPositions(user, pool, binIds) {
3886
+ const rpcUrl = this.requireRpc();
3887
+ const client = createPublicClient6({ transport: http6(rpcUrl) });
3888
+ const resolvedBinIds = binIds && binIds.length > 0 ? binIds : await this.autoDetectBins(pool);
3889
+ const accounts = resolvedBinIds.map(() => user);
3890
+ const ids = resolvedBinIds.map(BigInt);
3891
+ const balances = await client.readContract({
3892
+ address: pool,
3893
+ abi: lbPairAbi,
3894
+ functionName: "balanceOfBatch",
3895
+ args: [accounts, ids]
3896
+ });
3897
+ return resolvedBinIds.map((binId, i) => ({ binId, balance: balances[i] ?? 0n })).filter((p) => p.balance > 0n);
3898
+ }
3899
+ };
3900
+ var POOL_ABI = parseAbi11([
3071
3901
  "function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
3072
3902
  "function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
3073
3903
  "function repay(address asset, uint256 amount, uint256 interestRateMode, address onBehalfOf) external returns (uint256)",
@@ -3075,27 +3905,27 @@ var POOL_ABI = parseAbi10([
3075
3905
  "function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)",
3076
3906
  "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)"
3077
3907
  ]);
3078
- var ERC20_ABI = parseAbi10([
3908
+ var ERC20_ABI2 = parseAbi11([
3079
3909
  "function totalSupply() external view returns (uint256)"
3080
3910
  ]);
3081
- var INCENTIVES_ABI = parseAbi10([
3911
+ var INCENTIVES_ABI = parseAbi11([
3082
3912
  "function getIncentivesController() external view returns (address)"
3083
3913
  ]);
3084
- var REWARDS_CONTROLLER_ABI = parseAbi10([
3914
+ var REWARDS_CONTROLLER_ABI = parseAbi11([
3085
3915
  "function getRewardsByAsset(address asset) external view returns (address[])",
3086
3916
  "function getRewardsData(address asset, address reward) external view returns (uint256 index, uint256 emissionsPerSecond, uint256 lastUpdateTimestamp, uint256 distributionEnd)"
3087
3917
  ]);
3088
- var POOL_PROVIDER_ABI = parseAbi10([
3918
+ var POOL_PROVIDER_ABI = parseAbi11([
3089
3919
  "function ADDRESSES_PROVIDER() external view returns (address)"
3090
3920
  ]);
3091
- var ADDRESSES_PROVIDER_ABI = parseAbi10([
3921
+ var ADDRESSES_PROVIDER_ABI = parseAbi11([
3092
3922
  "function getPriceOracle() external view returns (address)"
3093
3923
  ]);
3094
- var ORACLE_ABI = parseAbi10([
3924
+ var ORACLE_ABI = parseAbi11([
3095
3925
  "function getAssetPrice(address asset) external view returns (uint256)",
3096
3926
  "function BASE_CURRENCY_UNIT() external view returns (uint256)"
3097
3927
  ]);
3098
- var ERC20_DECIMALS_ABI = parseAbi10([
3928
+ var ERC20_DECIMALS_ABI = parseAbi11([
3099
3929
  "function decimals() external view returns (uint8)"
3100
3930
  ]);
3101
3931
  function u256ToF64(v) {
@@ -3103,6 +3933,46 @@ function u256ToF64(v) {
3103
3933
  if (v > MAX_U128) return Infinity;
3104
3934
  return Number(v);
3105
3935
  }
3936
+ function decodeAddress(data) {
3937
+ if (!data || data.length < 66) return null;
3938
+ return `0x${data.slice(26, 66)}`;
3939
+ }
3940
+ function decodeAddressArray(data) {
3941
+ if (!data) return [];
3942
+ try {
3943
+ return decodeFunctionResult3({
3944
+ abi: REWARDS_CONTROLLER_ABI,
3945
+ functionName: "getRewardsByAsset",
3946
+ data
3947
+ });
3948
+ } catch {
3949
+ return [];
3950
+ }
3951
+ }
3952
+ function decodeReserveData(data) {
3953
+ if (!data) return null;
3954
+ try {
3955
+ return decodeFunctionResult3({
3956
+ abi: POOL_ABI,
3957
+ functionName: "getReserveData",
3958
+ data
3959
+ });
3960
+ } catch {
3961
+ return null;
3962
+ }
3963
+ }
3964
+ function decodeRewardsData(data) {
3965
+ if (!data) return null;
3966
+ try {
3967
+ return decodeFunctionResult3({
3968
+ abi: REWARDS_CONTROLLER_ABI,
3969
+ functionName: "getRewardsData",
3970
+ data
3971
+ });
3972
+ } catch {
3973
+ return null;
3974
+ }
3975
+ }
3106
3976
  var AaveV3Adapter = class {
3107
3977
  protocolName;
3108
3978
  pool;
@@ -3118,7 +3988,7 @@ var AaveV3Adapter = class {
3118
3988
  return this.protocolName;
3119
3989
  }
3120
3990
  async buildSupply(params) {
3121
- const data = encodeFunctionData10({
3991
+ const data = encodeFunctionData11({
3122
3992
  abi: POOL_ABI,
3123
3993
  functionName: "supply",
3124
3994
  args: [params.asset, params.amount, params.on_behalf_of, 0]
@@ -3128,12 +3998,13 @@ var AaveV3Adapter = class {
3128
3998
  to: this.pool,
3129
3999
  data,
3130
4000
  value: 0n,
3131
- gas_estimate: 3e5
4001
+ gas_estimate: 3e5,
4002
+ approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
3132
4003
  };
3133
4004
  }
3134
4005
  async buildBorrow(params) {
3135
4006
  const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
3136
- const data = encodeFunctionData10({
4007
+ const data = encodeFunctionData11({
3137
4008
  abi: POOL_ABI,
3138
4009
  functionName: "borrow",
3139
4010
  args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
@@ -3148,7 +4019,7 @@ var AaveV3Adapter = class {
3148
4019
  }
3149
4020
  async buildRepay(params) {
3150
4021
  const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
3151
- const data = encodeFunctionData10({
4022
+ const data = encodeFunctionData11({
3152
4023
  abi: POOL_ABI,
3153
4024
  functionName: "repay",
3154
4025
  args: [params.asset, params.amount, rateMode, params.on_behalf_of]
@@ -3158,11 +4029,12 @@ var AaveV3Adapter = class {
3158
4029
  to: this.pool,
3159
4030
  data,
3160
4031
  value: 0n,
3161
- gas_estimate: 3e5
4032
+ gas_estimate: 3e5,
4033
+ approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
3162
4034
  };
3163
4035
  }
3164
4036
  async buildWithdraw(params) {
3165
- const data = encodeFunctionData10({
4037
+ const data = encodeFunctionData11({
3166
4038
  abi: POOL_ABI,
3167
4039
  functionName: "withdraw",
3168
4040
  args: [params.asset, params.amount, params.to]
@@ -3177,15 +4049,21 @@ var AaveV3Adapter = class {
3177
4049
  }
3178
4050
  async getRates(asset) {
3179
4051
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
3180
- const client = createPublicClient7({ transport: http7(this.rpcUrl) });
3181
- const result = await client.readContract({
3182
- address: this.pool,
4052
+ const reserveCallData = encodeFunctionData11({
3183
4053
  abi: POOL_ABI,
3184
4054
  functionName: "getReserveData",
3185
4055
  args: [asset]
3186
- }).catch((e) => {
4056
+ });
4057
+ const [reserveRaw] = await multicallRead(this.rpcUrl, [
4058
+ [this.pool, reserveCallData]
4059
+ ]).catch((e) => {
3187
4060
  throw DefiError.rpcError(`[${this.protocolName}] getReserveData failed: ${e}`);
3188
4061
  });
4062
+ const reserveDecoded = decodeReserveData(reserveRaw ?? null);
4063
+ if (!reserveDecoded) {
4064
+ throw DefiError.rpcError(`[${this.protocolName}] getReserveData returned no data`);
4065
+ }
4066
+ const result = reserveDecoded;
3189
4067
  const RAY = 1e27;
3190
4068
  const SECONDS_PER_YEAR4 = 31536e3;
3191
4069
  const toApy = (rayRate) => {
@@ -3197,74 +4075,56 @@ var AaveV3Adapter = class {
3197
4075
  const stableRate = toApy(result[5]);
3198
4076
  const aTokenAddress = result[8];
3199
4077
  const variableDebtTokenAddress = result[10];
3200
- const [totalSupply, totalBorrow] = await Promise.all([
3201
- client.readContract({
3202
- address: aTokenAddress,
3203
- abi: ERC20_ABI,
3204
- functionName: "totalSupply"
3205
- }).catch(() => 0n),
3206
- client.readContract({
3207
- address: variableDebtTokenAddress,
3208
- abi: ERC20_ABI,
3209
- functionName: "totalSupply"
3210
- }).catch(() => 0n)
4078
+ const [supplyRaw, borrowRaw] = await multicallRead(this.rpcUrl, [
4079
+ [aTokenAddress, encodeFunctionData11({ abi: ERC20_ABI2, functionName: "totalSupply" })],
4080
+ [variableDebtTokenAddress, encodeFunctionData11({ abi: ERC20_ABI2, functionName: "totalSupply" })]
3211
4081
  ]);
4082
+ const totalSupply = decodeU256(supplyRaw ?? null);
4083
+ const totalBorrow = decodeU256(borrowRaw ?? null);
3212
4084
  const utilization = totalSupply > 0n ? Number(totalBorrow * 10000n / totalSupply) / 100 : 0;
3213
4085
  const supplyRewardTokens = [];
3214
4086
  const borrowRewardTokens = [];
3215
4087
  const supplyEmissions = [];
3216
4088
  const borrowEmissions = [];
3217
4089
  try {
3218
- const controllerAddr = await client.readContract({
3219
- address: aTokenAddress,
3220
- abi: INCENTIVES_ABI,
3221
- functionName: "getIncentivesController"
3222
- });
4090
+ const [controllerRaw] = await multicallRead(this.rpcUrl, [
4091
+ [aTokenAddress, encodeFunctionData11({ abi: INCENTIVES_ABI, functionName: "getIncentivesController" })]
4092
+ ]);
4093
+ const controllerAddr = decodeAddress(controllerRaw ?? null);
3223
4094
  if (controllerAddr && controllerAddr !== zeroAddress5) {
3224
- const [supplyRewards, borrowRewards] = await Promise.all([
3225
- client.readContract({
3226
- address: controllerAddr,
3227
- abi: REWARDS_CONTROLLER_ABI,
3228
- functionName: "getRewardsByAsset",
3229
- args: [aTokenAddress]
3230
- }).catch(() => []),
3231
- client.readContract({
3232
- address: controllerAddr,
3233
- abi: REWARDS_CONTROLLER_ABI,
3234
- functionName: "getRewardsByAsset",
3235
- args: [variableDebtTokenAddress]
3236
- }).catch(() => [])
4095
+ const [supplyRewardsRaw, borrowRewardsRaw] = await multicallRead(this.rpcUrl, [
4096
+ [controllerAddr, encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [aTokenAddress] })],
4097
+ [controllerAddr, encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [variableDebtTokenAddress] })]
3237
4098
  ]);
3238
- const supplyDataPromises = supplyRewards.map(
3239
- (reward) => client.readContract({
3240
- address: controllerAddr,
3241
- abi: REWARDS_CONTROLLER_ABI,
3242
- functionName: "getRewardsData",
3243
- args: [aTokenAddress, reward]
3244
- }).catch(() => null)
3245
- );
3246
- const supplyData = await Promise.all(supplyDataPromises);
3247
- for (let i = 0; i < supplyRewards.length; i++) {
3248
- const data = supplyData[i];
3249
- if (data && data[1] > 0n) {
3250
- supplyRewardTokens.push(supplyRewards[i]);
3251
- supplyEmissions.push(data[1].toString());
4099
+ const supplyRewards = decodeAddressArray(supplyRewardsRaw ?? null);
4100
+ const borrowRewards = decodeAddressArray(borrowRewardsRaw ?? null);
4101
+ const rewardsDataCalls = [
4102
+ ...supplyRewards.map((reward) => [
4103
+ controllerAddr,
4104
+ encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [aTokenAddress, reward] })
4105
+ ]),
4106
+ ...borrowRewards.map((reward) => [
4107
+ controllerAddr,
4108
+ encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [variableDebtTokenAddress, reward] })
4109
+ ])
4110
+ ];
4111
+ if (rewardsDataCalls.length > 0) {
4112
+ const rewardsDataResults = await multicallRead(this.rpcUrl, rewardsDataCalls);
4113
+ const supplyDataResults = rewardsDataResults.slice(0, supplyRewards.length);
4114
+ const borrowDataResults = rewardsDataResults.slice(supplyRewards.length);
4115
+ for (let i = 0; i < supplyRewards.length; i++) {
4116
+ const data = decodeRewardsData(supplyDataResults[i] ?? null);
4117
+ if (data && data[1] > 0n) {
4118
+ supplyRewardTokens.push(supplyRewards[i]);
4119
+ supplyEmissions.push(data[1].toString());
4120
+ }
3252
4121
  }
3253
- }
3254
- const borrowDataPromises = borrowRewards.map(
3255
- (reward) => client.readContract({
3256
- address: controllerAddr,
3257
- abi: REWARDS_CONTROLLER_ABI,
3258
- functionName: "getRewardsData",
3259
- args: [variableDebtTokenAddress, reward]
3260
- }).catch(() => null)
3261
- );
3262
- const borrowData = await Promise.all(borrowDataPromises);
3263
- for (let i = 0; i < borrowRewards.length; i++) {
3264
- const data = borrowData[i];
3265
- if (data && data[1] > 0n) {
3266
- borrowRewardTokens.push(borrowRewards[i]);
3267
- borrowEmissions.push(data[1].toString());
4122
+ for (let i = 0; i < borrowRewards.length; i++) {
4123
+ const data = decodeRewardsData(borrowDataResults[i] ?? null);
4124
+ if (data && data[1] > 0n) {
4125
+ borrowRewardTokens.push(borrowRewards[i]);
4126
+ borrowEmissions.push(data[1].toString());
4127
+ }
3268
4128
  }
3269
4129
  }
3270
4130
  }
@@ -3276,55 +4136,49 @@ var AaveV3Adapter = class {
3276
4136
  const hasBorrowRewards = borrowRewardTokens.length > 0;
3277
4137
  if ((hasSupplyRewards || hasBorrowRewards) && totalSupply > 0n) {
3278
4138
  try {
3279
- const providerAddr = await client.readContract({
3280
- address: this.pool,
3281
- abi: POOL_PROVIDER_ABI,
3282
- functionName: "ADDRESSES_PROVIDER"
3283
- });
3284
- const oracleAddr = await client.readContract({
3285
- address: providerAddr,
3286
- abi: ADDRESSES_PROVIDER_ABI,
3287
- functionName: "getPriceOracle"
3288
- });
3289
- const [assetPrice, baseCurrencyUnit, assetDecimals] = await Promise.all([
3290
- client.readContract({
3291
- address: oracleAddr,
3292
- abi: ORACLE_ABI,
3293
- functionName: "getAssetPrice",
3294
- args: [asset]
3295
- }),
3296
- client.readContract({
3297
- address: oracleAddr,
3298
- abi: ORACLE_ABI,
3299
- functionName: "BASE_CURRENCY_UNIT"
3300
- }),
3301
- client.readContract({
3302
- address: asset,
3303
- abi: ERC20_DECIMALS_ABI,
3304
- functionName: "decimals"
3305
- }).catch(() => 18)
4139
+ const [providerRaw] = await multicallRead(this.rpcUrl, [
4140
+ [this.pool, encodeFunctionData11({ abi: POOL_PROVIDER_ABI, functionName: "ADDRESSES_PROVIDER" })]
4141
+ ]);
4142
+ const providerAddr = decodeAddress(providerRaw ?? null);
4143
+ if (!providerAddr) throw new Error("No provider address");
4144
+ const [oracleRaw] = await multicallRead(this.rpcUrl, [
4145
+ [providerAddr, encodeFunctionData11({ abi: ADDRESSES_PROVIDER_ABI, functionName: "getPriceOracle" })]
4146
+ ]);
4147
+ const oracleAddr = decodeAddress(oracleRaw ?? null);
4148
+ if (!oracleAddr) throw new Error("No oracle address");
4149
+ const [assetPriceRaw, baseCurrencyUnitRaw, assetDecimalsRaw] = await multicallRead(this.rpcUrl, [
4150
+ [oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [asset] })],
4151
+ [oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "BASE_CURRENCY_UNIT" })],
4152
+ [asset, encodeFunctionData11({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
3306
4153
  ]);
3307
- const priceUnit = Number(baseCurrencyUnit);
4154
+ const assetPrice = decodeU256(assetPriceRaw ?? null);
4155
+ const baseCurrencyUnit = decodeU256(baseCurrencyUnitRaw ?? null);
4156
+ const assetDecimals = assetDecimalsRaw ? Number(decodeU256(assetDecimalsRaw)) : 18;
4157
+ const priceUnit = Number(baseCurrencyUnit) || 1e8;
3308
4158
  const assetPriceF = Number(assetPrice) / priceUnit;
3309
4159
  const assetDecimalsDivisor = 10 ** assetDecimals;
4160
+ const allRewardTokens = Array.from(/* @__PURE__ */ new Set([...supplyRewardTokens, ...borrowRewardTokens]));
4161
+ const rewardPriceCalls = allRewardTokens.flatMap((token) => [
4162
+ [oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [token] })],
4163
+ [token, encodeFunctionData11({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
4164
+ ]);
4165
+ const rewardPriceResults = rewardPriceCalls.length > 0 ? await multicallRead(this.rpcUrl, rewardPriceCalls) : [];
4166
+ const rewardPriceMap = /* @__PURE__ */ new Map();
4167
+ for (let i = 0; i < allRewardTokens.length; i++) {
4168
+ const priceRaw = rewardPriceResults[i * 2] ?? null;
4169
+ const decimalsRaw = rewardPriceResults[i * 2 + 1] ?? null;
4170
+ const price = decodeU256(priceRaw);
4171
+ const decimals = decimalsRaw ? Number(decodeU256(decimalsRaw)) : 18;
4172
+ rewardPriceMap.set(allRewardTokens[i].toLowerCase(), { price, decimals });
4173
+ }
3310
4174
  if (hasSupplyRewards) {
3311
4175
  let totalSupplyIncentiveUsdPerYear = 0;
3312
4176
  const totalSupplyUsd = Number(totalSupply) / assetDecimalsDivisor * assetPriceF;
3313
4177
  for (let i = 0; i < supplyRewardTokens.length; i++) {
3314
4178
  const emissionPerSec = BigInt(supplyEmissions[i]);
3315
- const [rewardPrice, rewardDecimals] = await Promise.all([
3316
- client.readContract({
3317
- address: oracleAddr,
3318
- abi: ORACLE_ABI,
3319
- functionName: "getAssetPrice",
3320
- args: [supplyRewardTokens[i]]
3321
- }).catch(() => 0n),
3322
- client.readContract({
3323
- address: supplyRewardTokens[i],
3324
- abi: ERC20_DECIMALS_ABI,
3325
- functionName: "decimals"
3326
- }).catch(() => 18)
3327
- ]);
4179
+ const entry = rewardPriceMap.get(supplyRewardTokens[i].toLowerCase());
4180
+ const rewardPrice = entry?.price ?? 0n;
4181
+ const rewardDecimals = entry?.decimals ?? 18;
3328
4182
  if (rewardPrice > 0n) {
3329
4183
  const rewardPriceF = Number(rewardPrice) / priceUnit;
3330
4184
  const emissionPerYear = Number(emissionPerSec) / 10 ** rewardDecimals * SECONDS_PER_YEAR4;
@@ -3340,19 +4194,9 @@ var AaveV3Adapter = class {
3340
4194
  const totalBorrowUsd = Number(totalBorrow) / assetDecimalsDivisor * assetPriceF;
3341
4195
  for (let i = 0; i < borrowRewardTokens.length; i++) {
3342
4196
  const emissionPerSec = BigInt(borrowEmissions[i]);
3343
- const [rewardPrice, rewardDecimals] = await Promise.all([
3344
- client.readContract({
3345
- address: oracleAddr,
3346
- abi: ORACLE_ABI,
3347
- functionName: "getAssetPrice",
3348
- args: [borrowRewardTokens[i]]
3349
- }).catch(() => 0n),
3350
- client.readContract({
3351
- address: borrowRewardTokens[i],
3352
- abi: ERC20_DECIMALS_ABI,
3353
- functionName: "decimals"
3354
- }).catch(() => 18)
3355
- ]);
4197
+ const entry = rewardPriceMap.get(borrowRewardTokens[i].toLowerCase());
4198
+ const rewardPrice = entry?.price ?? 0n;
4199
+ const rewardDecimals = entry?.decimals ?? 18;
3356
4200
  if (rewardPrice > 0n) {
3357
4201
  const rewardPriceF = Number(rewardPrice) / priceUnit;
3358
4202
  const emissionPerYear = Number(emissionPerSec) / 10 ** rewardDecimals * SECONDS_PER_YEAR4;
@@ -3416,7 +4260,7 @@ var AaveV3Adapter = class {
3416
4260
  };
3417
4261
  }
3418
4262
  };
3419
- var POOL_ABI2 = parseAbi11([
4263
+ var POOL_ABI2 = parseAbi12([
3420
4264
  "function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
3421
4265
  "function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
3422
4266
  "function repay(address asset, uint256 amount, uint256 rateMode, address onBehalfOf) external returns (uint256)",
@@ -3429,7 +4273,7 @@ var POOL_ABI2 = parseAbi11([
3429
4273
  // [9]=variableDebtTokenAddress, [10]=interestRateStrategyAddress, [11]=id
3430
4274
  "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)"
3431
4275
  ]);
3432
- var ERC20_ABI2 = parseAbi11([
4276
+ var ERC20_ABI22 = parseAbi12([
3433
4277
  "function totalSupply() external view returns (uint256)"
3434
4278
  ]);
3435
4279
  function u256ToF642(v) {
@@ -3452,7 +4296,7 @@ var AaveV2Adapter = class {
3452
4296
  return this.protocolName;
3453
4297
  }
3454
4298
  async buildSupply(params) {
3455
- const data = encodeFunctionData11({
4299
+ const data = encodeFunctionData12({
3456
4300
  abi: POOL_ABI2,
3457
4301
  functionName: "deposit",
3458
4302
  args: [params.asset, params.amount, params.on_behalf_of, 0]
@@ -3462,12 +4306,13 @@ var AaveV2Adapter = class {
3462
4306
  to: this.pool,
3463
4307
  data,
3464
4308
  value: 0n,
3465
- gas_estimate: 3e5
4309
+ gas_estimate: 3e5,
4310
+ approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
3466
4311
  };
3467
4312
  }
3468
4313
  async buildBorrow(params) {
3469
4314
  const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
3470
- const data = encodeFunctionData11({
4315
+ const data = encodeFunctionData12({
3471
4316
  abi: POOL_ABI2,
3472
4317
  functionName: "borrow",
3473
4318
  args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
@@ -3482,7 +4327,7 @@ var AaveV2Adapter = class {
3482
4327
  }
3483
4328
  async buildRepay(params) {
3484
4329
  const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
3485
- const data = encodeFunctionData11({
4330
+ const data = encodeFunctionData12({
3486
4331
  abi: POOL_ABI2,
3487
4332
  functionName: "repay",
3488
4333
  args: [params.asset, params.amount, rateMode, params.on_behalf_of]
@@ -3492,11 +4337,12 @@ var AaveV2Adapter = class {
3492
4337
  to: this.pool,
3493
4338
  data,
3494
4339
  value: 0n,
3495
- gas_estimate: 3e5
4340
+ gas_estimate: 3e5,
4341
+ approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
3496
4342
  };
3497
4343
  }
3498
4344
  async buildWithdraw(params) {
3499
- const data = encodeFunctionData11({
4345
+ const data = encodeFunctionData12({
3500
4346
  abi: POOL_ABI2,
3501
4347
  functionName: "withdraw",
3502
4348
  args: [params.asset, params.amount, params.to]
@@ -3534,12 +4380,12 @@ var AaveV2Adapter = class {
3534
4380
  const [totalSupply, totalBorrow] = await Promise.all([
3535
4381
  client.readContract({
3536
4382
  address: aTokenAddress,
3537
- abi: ERC20_ABI2,
4383
+ abi: ERC20_ABI22,
3538
4384
  functionName: "totalSupply"
3539
4385
  }).catch(() => 0n),
3540
4386
  client.readContract({
3541
4387
  address: variableDebtTokenAddress,
3542
- abi: ERC20_ABI2,
4388
+ abi: ERC20_ABI22,
3543
4389
  functionName: "totalSupply"
3544
4390
  }).catch(() => 0n)
3545
4391
  ]);
@@ -3584,7 +4430,7 @@ var AaveV2Adapter = class {
3584
4430
  };
3585
4431
  }
3586
4432
  };
3587
- var ORACLE_ABI2 = parseAbi12([
4433
+ var ORACLE_ABI2 = parseAbi13([
3588
4434
  "function getAssetPrice(address asset) external view returns (uint256)",
3589
4435
  "function getAssetsPrices(address[] calldata assets) external view returns (uint256[] memory)",
3590
4436
  "function BASE_CURRENCY_UNIT() external view returns (uint256)"
@@ -3661,7 +4507,7 @@ var AaveOracleAdapter = class {
3661
4507
  });
3662
4508
  }
3663
4509
  };
3664
- var CTOKEN_ABI = parseAbi13([
4510
+ var CTOKEN_ABI = parseAbi14([
3665
4511
  "function supplyRatePerBlock() external view returns (uint256)",
3666
4512
  "function borrowRatePerBlock() external view returns (uint256)",
3667
4513
  "function totalSupply() external view returns (uint256)",
@@ -3688,7 +4534,7 @@ var CompoundV2Adapter = class {
3688
4534
  return this.protocolName;
3689
4535
  }
3690
4536
  async buildSupply(params) {
3691
- const data = encodeFunctionData12({
4537
+ const data = encodeFunctionData13({
3692
4538
  abi: CTOKEN_ABI,
3693
4539
  functionName: "mint",
3694
4540
  args: [params.amount]
@@ -3702,7 +4548,7 @@ var CompoundV2Adapter = class {
3702
4548
  };
3703
4549
  }
3704
4550
  async buildBorrow(params) {
3705
- const data = encodeFunctionData12({
4551
+ const data = encodeFunctionData13({
3706
4552
  abi: CTOKEN_ABI,
3707
4553
  functionName: "borrow",
3708
4554
  args: [params.amount]
@@ -3716,7 +4562,7 @@ var CompoundV2Adapter = class {
3716
4562
  };
3717
4563
  }
3718
4564
  async buildRepay(params) {
3719
- const data = encodeFunctionData12({
4565
+ const data = encodeFunctionData13({
3720
4566
  abi: CTOKEN_ABI,
3721
4567
  functionName: "repayBorrow",
3722
4568
  args: [params.amount]
@@ -3730,7 +4576,7 @@ var CompoundV2Adapter = class {
3730
4576
  };
3731
4577
  }
3732
4578
  async buildWithdraw(params) {
3733
- const data = encodeFunctionData12({
4579
+ const data = encodeFunctionData13({
3734
4580
  abi: CTOKEN_ABI,
3735
4581
  functionName: "redeem",
3736
4582
  args: [params.amount]
@@ -3779,7 +4625,7 @@ var CompoundV2Adapter = class {
3779
4625
  );
3780
4626
  }
3781
4627
  };
3782
- var COMET_ABI = parseAbi14([
4628
+ var COMET_ABI = parseAbi15([
3783
4629
  "function getUtilization() external view returns (uint256)",
3784
4630
  "function getSupplyRate(uint256 utilization) external view returns (uint64)",
3785
4631
  "function getBorrowRate(uint256 utilization) external view returns (uint64)",
@@ -3805,7 +4651,7 @@ var CompoundV3Adapter = class {
3805
4651
  return this.protocolName;
3806
4652
  }
3807
4653
  async buildSupply(params) {
3808
- const data = encodeFunctionData13({
4654
+ const data = encodeFunctionData14({
3809
4655
  abi: COMET_ABI,
3810
4656
  functionName: "supply",
3811
4657
  args: [params.asset, params.amount]
@@ -3819,7 +4665,7 @@ var CompoundV3Adapter = class {
3819
4665
  };
3820
4666
  }
3821
4667
  async buildBorrow(params) {
3822
- const data = encodeFunctionData13({
4668
+ const data = encodeFunctionData14({
3823
4669
  abi: COMET_ABI,
3824
4670
  functionName: "withdraw",
3825
4671
  args: [params.asset, params.amount]
@@ -3833,7 +4679,7 @@ var CompoundV3Adapter = class {
3833
4679
  };
3834
4680
  }
3835
4681
  async buildRepay(params) {
3836
- const data = encodeFunctionData13({
4682
+ const data = encodeFunctionData14({
3837
4683
  abi: COMET_ABI,
3838
4684
  functionName: "supply",
3839
4685
  args: [params.asset, params.amount]
@@ -3847,7 +4693,7 @@ var CompoundV3Adapter = class {
3847
4693
  };
3848
4694
  }
3849
4695
  async buildWithdraw(params) {
3850
- const data = encodeFunctionData13({
4696
+ const data = encodeFunctionData14({
3851
4697
  abi: COMET_ABI,
3852
4698
  functionName: "withdraw",
3853
4699
  args: [params.asset, params.amount]
@@ -3901,7 +4747,7 @@ var CompoundV3Adapter = class {
3901
4747
  );
3902
4748
  }
3903
4749
  };
3904
- var EULER_VAULT_ABI = parseAbi15([
4750
+ var EULER_VAULT_ABI = parseAbi16([
3905
4751
  "function deposit(uint256 amount, address receiver) external returns (uint256)",
3906
4752
  "function withdraw(uint256 amount, address receiver, address owner) external returns (uint256)",
3907
4753
  "function borrow(uint256 amount, address receiver) external returns (uint256)",
@@ -3927,7 +4773,7 @@ var EulerV2Adapter = class {
3927
4773
  return this.protocolName;
3928
4774
  }
3929
4775
  async buildSupply(params) {
3930
- const data = encodeFunctionData14({
4776
+ const data = encodeFunctionData15({
3931
4777
  abi: EULER_VAULT_ABI,
3932
4778
  functionName: "deposit",
3933
4779
  args: [params.amount, params.on_behalf_of]
@@ -3941,7 +4787,7 @@ var EulerV2Adapter = class {
3941
4787
  };
3942
4788
  }
3943
4789
  async buildBorrow(params) {
3944
- const data = encodeFunctionData14({
4790
+ const data = encodeFunctionData15({
3945
4791
  abi: EULER_VAULT_ABI,
3946
4792
  functionName: "borrow",
3947
4793
  args: [params.amount, params.on_behalf_of]
@@ -3955,7 +4801,7 @@ var EulerV2Adapter = class {
3955
4801
  };
3956
4802
  }
3957
4803
  async buildRepay(params) {
3958
- const data = encodeFunctionData14({
4804
+ const data = encodeFunctionData15({
3959
4805
  abi: EULER_VAULT_ABI,
3960
4806
  functionName: "repay",
3961
4807
  args: [params.amount, params.on_behalf_of]
@@ -3969,7 +4815,7 @@ var EulerV2Adapter = class {
3969
4815
  };
3970
4816
  }
3971
4817
  async buildWithdraw(params) {
3972
- const data = encodeFunctionData14({
4818
+ const data = encodeFunctionData15({
3973
4819
  abi: EULER_VAULT_ABI,
3974
4820
  functionName: "withdraw",
3975
4821
  args: [params.amount, params.to, params.to]
@@ -4018,7 +4864,7 @@ var EulerV2Adapter = class {
4018
4864
  );
4019
4865
  }
4020
4866
  };
4021
- var MORPHO_ABI = parseAbi16([
4867
+ var MORPHO_ABI = parseAbi17([
4022
4868
  "function market(bytes32 id) external view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)",
4023
4869
  "function idToMarketParams(bytes32 id) external view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)",
4024
4870
  "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)",
@@ -4026,13 +4872,13 @@ var MORPHO_ABI = parseAbi16([
4026
4872
  "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)",
4027
4873
  "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)"
4028
4874
  ]);
4029
- var META_MORPHO_ABI = parseAbi16([
4875
+ var META_MORPHO_ABI = parseAbi17([
4030
4876
  "function supplyQueueLength() external view returns (uint256)",
4031
4877
  "function supplyQueue(uint256 index) external view returns (bytes32)",
4032
4878
  "function totalAssets() external view returns (uint256)",
4033
4879
  "function totalSupply() external view returns (uint256)"
4034
4880
  ]);
4035
- var IRM_ABI = parseAbi16([
4881
+ var IRM_ABI = parseAbi17([
4036
4882
  "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)"
4037
4883
  ]);
4038
4884
  var SECONDS_PER_YEAR3 = 365.25 * 24 * 3600;
@@ -4045,6 +4891,30 @@ function defaultMarketParams(loanToken = zeroAddress7) {
4045
4891
  lltv: 0n
4046
4892
  };
4047
4893
  }
4894
+ function decodeMarket(data) {
4895
+ if (!data) return null;
4896
+ try {
4897
+ return decodeFunctionResult4({
4898
+ abi: MORPHO_ABI,
4899
+ functionName: "market",
4900
+ data
4901
+ });
4902
+ } catch {
4903
+ return null;
4904
+ }
4905
+ }
4906
+ function decodeMarketParams(data) {
4907
+ if (!data) return null;
4908
+ try {
4909
+ return decodeFunctionResult4({
4910
+ abi: MORPHO_ABI,
4911
+ functionName: "idToMarketParams",
4912
+ data
4913
+ });
4914
+ } catch {
4915
+ return null;
4916
+ }
4917
+ }
4048
4918
  var MorphoBlueAdapter = class {
4049
4919
  protocolName;
4050
4920
  morpho;
@@ -4064,7 +4934,7 @@ var MorphoBlueAdapter = class {
4064
4934
  }
4065
4935
  async buildSupply(params) {
4066
4936
  const market = defaultMarketParams(params.asset);
4067
- const data = encodeFunctionData15({
4937
+ const data = encodeFunctionData16({
4068
4938
  abi: MORPHO_ABI,
4069
4939
  functionName: "supply",
4070
4940
  args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
@@ -4079,7 +4949,7 @@ var MorphoBlueAdapter = class {
4079
4949
  }
4080
4950
  async buildBorrow(params) {
4081
4951
  const market = defaultMarketParams(params.asset);
4082
- const data = encodeFunctionData15({
4952
+ const data = encodeFunctionData16({
4083
4953
  abi: MORPHO_ABI,
4084
4954
  functionName: "borrow",
4085
4955
  args: [market, params.amount, 0n, params.on_behalf_of, params.on_behalf_of]
@@ -4094,7 +4964,7 @@ var MorphoBlueAdapter = class {
4094
4964
  }
4095
4965
  async buildRepay(params) {
4096
4966
  const market = defaultMarketParams(params.asset);
4097
- const data = encodeFunctionData15({
4967
+ const data = encodeFunctionData16({
4098
4968
  abi: MORPHO_ABI,
4099
4969
  functionName: "repay",
4100
4970
  args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
@@ -4109,7 +4979,7 @@ var MorphoBlueAdapter = class {
4109
4979
  }
4110
4980
  async buildWithdraw(params) {
4111
4981
  const market = defaultMarketParams(params.asset);
4112
- const data = encodeFunctionData15({
4982
+ const data = encodeFunctionData16({
4113
4983
  abi: MORPHO_ABI,
4114
4984
  functionName: "withdraw",
4115
4985
  args: [market, params.amount, 0n, params.to, params.to]
@@ -4127,14 +4997,12 @@ var MorphoBlueAdapter = class {
4127
4997
  if (!this.defaultVault) {
4128
4998
  throw DefiError.contractError(`[${this.protocolName}] No MetaMorpho vault configured for rate query`);
4129
4999
  }
4130
- const client = createPublicClient13({ transport: http13(this.rpcUrl) });
4131
- const queueLen = await client.readContract({
4132
- address: this.defaultVault,
4133
- abi: META_MORPHO_ABI,
4134
- functionName: "supplyQueueLength"
4135
- }).catch((e) => {
5000
+ const [queueLenRaw] = await multicallRead(this.rpcUrl, [
5001
+ [this.defaultVault, encodeFunctionData16({ abi: META_MORPHO_ABI, functionName: "supplyQueueLength" })]
5002
+ ]).catch((e) => {
4136
5003
  throw DefiError.rpcError(`[${this.protocolName}] supplyQueueLength failed: ${e}`);
4137
5004
  });
5005
+ const queueLen = decodeU256(queueLenRaw ?? null);
4138
5006
  if (queueLen === 0n) {
4139
5007
  return {
4140
5008
  protocol: this.protocolName,
@@ -4146,45 +5014,40 @@ var MorphoBlueAdapter = class {
4146
5014
  total_borrow: 0n
4147
5015
  };
4148
5016
  }
4149
- const marketId = await client.readContract({
4150
- address: this.defaultVault,
4151
- abi: META_MORPHO_ABI,
4152
- functionName: "supplyQueue",
4153
- args: [0n]
4154
- }).catch((e) => {
5017
+ const [marketIdRaw] = await multicallRead(this.rpcUrl, [
5018
+ [this.defaultVault, encodeFunctionData16({ abi: META_MORPHO_ABI, functionName: "supplyQueue", args: [0n] })]
5019
+ ]).catch((e) => {
4155
5020
  throw DefiError.rpcError(`[${this.protocolName}] supplyQueue(0) failed: ${e}`);
4156
5021
  });
4157
- const mkt = await client.readContract({
4158
- address: this.morpho,
4159
- abi: MORPHO_ABI,
4160
- functionName: "market",
4161
- args: [marketId]
4162
- }).catch((e) => {
4163
- throw DefiError.rpcError(`[${this.protocolName}] market() failed: ${e}`);
5022
+ if (!marketIdRaw || marketIdRaw.length < 66) {
5023
+ throw DefiError.rpcError(`[${this.protocolName}] supplyQueue(0) returned no data`);
5024
+ }
5025
+ const marketId = marketIdRaw.slice(0, 66);
5026
+ const [marketRaw, paramsRaw] = await multicallRead(this.rpcUrl, [
5027
+ [this.morpho, encodeFunctionData16({ abi: MORPHO_ABI, functionName: "market", args: [marketId] })],
5028
+ [this.morpho, encodeFunctionData16({ abi: MORPHO_ABI, functionName: "idToMarketParams", args: [marketId] })]
5029
+ ]).catch((e) => {
5030
+ throw DefiError.rpcError(`[${this.protocolName}] market/idToMarketParams failed: ${e}`);
4164
5031
  });
4165
- const [totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee] = mkt;
5032
+ const mktDecoded = decodeMarket(marketRaw ?? null);
5033
+ if (!mktDecoded) throw DefiError.rpcError(`[${this.protocolName}] market() returned no data`);
5034
+ const [totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee] = mktDecoded;
5035
+ const paramsDecoded = decodeMarketParams(paramsRaw ?? null);
5036
+ if (!paramsDecoded) throw DefiError.rpcError(`[${this.protocolName}] idToMarketParams returned no data`);
5037
+ const [loanToken, collateralToken, oracle, irm, lltv] = paramsDecoded;
4166
5038
  const supplyF = Number(totalSupplyAssets);
4167
5039
  const borrowF = Number(totalBorrowAssets);
4168
5040
  const util = supplyF > 0 ? borrowF / supplyF : 0;
4169
- const params2 = await client.readContract({
4170
- address: this.morpho,
4171
- abi: MORPHO_ABI,
4172
- functionName: "idToMarketParams",
4173
- args: [marketId]
4174
- }).catch((e) => {
4175
- throw DefiError.rpcError(`[${this.protocolName}] idToMarketParams failed: ${e}`);
4176
- });
4177
- const [loanToken, collateralToken, oracle, irm, lltv] = params2;
4178
5041
  const irmMarketParams = { loanToken, collateralToken, oracle, irm, lltv };
4179
5042
  const irmMarket = { totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee };
4180
- const borrowRatePerSec = await client.readContract({
4181
- address: irm,
4182
- abi: IRM_ABI,
4183
- functionName: "borrowRateView",
4184
- args: [irmMarketParams, irmMarket]
4185
- }).catch((e) => {
4186
- throw DefiError.rpcError(`[${this.protocolName}] borrowRateView failed: ${e}`);
4187
- });
5043
+ const borrowRatePerSec = await (async () => {
5044
+ const [borrowRateRaw] = await multicallRead(this.rpcUrl, [
5045
+ [irm, encodeFunctionData16({ abi: IRM_ABI, functionName: "borrowRateView", args: [irmMarketParams, irmMarket] })]
5046
+ ]).catch((e) => {
5047
+ throw DefiError.rpcError(`[${this.protocolName}] borrowRateView failed: ${e}`);
5048
+ });
5049
+ return decodeU256(borrowRateRaw ?? null);
5050
+ })();
4188
5051
  const ratePerSec = Number(borrowRatePerSec) / 1e18;
4189
5052
  const borrowApy = ratePerSec * SECONDS_PER_YEAR3 * 100;
4190
5053
  const feePct = Number(fee) / 1e18;
@@ -4205,18 +5068,18 @@ var MorphoBlueAdapter = class {
4205
5068
  );
4206
5069
  }
4207
5070
  };
4208
- var BORROWER_OPS_ABI = parseAbi17([
5071
+ var BORROWER_OPS_ABI = parseAbi18([
4209
5072
  "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)",
4210
5073
  "function adjustTrove(uint256 _troveId, uint256 _collChange, bool _isCollIncrease, uint256 _debtChange, bool _isDebtIncrease, uint256 _upperHint, uint256 _lowerHint, uint256 _maxUpfrontFee) external",
4211
5074
  "function closeTrove(uint256 _troveId) external"
4212
5075
  ]);
4213
- var TROVE_MANAGER_ABI = parseAbi17([
5076
+ var TROVE_MANAGER_ABI = parseAbi18([
4214
5077
  "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)"
4215
5078
  ]);
4216
- var HINT_HELPERS_ABI = parseAbi17([
5079
+ var HINT_HELPERS_ABI = parseAbi18([
4217
5080
  "function getApproxHint(uint256 _collIndex, uint256 _interestRate, uint256 _numTrials, uint256 _inputRandomSeed) external view returns (uint256 hintId, uint256 diff, uint256 latestRandomSeed)"
4218
5081
  ]);
4219
- var SORTED_TROVES_ABI = parseAbi17([
5082
+ var SORTED_TROVES_ABI = parseAbi18([
4220
5083
  "function findInsertPosition(uint256 _annualInterestRate, uint256 _prevId, uint256 _nextId) external view returns (uint256 prevId, uint256 nextId)"
4221
5084
  ]);
4222
5085
  var FelixCdpAdapter = class {
@@ -4244,7 +5107,7 @@ var FelixCdpAdapter = class {
4244
5107
  if (!this.hintHelpers || !this.sortedTroves || !this.rpcUrl) {
4245
5108
  return [0n, 0n];
4246
5109
  }
4247
- const client = createPublicClient14({ transport: http14(this.rpcUrl) });
5110
+ const client = createPublicClient13({ transport: http13(this.rpcUrl) });
4248
5111
  const approxResult = await client.readContract({
4249
5112
  address: this.hintHelpers,
4250
5113
  abi: HINT_HELPERS_ABI,
@@ -4267,7 +5130,7 @@ var FelixCdpAdapter = class {
4267
5130
  const interestRate = 50000000000000000n;
4268
5131
  const [upperHint, lowerHint] = await this.getHints(interestRate);
4269
5132
  const hasHints = upperHint !== 0n || lowerHint !== 0n;
4270
- const data = encodeFunctionData16({
5133
+ const data = encodeFunctionData17({
4271
5134
  abi: BORROWER_OPS_ABI,
4272
5135
  functionName: "openTrove",
4273
5136
  args: [
@@ -4296,7 +5159,7 @@ var FelixCdpAdapter = class {
4296
5159
  async buildAdjust(params) {
4297
5160
  const collChange = params.collateral_delta ?? 0n;
4298
5161
  const debtChange = params.debt_delta ?? 0n;
4299
- const data = encodeFunctionData16({
5162
+ const data = encodeFunctionData17({
4300
5163
  abi: BORROWER_OPS_ABI,
4301
5164
  functionName: "adjustTrove",
4302
5165
  args: [
@@ -4319,7 +5182,7 @@ var FelixCdpAdapter = class {
4319
5182
  };
4320
5183
  }
4321
5184
  async buildClose(params) {
4322
- const data = encodeFunctionData16({
5185
+ const data = encodeFunctionData17({
4323
5186
  abi: BORROWER_OPS_ABI,
4324
5187
  functionName: "closeTrove",
4325
5188
  args: [params.cdp_id]
@@ -4335,7 +5198,7 @@ var FelixCdpAdapter = class {
4335
5198
  async getCdpInfo(cdpId) {
4336
5199
  if (!this.rpcUrl) throw DefiError.rpcError(`[${this.protocolName}] getCdpInfo requires RPC \u2014 set HYPEREVM_RPC_URL`);
4337
5200
  if (!this.troveManager) throw DefiError.contractError(`[${this.protocolName}] trove_manager contract not configured`);
4338
- const client = createPublicClient14({ transport: http14(this.rpcUrl) });
5201
+ const client = createPublicClient13({ transport: http13(this.rpcUrl) });
4339
5202
  const data = await client.readContract({
4340
5203
  address: this.troveManager,
4341
5204
  abi: TROVE_MANAGER_ABI,
@@ -4368,7 +5231,7 @@ var FelixCdpAdapter = class {
4368
5231
  };
4369
5232
  }
4370
5233
  };
4371
- var PRICE_FEED_ABI = parseAbi18([
5234
+ var PRICE_FEED_ABI = parseAbi19([
4372
5235
  "function fetchPrice() external view returns (uint256 price, bool isNewOracleFailureDetected)",
4373
5236
  "function lastGoodPrice() external view returns (uint256)"
4374
5237
  ]);
@@ -4394,7 +5257,7 @@ var FelixOracleAdapter = class {
4394
5257
  if (asset !== this.asset && this.asset !== "0x0000000000000000000000000000000000000000") {
4395
5258
  throw DefiError.unsupported(`[${this.protocolName}] Felix PriceFeed only supports asset ${this.asset}`);
4396
5259
  }
4397
- const client = createPublicClient15({ transport: http15(this.rpcUrl) });
5260
+ const client = createPublicClient14({ transport: http14(this.rpcUrl) });
4398
5261
  let priceVal;
4399
5262
  try {
4400
5263
  const result = await client.readContract({
@@ -4433,7 +5296,7 @@ var FelixOracleAdapter = class {
4433
5296
  return results;
4434
5297
  }
4435
5298
  };
4436
- var ERC4626_ABI = parseAbi19([
5299
+ var ERC4626_ABI = parseAbi20([
4437
5300
  "function asset() external view returns (address)",
4438
5301
  "function totalAssets() external view returns (uint256)",
4439
5302
  "function totalSupply() external view returns (uint256)",
@@ -4457,7 +5320,7 @@ var ERC4626VaultAdapter = class {
4457
5320
  return this.protocolName;
4458
5321
  }
4459
5322
  async buildDeposit(assets, receiver) {
4460
- const data = encodeFunctionData17({
5323
+ const data = encodeFunctionData18({
4461
5324
  abi: ERC4626_ABI,
4462
5325
  functionName: "deposit",
4463
5326
  args: [assets, receiver]
@@ -4471,7 +5334,7 @@ var ERC4626VaultAdapter = class {
4471
5334
  };
4472
5335
  }
4473
5336
  async buildWithdraw(assets, receiver, owner) {
4474
- const data = encodeFunctionData17({
5337
+ const data = encodeFunctionData18({
4475
5338
  abi: ERC4626_ABI,
4476
5339
  functionName: "withdraw",
4477
5340
  args: [assets, receiver, owner]
@@ -4486,7 +5349,7 @@ var ERC4626VaultAdapter = class {
4486
5349
  }
4487
5350
  async totalAssets() {
4488
5351
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4489
- const client = createPublicClient16({ transport: http16(this.rpcUrl) });
5352
+ const client = createPublicClient15({ transport: http15(this.rpcUrl) });
4490
5353
  return client.readContract({
4491
5354
  address: this.vaultAddress,
4492
5355
  abi: ERC4626_ABI,
@@ -4497,7 +5360,7 @@ var ERC4626VaultAdapter = class {
4497
5360
  }
4498
5361
  async convertToShares(assets) {
4499
5362
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4500
- const client = createPublicClient16({ transport: http16(this.rpcUrl) });
5363
+ const client = createPublicClient15({ transport: http15(this.rpcUrl) });
4501
5364
  return client.readContract({
4502
5365
  address: this.vaultAddress,
4503
5366
  abi: ERC4626_ABI,
@@ -4509,7 +5372,7 @@ var ERC4626VaultAdapter = class {
4509
5372
  }
4510
5373
  async convertToAssets(shares) {
4511
5374
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4512
- const client = createPublicClient16({ transport: http16(this.rpcUrl) });
5375
+ const client = createPublicClient15({ transport: http15(this.rpcUrl) });
4513
5376
  return client.readContract({
4514
5377
  address: this.vaultAddress,
4515
5378
  abi: ERC4626_ABI,
@@ -4521,7 +5384,7 @@ var ERC4626VaultAdapter = class {
4521
5384
  }
4522
5385
  async getVaultInfo() {
4523
5386
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4524
- const client = createPublicClient16({ transport: http16(this.rpcUrl) });
5387
+ const client = createPublicClient15({ transport: http15(this.rpcUrl) });
4525
5388
  const [totalAssets, totalSupply, asset] = await Promise.all([
4526
5389
  client.readContract({ address: this.vaultAddress, abi: ERC4626_ABI, functionName: "totalAssets" }).catch((e) => {
4527
5390
  throw DefiError.rpcError(`[${this.protocolName}] totalAssets failed: ${e}`);
@@ -4542,7 +5405,7 @@ var ERC4626VaultAdapter = class {
4542
5405
  };
4543
5406
  }
4544
5407
  };
4545
- var GENERIC_LST_ABI = parseAbi20([
5408
+ var GENERIC_LST_ABI = parseAbi21([
4546
5409
  "function stake() external payable returns (uint256)",
4547
5410
  "function unstake(uint256 amount) external returns (uint256)"
4548
5411
  ]);
@@ -4559,7 +5422,7 @@ var GenericLstAdapter = class {
4559
5422
  return this.protocolName;
4560
5423
  }
4561
5424
  async buildStake(params) {
4562
- const data = encodeFunctionData18({ abi: GENERIC_LST_ABI, functionName: "stake" });
5425
+ const data = encodeFunctionData19({ abi: GENERIC_LST_ABI, functionName: "stake" });
4563
5426
  return {
4564
5427
  description: `[${this.protocolName}] Stake ${params.amount} HYPE`,
4565
5428
  to: this.staking,
@@ -4569,7 +5432,7 @@ var GenericLstAdapter = class {
4569
5432
  };
4570
5433
  }
4571
5434
  async buildUnstake(params) {
4572
- const data = encodeFunctionData18({
5435
+ const data = encodeFunctionData19({
4573
5436
  abi: GENERIC_LST_ABI,
4574
5437
  functionName: "unstake",
4575
5438
  args: [params.amount]
@@ -4586,11 +5449,11 @@ var GenericLstAdapter = class {
4586
5449
  throw DefiError.unsupported(`[${this.protocolName}] getInfo requires RPC`);
4587
5450
  }
4588
5451
  };
4589
- var STHYPE_ABI = parseAbi21([
5452
+ var STHYPE_ABI = parseAbi222([
4590
5453
  "function submit(address referral) external payable returns (uint256)",
4591
5454
  "function requestWithdrawals(uint256[] amounts, address owner) external returns (uint256[] requestIds)"
4592
5455
  ]);
4593
- var ERC20_ABI3 = parseAbi21([
5456
+ var ERC20_ABI3 = parseAbi222([
4594
5457
  "function totalSupply() external view returns (uint256)"
4595
5458
  ]);
4596
5459
  var StHypeAdapter = class {
@@ -4610,7 +5473,7 @@ var StHypeAdapter = class {
4610
5473
  return this.protocolName;
4611
5474
  }
4612
5475
  async buildStake(params) {
4613
- const data = encodeFunctionData19({
5476
+ const data = encodeFunctionData20({
4614
5477
  abi: STHYPE_ABI,
4615
5478
  functionName: "submit",
4616
5479
  args: [zeroAddress9]
@@ -4624,7 +5487,7 @@ var StHypeAdapter = class {
4624
5487
  };
4625
5488
  }
4626
5489
  async buildUnstake(params) {
4627
- const data = encodeFunctionData19({
5490
+ const data = encodeFunctionData20({
4628
5491
  abi: STHYPE_ABI,
4629
5492
  functionName: "requestWithdrawals",
4630
5493
  args: [[params.amount], params.recipient]
@@ -4639,7 +5502,7 @@ var StHypeAdapter = class {
4639
5502
  }
4640
5503
  async getInfo() {
4641
5504
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4642
- const client = createPublicClient17({ transport: http17(this.rpcUrl) });
5505
+ const client = createPublicClient16({ transport: http16(this.rpcUrl) });
4643
5506
  const tokenAddr = this.sthypeToken ?? this.staking;
4644
5507
  const totalSupply = await client.readContract({
4645
5508
  address: tokenAddr,
@@ -4657,12 +5520,12 @@ var StHypeAdapter = class {
4657
5520
  };
4658
5521
  }
4659
5522
  };
4660
- var KINETIQ_ABI = parseAbi222([
5523
+ var KINETIQ_ABI = parseAbi23([
4661
5524
  "function stake() external payable returns (uint256)",
4662
5525
  "function requestUnstake(uint256 amount) external returns (uint256)",
4663
5526
  "function totalStaked() external view returns (uint256)"
4664
5527
  ]);
4665
- var ORACLE_ABI3 = parseAbi222([
5528
+ var ORACLE_ABI3 = parseAbi23([
4666
5529
  "function getAssetPrice(address asset) external view returns (uint256)"
4667
5530
  ]);
4668
5531
  var WHYPE = "0x5555555555555555555555555555555555555555";
@@ -4684,7 +5547,7 @@ var KinetiqAdapter = class {
4684
5547
  return this.protocolName;
4685
5548
  }
4686
5549
  async buildStake(params) {
4687
- const data = encodeFunctionData20({ abi: KINETIQ_ABI, functionName: "stake" });
5550
+ const data = encodeFunctionData21({ abi: KINETIQ_ABI, functionName: "stake" });
4688
5551
  return {
4689
5552
  description: `[${this.protocolName}] Stake ${params.amount} HYPE for kHYPE`,
4690
5553
  to: this.staking,
@@ -4694,7 +5557,7 @@ var KinetiqAdapter = class {
4694
5557
  };
4695
5558
  }
4696
5559
  async buildUnstake(params) {
4697
- const data = encodeFunctionData20({
5560
+ const data = encodeFunctionData21({
4698
5561
  abi: KINETIQ_ABI,
4699
5562
  functionName: "requestUnstake",
4700
5563
  args: [params.amount]
@@ -4709,7 +5572,7 @@ var KinetiqAdapter = class {
4709
5572
  }
4710
5573
  async getInfo() {
4711
5574
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4712
- const client = createPublicClient18({ transport: http18(this.rpcUrl) });
5575
+ const client = createPublicClient17({ transport: http17(this.rpcUrl) });
4713
5576
  const totalStaked = await client.readContract({
4714
5577
  address: this.staking,
4715
5578
  abi: KINETIQ_ABI,
@@ -4731,15 +5594,15 @@ var KinetiqAdapter = class {
4731
5594
  };
4732
5595
  }
4733
5596
  };
4734
- var HLP_ABI = parseAbi23([
5597
+ var HLP_ABI = parseAbi24([
4735
5598
  "function deposit(uint256 amount) external returns (uint256)",
4736
5599
  "function withdraw(uint256 shares) external returns (uint256)"
4737
5600
  ]);
4738
- var RYSK_ABI = parseAbi24([
5601
+ var RYSK_ABI = parseAbi25([
4739
5602
  "function openOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 premium)",
4740
5603
  "function closeOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 payout)"
4741
5604
  ]);
4742
- var ERC721_ABI = parseAbi25([
5605
+ var ERC721_ABI = parseAbi26([
4743
5606
  "function name() returns (string)",
4744
5607
  "function symbol() returns (string)",
4745
5608
  "function totalSupply() returns (uint256)",
@@ -4759,7 +5622,7 @@ var ERC721Adapter = class {
4759
5622
  }
4760
5623
  async getCollectionInfo(collection) {
4761
5624
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4762
- const client = createPublicClient19({ transport: http19(this.rpcUrl) });
5625
+ const client = createPublicClient18({ transport: http18(this.rpcUrl) });
4763
5626
  const [collectionName, symbol, totalSupply] = await Promise.all([
4764
5627
  client.readContract({ address: collection, abi: ERC721_ABI, functionName: "name" }).catch((e) => {
4765
5628
  throw DefiError.rpcError(`[${this.protocolName}] name failed: ${e}`);
@@ -4778,7 +5641,7 @@ var ERC721Adapter = class {
4778
5641
  }
4779
5642
  async getTokenInfo(collection, tokenId) {
4780
5643
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4781
- const client = createPublicClient19({ transport: http19(this.rpcUrl) });
5644
+ const client = createPublicClient18({ transport: http18(this.rpcUrl) });
4782
5645
  const [owner, tokenUri] = await Promise.all([
4783
5646
  client.readContract({ address: collection, abi: ERC721_ABI, functionName: "ownerOf", args: [tokenId] }).catch((e) => {
4784
5647
  throw DefiError.rpcError(`[${this.protocolName}] ownerOf failed: ${e}`);
@@ -4794,7 +5657,7 @@ var ERC721Adapter = class {
4794
5657
  }
4795
5658
  async getBalance(owner, collection) {
4796
5659
  if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
4797
- const client = createPublicClient19({ transport: http19(this.rpcUrl) });
5660
+ const client = createPublicClient18({ transport: http18(this.rpcUrl) });
4798
5661
  return client.readContract({ address: collection, abi: ERC721_ABI, functionName: "balanceOf", args: [owner] }).catch((e) => {
4799
5662
  throw DefiError.rpcError(`[${this.protocolName}] balanceOf failed: ${e}`);
4800
5663
  });
@@ -4915,6 +5778,9 @@ function createOracleFromCdp(entry, _asset, rpcUrl) {
4915
5778
  throw DefiError.unsupported(`Oracle not available for CDP interface '${entry.interface}'`);
4916
5779
  }
4917
5780
  }
5781
+ function createMerchantMoeLB(entry, rpcUrl) {
5782
+ return new MerchantMoeLBAdapter(entry, rpcUrl);
5783
+ }
4918
5784
  var DexSpotPrice = class {
4919
5785
  /**
4920
5786
  * Get the spot price for `token` denominated in `quoteToken` (e.g. USDC).
@@ -5922,20 +6788,20 @@ function registerYield(parent, getOpts, makeExecutor2) {
5922
6788
  }
5923
6789
 
5924
6790
  // src/commands/portfolio.ts
5925
- import { encodeFunctionData as encodeFunctionData24, parseAbi as parseAbi27 } from "viem";
6791
+ import { encodeFunctionData as encodeFunctionData25, parseAbi as parseAbi28 } from "viem";
5926
6792
 
5927
6793
  // src/portfolio-tracker.ts
5928
6794
  import { mkdirSync, writeFileSync, readdirSync as readdirSync2, readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
5929
6795
  import { homedir } from "os";
5930
6796
  import { resolve as resolve2 } from "path";
5931
- import { encodeFunctionData as encodeFunctionData23, parseAbi as parseAbi26 } from "viem";
5932
- var ERC20_ABI4 = parseAbi26([
6797
+ import { encodeFunctionData as encodeFunctionData24, parseAbi as parseAbi27 } from "viem";
6798
+ var ERC20_ABI4 = parseAbi27([
5933
6799
  "function balanceOf(address owner) external view returns (uint256)"
5934
6800
  ]);
5935
- var ORACLE_ABI4 = parseAbi26([
6801
+ var ORACLE_ABI4 = parseAbi27([
5936
6802
  "function getAssetPrice(address asset) external view returns (uint256)"
5937
6803
  ]);
5938
- var POOL_ABI3 = parseAbi26([
6804
+ var POOL_ABI3 = parseAbi27([
5939
6805
  "function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
5940
6806
  ]);
5941
6807
  function decodeU256Word(data, wordOffset = 0) {
@@ -5964,7 +6830,7 @@ async function takeSnapshot(chainName, wallet, registry) {
5964
6830
  tokenEntries.push({ symbol: t.symbol, address: entry.address, decimals: entry.decimals });
5965
6831
  calls.push([
5966
6832
  entry.address,
5967
- encodeFunctionData23({ abi: ERC20_ABI4, functionName: "balanceOf", args: [user] })
6833
+ encodeFunctionData24({ abi: ERC20_ABI4, functionName: "balanceOf", args: [user] })
5968
6834
  ]);
5969
6835
  callLabels.push(`balance:${t.symbol}`);
5970
6836
  }
@@ -5972,7 +6838,7 @@ async function takeSnapshot(chainName, wallet, registry) {
5972
6838
  for (const p of lendingProtocols) {
5973
6839
  calls.push([
5974
6840
  p.contracts["pool"],
5975
- encodeFunctionData23({ abi: POOL_ABI3, functionName: "getUserAccountData", args: [user] })
6841
+ encodeFunctionData24({ abi: POOL_ABI3, functionName: "getUserAccountData", args: [user] })
5976
6842
  ]);
5977
6843
  callLabels.push(`lending:${p.name}`);
5978
6844
  }
@@ -5982,7 +6848,7 @@ async function takeSnapshot(chainName, wallet, registry) {
5982
6848
  if (oracleAddr) {
5983
6849
  calls.push([
5984
6850
  oracleAddr,
5985
- encodeFunctionData23({ abi: ORACLE_ABI4, functionName: "getAssetPrice", args: [wrappedNative] })
6851
+ encodeFunctionData24({ abi: ORACLE_ABI4, functionName: "getAssetPrice", args: [wrappedNative] })
5986
6852
  ]);
5987
6853
  callLabels.push("price:native");
5988
6854
  }
@@ -6120,13 +6986,13 @@ function calculatePnL(current, previous) {
6120
6986
  }
6121
6987
 
6122
6988
  // src/commands/portfolio.ts
6123
- var ERC20_ABI5 = parseAbi27([
6989
+ var ERC20_ABI5 = parseAbi28([
6124
6990
  "function balanceOf(address owner) external view returns (uint256)"
6125
6991
  ]);
6126
- var POOL_ABI4 = parseAbi27([
6992
+ var POOL_ABI4 = parseAbi28([
6127
6993
  "function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
6128
6994
  ]);
6129
- var ORACLE_ABI5 = parseAbi27([
6995
+ var ORACLE_ABI5 = parseAbi28([
6130
6996
  "function getAssetPrice(address asset) external view returns (uint256)"
6131
6997
  ]);
6132
6998
  function decodeU2562(data, wordOffset = 0) {
@@ -6166,7 +7032,7 @@ function registerPortfolio(parent, getOpts) {
6166
7032
  if (entry.address === "0x0000000000000000000000000000000000000000") continue;
6167
7033
  calls.push([
6168
7034
  entry.address,
6169
- encodeFunctionData24({ abi: ERC20_ABI5, functionName: "balanceOf", args: [user] })
7035
+ encodeFunctionData25({ abi: ERC20_ABI5, functionName: "balanceOf", args: [user] })
6170
7036
  ]);
6171
7037
  callLabels.push(`balance:${symbol}`);
6172
7038
  }
@@ -6174,7 +7040,7 @@ function registerPortfolio(parent, getOpts) {
6174
7040
  for (const p of lendingProtocols) {
6175
7041
  calls.push([
6176
7042
  p.contracts["pool"],
6177
- encodeFunctionData24({ abi: POOL_ABI4, functionName: "getUserAccountData", args: [user] })
7043
+ encodeFunctionData25({ abi: POOL_ABI4, functionName: "getUserAccountData", args: [user] })
6178
7044
  ]);
6179
7045
  callLabels.push(`lending:${p.name}`);
6180
7046
  }
@@ -6184,7 +7050,7 @@ function registerPortfolio(parent, getOpts) {
6184
7050
  if (oracleAddr) {
6185
7051
  calls.push([
6186
7052
  oracleAddr,
6187
- encodeFunctionData24({ abi: ORACLE_ABI5, functionName: "getAssetPrice", args: [wrappedNative] })
7053
+ encodeFunctionData25({ abi: ORACLE_ABI5, functionName: "getAssetPrice", args: [wrappedNative] })
6188
7054
  ]);
6189
7055
  callLabels.push("price:native");
6190
7056
  }
@@ -6546,14 +7412,14 @@ function registerAlert(parent, getOpts) {
6546
7412
  }
6547
7413
 
6548
7414
  // src/commands/scan.ts
6549
- import { encodeFunctionData as encodeFunctionData25, parseAbi as parseAbi28 } from "viem";
6550
- var AAVE_ORACLE_ABI = parseAbi28([
7415
+ import { encodeFunctionData as encodeFunctionData26, parseAbi as parseAbi29 } from "viem";
7416
+ var AAVE_ORACLE_ABI = parseAbi29([
6551
7417
  "function getAssetPrice(address asset) external view returns (uint256)"
6552
7418
  ]);
6553
- var UNIV2_ROUTER_ABI = parseAbi28([
7419
+ var UNIV2_ROUTER_ABI = parseAbi29([
6554
7420
  "function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory)"
6555
7421
  ]);
6556
- var VTOKEN_ABI = parseAbi28([
7422
+ var VTOKEN_ABI = parseAbi29([
6557
7423
  "function exchangeRateStored() external view returns (uint256)"
6558
7424
  ]);
6559
7425
  var STABLECOINS = /* @__PURE__ */ new Set(["USDC", "USDT", "DAI", "USDT0"]);
@@ -6663,7 +7529,7 @@ function registerScan(parent, getOpts) {
6663
7529
  callTypes.push({ kind: "oracle", oracle: oracle.name, token: token.symbol, oracleDecimals: oracle.decimals });
6664
7530
  calls.push([
6665
7531
  oracle.addr,
6666
- encodeFunctionData25({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })
7532
+ encodeFunctionData26({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })
6667
7533
  ]);
6668
7534
  }
6669
7535
  }
@@ -6674,7 +7540,7 @@ function registerScan(parent, getOpts) {
6674
7540
  callTypes.push({ kind: "dex", token: token.symbol, outDecimals: quoteStable.decimals });
6675
7541
  calls.push([
6676
7542
  dexRouter,
6677
- encodeFunctionData25({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [amountIn, path] })
7543
+ encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [amountIn, path] })
6678
7544
  ]);
6679
7545
  }
6680
7546
  }
@@ -6683,7 +7549,7 @@ function registerScan(parent, getOpts) {
6683
7549
  callTypes.push({ kind: "stable", from: "USDC", to: "USDT", outDecimals: usdt.decimals });
6684
7550
  calls.push([
6685
7551
  dexRouter,
6686
- encodeFunctionData25({
7552
+ encodeFunctionData26({
6687
7553
  abi: UNIV2_ROUTER_ABI,
6688
7554
  functionName: "getAmountsOut",
6689
7555
  args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]]
@@ -6692,7 +7558,7 @@ function registerScan(parent, getOpts) {
6692
7558
  callTypes.push({ kind: "stable", from: "USDT", to: "USDC", outDecimals: usdc.decimals });
6693
7559
  calls.push([
6694
7560
  dexRouter,
6695
- encodeFunctionData25({
7561
+ encodeFunctionData26({
6696
7562
  abi: UNIV2_ROUTER_ABI,
6697
7563
  functionName: "getAmountsOut",
6698
7564
  args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]]
@@ -6703,7 +7569,7 @@ function registerScan(parent, getOpts) {
6703
7569
  for (const fork of compoundForks) {
6704
7570
  for (const { key, addr } of fork.vtokens) {
6705
7571
  callTypes.push({ kind: "exchangeRate", protocol: fork.name, vtoken: key });
6706
- calls.push([addr, encodeFunctionData25({ abi: VTOKEN_ABI, functionName: "exchangeRateStored", args: [] })]);
7572
+ calls.push([addr, encodeFunctionData26({ abi: VTOKEN_ABI, functionName: "exchangeRateStored", args: [] })]);
6707
7573
  }
6708
7574
  }
6709
7575
  }
@@ -6921,22 +7787,22 @@ async function runAllChains(registry, patterns, oracleThreshold, stableThreshold
6921
7787
  for (const oracle of oracles) {
6922
7788
  for (const token of scanTokens) {
6923
7789
  cts.push({ kind: "oracle", oracle: oracle.name, token: token.symbol, dec: oracle.decimals });
6924
- calls.push([oracle.addr, encodeFunctionData25({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })]);
7790
+ calls.push([oracle.addr, encodeFunctionData26({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })]);
6925
7791
  }
6926
7792
  }
6927
7793
  if (dexRouter) {
6928
7794
  for (const token of scanTokens) {
6929
7795
  const path = wrappedNative && token.address.toLowerCase() === wrappedNative.toLowerCase() ? [token.address, quoteStable.address] : wrappedNative ? [token.address, wrappedNative, quoteStable.address] : [token.address, quoteStable.address];
6930
7796
  cts.push({ kind: "dex", token: token.symbol, dec: quoteStable.decimals });
6931
- calls.push([dexRouter, encodeFunctionData25({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(token.decimals), path] })]);
7797
+ calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(token.decimals), path] })]);
6932
7798
  }
6933
7799
  }
6934
7800
  }
6935
7801
  if (doStable && usdc && usdt && dexRouter) {
6936
7802
  cts.push({ kind: "stable", from: "USDC", to: "USDT", dec: usdt.decimals });
6937
- calls.push([dexRouter, encodeFunctionData25({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]] })]);
7803
+ calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]] })]);
6938
7804
  cts.push({ kind: "stable", from: "USDT", to: "USDC", dec: usdc.decimals });
6939
- calls.push([dexRouter, encodeFunctionData25({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]] })]);
7805
+ calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]] })]);
6940
7806
  }
6941
7807
  if (calls.length === 0) return null;
6942
7808
  const ct0 = Date.now();
@@ -7064,14 +7930,14 @@ function registerArb(parent, getOpts, makeExecutor2) {
7064
7930
  }
7065
7931
 
7066
7932
  // src/commands/positions.ts
7067
- import { encodeFunctionData as encodeFunctionData26, parseAbi as parseAbi29 } from "viem";
7068
- var ERC20_ABI6 = parseAbi29([
7933
+ import { encodeFunctionData as encodeFunctionData27, parseAbi as parseAbi30 } from "viem";
7934
+ var ERC20_ABI6 = parseAbi30([
7069
7935
  "function balanceOf(address owner) external view returns (uint256)"
7070
7936
  ]);
7071
- var POOL_ABI5 = parseAbi29([
7937
+ var POOL_ABI5 = parseAbi30([
7072
7938
  "function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
7073
7939
  ]);
7074
- var ORACLE_ABI6 = parseAbi29([
7940
+ var ORACLE_ABI6 = parseAbi30([
7075
7941
  "function getAssetPrice(address asset) external view returns (uint256)"
7076
7942
  ]);
7077
7943
  function round22(x) {
@@ -7100,7 +7966,7 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
7100
7966
  callTypes.push({ kind: "token", symbol: token.symbol, decimals: token.decimals });
7101
7967
  calls.push([
7102
7968
  token.address,
7103
- encodeFunctionData26({ abi: ERC20_ABI6, functionName: "balanceOf", args: [user] })
7969
+ encodeFunctionData27({ abi: ERC20_ABI6, functionName: "balanceOf", args: [user] })
7104
7970
  ]);
7105
7971
  }
7106
7972
  }
@@ -7108,14 +7974,14 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
7108
7974
  callTypes.push({ kind: "lending", protocol: name, iface });
7109
7975
  calls.push([
7110
7976
  pool,
7111
- encodeFunctionData26({ abi: POOL_ABI5, functionName: "getUserAccountData", args: [user] })
7977
+ encodeFunctionData27({ abi: POOL_ABI5, functionName: "getUserAccountData", args: [user] })
7112
7978
  ]);
7113
7979
  }
7114
7980
  if (oracleAddr) {
7115
7981
  callTypes.push({ kind: "native_price" });
7116
7982
  calls.push([
7117
7983
  oracleAddr,
7118
- encodeFunctionData26({ abi: ORACLE_ABI6, functionName: "getAssetPrice", args: [wrappedNative] })
7984
+ encodeFunctionData27({ abi: ORACLE_ABI6, functionName: "getAssetPrice", args: [wrappedNative] })
7119
7985
  ]);
7120
7986
  }
7121
7987
  if (calls.length === 0) return null;
@@ -7408,14 +8274,14 @@ function registerPrice(parent, getOpts) {
7408
8274
  }
7409
8275
 
7410
8276
  // src/commands/wallet.ts
7411
- import { createPublicClient as createPublicClient20, http as http20, formatEther } from "viem";
8277
+ import { createPublicClient as createPublicClient19, http as http19, formatEther } from "viem";
7412
8278
  function registerWallet(parent, getOpts) {
7413
8279
  const wallet = parent.command("wallet").description("Wallet management");
7414
8280
  wallet.command("balance").description("Show native token balance").requiredOption("--address <address>", "Wallet address to query").action(async (opts) => {
7415
8281
  const chainName = parent.opts().chain ?? "hyperevm";
7416
8282
  const registry = Registry.loadEmbedded();
7417
8283
  const chain = registry.getChain(chainName);
7418
- const client = createPublicClient20({ transport: http20(chain.effectiveRpcUrl()) });
8284
+ const client = createPublicClient19({ transport: http19(chain.effectiveRpcUrl()) });
7419
8285
  const balance = await client.getBalance({ address: opts.address });
7420
8286
  printOutput({
7421
8287
  chain: chain.name,
@@ -7432,14 +8298,14 @@ function registerWallet(parent, getOpts) {
7432
8298
  }
7433
8299
 
7434
8300
  // src/commands/token.ts
7435
- import { createPublicClient as createPublicClient21, http as http21, maxUint256 } from "viem";
8301
+ import { createPublicClient as createPublicClient20, http as http20, maxUint256 } from "viem";
7436
8302
  function registerToken(parent, getOpts, makeExecutor2) {
7437
8303
  const token = parent.command("token").description("Token operations: approve, allowance, transfer, balance");
7438
8304
  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) => {
7439
8305
  const chainName = parent.opts().chain ?? "hyperevm";
7440
8306
  const registry = Registry.loadEmbedded();
7441
8307
  const chain = registry.getChain(chainName);
7442
- const client = createPublicClient21({ transport: http21(chain.effectiveRpcUrl()) });
8308
+ const client = createPublicClient20({ transport: http20(chain.effectiveRpcUrl()) });
7443
8309
  const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
7444
8310
  const [balance, symbol, decimals] = await Promise.all([
7445
8311
  client.readContract({ address: tokenAddr, abi: erc20Abi, functionName: "balanceOf", args: [opts.owner] }),
@@ -7468,7 +8334,7 @@ function registerToken(parent, getOpts, makeExecutor2) {
7468
8334
  const chainName = parent.opts().chain ?? "hyperevm";
7469
8335
  const registry = Registry.loadEmbedded();
7470
8336
  const chain = registry.getChain(chainName);
7471
- const client = createPublicClient21({ transport: http21(chain.effectiveRpcUrl()) });
8337
+ const client = createPublicClient20({ transport: http20(chain.effectiveRpcUrl()) });
7472
8338
  const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
7473
8339
  const allowance = await client.readContract({
7474
8340
  address: tokenAddr,
@@ -7490,8 +8356,8 @@ function registerToken(parent, getOpts, makeExecutor2) {
7490
8356
  }
7491
8357
 
7492
8358
  // src/commands/whales.ts
7493
- import { encodeFunctionData as encodeFunctionData27, parseAbi as parseAbi30 } from "viem";
7494
- var POOL_ABI6 = parseAbi30([
8359
+ import { encodeFunctionData as encodeFunctionData28, parseAbi as parseAbi31 } from "viem";
8360
+ var POOL_ABI6 = parseAbi31([
7495
8361
  "function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
7496
8362
  ]);
7497
8363
  function round24(x) {
@@ -7602,7 +8468,7 @@ function registerWhales(parent, getOpts) {
7602
8468
  for (const { pool } of lendingPools) {
7603
8469
  calls.push([
7604
8470
  pool,
7605
- encodeFunctionData27({ abi: POOL_ABI6, functionName: "getUserAccountData", args: [whale.address] })
8471
+ encodeFunctionData28({ abi: POOL_ABI6, functionName: "getUserAccountData", args: [whale.address] })
7606
8472
  ]);
7607
8473
  }
7608
8474
  }
@@ -8030,11 +8896,11 @@ function registerBridge(parent, getOpts) {
8030
8896
  const amountUsdc = Number(BigInt(opts.amount)) / 1e6;
8031
8897
  const { fee, maxFeeSubunits } = await getCctpFeeEstimate(srcDomain, dstDomain, amountUsdc);
8032
8898
  const recipientPadded = `0x${"0".repeat(24)}${recipient.replace("0x", "").toLowerCase()}`;
8033
- const { encodeFunctionData: encodeFunctionData29, parseAbi: parseAbi33 } = await import("viem");
8034
- const tokenMessengerAbi = parseAbi33([
8899
+ const { encodeFunctionData: encodeFunctionData30, parseAbi: parseAbi34 } = await import("viem");
8900
+ const tokenMessengerAbi = parseAbi34([
8035
8901
  "function depositForBurn(uint256 amount, uint32 destinationDomain, bytes32 mintRecipient, address burnToken, bytes32 destinationCaller, uint256 maxFee, uint32 minFinalityThreshold) external returns (uint64 nonce)"
8036
8902
  ]);
8037
- const data = encodeFunctionData29({
8903
+ const data = encodeFunctionData30({
8038
8904
  abi: tokenMessengerAbi,
8039
8905
  functionName: "depositForBurn",
8040
8906
  args: [
@@ -8371,6 +9237,107 @@ function registerSetup(program2) {
8371
9237
  });
8372
9238
  }
8373
9239
 
9240
+ // src/commands/lb.ts
9241
+ function registerLB(parent, getOpts, makeExecutor2) {
9242
+ const lb = parent.command("lb").description("Merchant Moe Liquidity Book: add/remove liquidity, rewards, positions");
9243
+ 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) => {
9244
+ const executor = makeExecutor2();
9245
+ const registry = Registry.loadEmbedded();
9246
+ const protocol = registry.getProtocol(opts.protocol);
9247
+ const chainName = parent.opts().chain;
9248
+ const chain = registry.getChain(chainName ?? "mantle");
9249
+ const rpcUrl = chain.effectiveRpcUrl();
9250
+ const adapter = createMerchantMoeLB(protocol, rpcUrl);
9251
+ const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
9252
+ const tx = await adapter.buildAddLiquidity({
9253
+ pool: opts.pool,
9254
+ tokenX: opts.tokenX,
9255
+ tokenY: opts.tokenY,
9256
+ binStep: parseInt(opts.binStep),
9257
+ amountX: BigInt(opts.amountX),
9258
+ amountY: BigInt(opts.amountY),
9259
+ numBins: parseInt(opts.bins),
9260
+ activeIdDesired: opts.activeId ? parseInt(opts.activeId) : void 0,
9261
+ recipient
9262
+ });
9263
+ const result = await executor.execute(tx);
9264
+ printOutput(result, getOpts());
9265
+ });
9266
+ 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) => {
9267
+ const executor = makeExecutor2();
9268
+ const registry = Registry.loadEmbedded();
9269
+ const protocol = registry.getProtocol(opts.protocol);
9270
+ const adapter = createMerchantMoeLB(protocol);
9271
+ const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
9272
+ const binIds = opts.bins.split(",").map((s) => parseInt(s.trim()));
9273
+ const amounts = opts.amounts.split(",").map((s) => BigInt(s.trim()));
9274
+ const tx = await adapter.buildRemoveLiquidity({
9275
+ tokenX: opts.tokenX,
9276
+ tokenY: opts.tokenY,
9277
+ binStep: parseInt(opts.binStep),
9278
+ binIds,
9279
+ amounts,
9280
+ recipient
9281
+ });
9282
+ const result = await executor.execute(tx);
9283
+ printOutput(result, getOpts());
9284
+ });
9285
+ 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) => {
9286
+ const registry = Registry.loadEmbedded();
9287
+ const protocol = registry.getProtocol(opts.protocol);
9288
+ const chainName = parent.opts().chain;
9289
+ const chain = registry.getChain(chainName ?? "mantle");
9290
+ const rpcUrl = chain.effectiveRpcUrl();
9291
+ const adapter = createMerchantMoeLB(protocol, rpcUrl);
9292
+ const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
9293
+ if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
9294
+ const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
9295
+ const rewards = await adapter.getPendingRewards(user, opts.pool, binIds);
9296
+ printOutput(rewards, getOpts());
9297
+ });
9298
+ 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) => {
9299
+ const executor = makeExecutor2();
9300
+ const registry = Registry.loadEmbedded();
9301
+ const protocol = registry.getProtocol(opts.protocol);
9302
+ const chainName = parent.opts().chain;
9303
+ const chain = registry.getChain(chainName ?? "mantle");
9304
+ const rpcUrl = chain.effectiveRpcUrl();
9305
+ const adapter = createMerchantMoeLB(protocol, rpcUrl);
9306
+ const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
9307
+ if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
9308
+ const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
9309
+ const tx = await adapter.buildClaimRewards(user, opts.pool, binIds);
9310
+ const result = await executor.execute(tx);
9311
+ printOutput(result, getOpts());
9312
+ });
9313
+ 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) => {
9314
+ const registry = Registry.loadEmbedded();
9315
+ const protocol = registry.getProtocol(opts.protocol);
9316
+ const chainName = parent.opts().chain;
9317
+ const chain = registry.getChain(chainName ?? "mantle");
9318
+ const rpcUrl = chain.effectiveRpcUrl();
9319
+ const adapter = createMerchantMoeLB(protocol, rpcUrl);
9320
+ let pools = await adapter.discoverRewardedPools();
9321
+ if (opts.activeOnly) {
9322
+ pools = pools.filter((p) => !p.stopped);
9323
+ }
9324
+ printOutput(pools, getOpts());
9325
+ });
9326
+ 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) => {
9327
+ const registry = Registry.loadEmbedded();
9328
+ const protocol = registry.getProtocol(opts.protocol);
9329
+ const chainName = parent.opts().chain;
9330
+ const chain = registry.getChain(chainName ?? "mantle");
9331
+ const rpcUrl = chain.effectiveRpcUrl();
9332
+ const adapter = createMerchantMoeLB(protocol, rpcUrl);
9333
+ const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
9334
+ if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
9335
+ const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
9336
+ const positions = await adapter.getUserPositions(user, opts.pool, binIds);
9337
+ printOutput(positions, getOpts());
9338
+ });
9339
+ }
9340
+
8374
9341
  // src/cli.ts
8375
9342
  var _require = createRequire(import.meta.url);
8376
9343
  var _pkg = _require("../package.json");
@@ -8382,7 +9349,7 @@ var BANNER = `
8382
9349
  \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
8383
9350
  \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
8384
9351
 
8385
- 2 chains \xB7 32 protocols \xB7 by HypurrQuant
9352
+ 2 chains \xB7 30 protocols \xB7 by HypurrQuant
8386
9353
 
8387
9354
  Scan exploits, swap tokens, bridge assets, track whales,
8388
9355
  compare yields \u2014 all from your terminal.
@@ -8422,6 +9389,7 @@ registerSwap(program, getOutputMode, makeExecutor);
8422
9389
  registerBridge(program, getOutputMode);
8423
9390
  registerNft(program, getOutputMode);
8424
9391
  registerFarm(program, getOutputMode, makeExecutor);
9392
+ registerLB(program, getOutputMode, makeExecutor);
8425
9393
  registerSetup(program);
8426
9394
  program.command("agent").description("Agent mode: read JSON commands from stdin (for AI agents)").action(async () => {
8427
9395
  const executor = makeExecutor();
@@ -8432,13 +9400,13 @@ program.command("agent").description("Agent mode: read JSON commands from stdin
8432
9400
 
8433
9401
  // src/landing.ts
8434
9402
  import pc3 from "picocolors";
8435
- import { encodeFunctionData as encodeFunctionData28, parseAbi as parseAbi31, formatUnits } from "viem";
9403
+ import { encodeFunctionData as encodeFunctionData29, parseAbi as parseAbi33, formatUnits } from "viem";
8436
9404
  var HYPEREVM_DISPLAY = ["HYPE", "WHYPE", "USDC", "USDT0", "USDe", "kHYPE", "wstHYPE"];
8437
9405
  var MANTLE_DISPLAY = ["MNT", "WMNT", "USDC", "USDT", "WETH", "mETH"];
8438
- var balanceOfAbi = parseAbi31([
9406
+ var balanceOfAbi = parseAbi33([
8439
9407
  "function balanceOf(address account) view returns (uint256)"
8440
9408
  ]);
8441
- var getEthBalanceAbi = parseAbi31([
9409
+ var getEthBalanceAbi = parseAbi33([
8442
9410
  "function getEthBalance(address addr) view returns (uint256)"
8443
9411
  ]);
8444
9412
  async function fetchBalances(rpcUrl, wallet, tokens) {
@@ -8447,7 +9415,7 @@ async function fetchBalances(rpcUrl, wallet, tokens) {
8447
9415
  if (isNative) {
8448
9416
  return [
8449
9417
  MULTICALL3_ADDRESS,
8450
- encodeFunctionData28({
9418
+ encodeFunctionData29({
8451
9419
  abi: getEthBalanceAbi,
8452
9420
  functionName: "getEthBalance",
8453
9421
  args: [wallet]
@@ -8456,7 +9424,7 @@ async function fetchBalances(rpcUrl, wallet, tokens) {
8456
9424
  }
8457
9425
  return [
8458
9426
  t.address,
8459
- encodeFunctionData28({
9427
+ encodeFunctionData29({
8460
9428
  abi: balanceOfAbi,
8461
9429
  functionName: "balanceOf",
8462
9430
  args: [wallet]
@@ -8630,6 +9598,7 @@ async function main() {
8630
9598
  "bridge",
8631
9599
  "nft",
8632
9600
  "farm",
9601
+ "lb",
8633
9602
  "agent",
8634
9603
  "setup",
8635
9604
  "init"