@hypurrquant/defi-cli 0.2.4 → 0.2.5

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
@@ -1016,8 +1016,13 @@ var Registry = class _Registry {
1016
1016
  };
1017
1017
 
1018
1018
  // src/executor.ts
1019
+ var ERC20_ABI = parseAbi3([
1020
+ "function allowance(address owner, address spender) external view returns (uint256)",
1021
+ "function approve(address spender, uint256 amount) external returns (bool)"
1022
+ ]);
1019
1023
  var GAS_BUFFER_BPS = 12000n;
1020
- var DEFAULT_PRIORITY_FEE_WEI = 100000000n;
1024
+ var DEFAULT_PRIORITY_FEE_WEI = 20000000000n;
1025
+ var MAX_GAS_LIMIT = 5000000000n;
1021
1026
  var Executor = class _Executor {
1022
1027
  dryRun;
1023
1028
  rpcUrl;
@@ -1031,6 +1036,62 @@ var Executor = class _Executor {
1031
1036
  static applyGasBuffer(gas) {
1032
1037
  return gas * GAS_BUFFER_BPS / 10000n;
1033
1038
  }
1039
+ /**
1040
+ * Check allowance for a single token/spender pair and send an approve tx if needed.
1041
+ * Only called in broadcast mode (not dry-run).
1042
+ */
1043
+ async checkAndApprove(token, spender, amount, owner, publicClient, walletClient) {
1044
+ const allowance = await publicClient.readContract({
1045
+ address: token,
1046
+ abi: ERC20_ABI,
1047
+ functionName: "allowance",
1048
+ args: [owner, spender]
1049
+ });
1050
+ if (allowance >= amount) return;
1051
+ process.stderr.write(
1052
+ ` Approving ${amount} of ${token} for ${spender}...
1053
+ `
1054
+ );
1055
+ const approveData = encodeFunctionData3({
1056
+ abi: ERC20_ABI,
1057
+ functionName: "approve",
1058
+ args: [spender, amount]
1059
+ });
1060
+ const rpcUrl = this.rpcUrl;
1061
+ const gasLimit = await (async () => {
1062
+ try {
1063
+ const estimated = await publicClient.estimateGas({
1064
+ to: token,
1065
+ data: approveData,
1066
+ account: owner
1067
+ });
1068
+ const buffered = _Executor.applyGasBuffer(estimated);
1069
+ return buffered > MAX_GAS_LIMIT ? MAX_GAS_LIMIT : buffered;
1070
+ } catch {
1071
+ return 80000n;
1072
+ }
1073
+ })();
1074
+ const [maxFeePerGas, maxPriorityFeePerGas] = await this.fetchEip1559Fees(rpcUrl);
1075
+ const approveTxHash = await walletClient.sendTransaction({
1076
+ chain: null,
1077
+ account: walletClient.account,
1078
+ to: token,
1079
+ data: approveData,
1080
+ gas: gasLimit > 0n ? gasLimit : void 0,
1081
+ maxFeePerGas: maxFeePerGas > 0n ? maxFeePerGas : void 0,
1082
+ maxPriorityFeePerGas: maxPriorityFeePerGas > 0n ? maxPriorityFeePerGas : void 0
1083
+ });
1084
+ const approveTxUrl = this.explorerUrl ? `${this.explorerUrl}/tx/${approveTxHash}` : void 0;
1085
+ process.stderr.write(` Approve tx: ${approveTxHash}
1086
+ `);
1087
+ if (approveTxUrl) process.stderr.write(` Explorer: ${approveTxUrl}
1088
+ `);
1089
+ await publicClient.waitForTransactionReceipt({ hash: approveTxHash });
1090
+ process.stderr.write(
1091
+ ` Approved ${amount} of ${token} for ${spender}
1092
+ `
1093
+ );
1094
+ }
1034
1095
  /** Fetch EIP-1559 fee params from the network. Returns [maxFeePerGas, maxPriorityFeePerGas]. */
1035
1096
  async fetchEip1559Fees(rpcUrl) {
1036
1097
  try {
@@ -1057,7 +1118,10 @@ var Executor = class _Executor {
1057
1118
  value: tx.value,
1058
1119
  account: from
1059
1120
  });
1060
- if (estimated > 0n) return _Executor.applyGasBuffer(estimated);
1121
+ if (estimated > 0n) {
1122
+ const buffered = _Executor.applyGasBuffer(estimated);
1123
+ return buffered > MAX_GAS_LIMIT ? MAX_GAS_LIMIT : buffered;
1124
+ }
1061
1125
  } catch {
1062
1126
  }
1063
1127
  return tx.gas_estimate ? BigInt(tx.gas_estimate) : 0n;
@@ -1143,6 +1207,18 @@ var Executor = class _Executor {
1143
1207
  }
1144
1208
  const publicClient = createPublicClient2({ transport: http2(rpcUrl) });
1145
1209
  const walletClient = createWalletClient({ account, transport: http2(rpcUrl) });
1210
+ if (tx.approvals && tx.approvals.length > 0) {
1211
+ for (const approval of tx.approvals) {
1212
+ await this.checkAndApprove(
1213
+ approval.token,
1214
+ approval.spender,
1215
+ approval.amount,
1216
+ account.address,
1217
+ publicClient,
1218
+ walletClient
1219
+ );
1220
+ }
1221
+ }
1146
1222
  const gasLimit = await this.estimateGasWithBuffer(rpcUrl, tx, account.address);
1147
1223
  const [maxFeePerGas, maxPriorityFeePerGas] = await this.fetchEip1559Fees(rpcUrl);
1148
1224
  process.stderr.write(`Broadcasting transaction to ${rpcUrl}...
@@ -1719,10 +1795,10 @@ function registerSchema(parent, getOpts) {
1719
1795
  }
1720
1796
 
1721
1797
  // ../defi-protocols/dist/index.js
1722
- import { encodeFunctionData as encodeFunctionData3, parseAbi as parseAbi3, createPublicClient as createPublicClient4, http as http4, decodeAbiParameters } from "viem";
1798
+ import { encodeFunctionData as encodeFunctionData4, parseAbi as parseAbi4, createPublicClient as createPublicClient4, http as http4, decodeAbiParameters } from "viem";
1723
1799
  import { encodeFunctionData as encodeFunctionData22, parseAbi as parseAbi22, createPublicClient as createPublicClient22, http as http22, decodeFunctionResult as decodeFunctionResult2, decodeAbiParameters as decodeAbiParameters2 } from "viem";
1724
1800
  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";
1801
+ import { encodeFunctionData as encodeFunctionData42, parseAbi as parseAbi42, zeroAddress as zeroAddress2 } from "viem";
1726
1802
  import { encodeFunctionData as encodeFunctionData5, parseAbi as parseAbi5 } from "viem";
1727
1803
  import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6, createPublicClient as createPublicClient42, http as http42, decodeAbiParameters as decodeAbiParameters4 } from "viem";
1728
1804
  import { encodeFunctionData as encodeFunctionData7, parseAbi as parseAbi7, zeroAddress as zeroAddress3 } from "viem";
@@ -1745,19 +1821,19 @@ import { parseAbi as parseAbi23, encodeFunctionData as encodeFunctionData21 } fr
1745
1821
  import { parseAbi as parseAbi24, encodeFunctionData as encodeFunctionData222 } from "viem";
1746
1822
  import { createPublicClient as createPublicClient19, http as http19, parseAbi as parseAbi25 } from "viem";
1747
1823
  var DEFAULT_FEE = 3e3;
1748
- var swapRouterAbi = parseAbi3([
1824
+ var swapRouterAbi = parseAbi4([
1749
1825
  "struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; }",
1750
1826
  "function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut)"
1751
1827
  ]);
1752
- var quoterAbi = parseAbi3([
1828
+ var quoterAbi = parseAbi4([
1753
1829
  "struct QuoteExactInputSingleParams { address tokenIn; address tokenOut; uint256 amountIn; uint24 fee; uint160 sqrtPriceLimitX96; }",
1754
1830
  "function quoteExactInputSingle(QuoteExactInputSingleParams memory params) external returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)"
1755
1831
  ]);
1756
- var ramsesQuoterAbi = parseAbi3([
1832
+ var ramsesQuoterAbi = parseAbi4([
1757
1833
  "struct QuoteExactInputSingleParams { address tokenIn; address tokenOut; uint256 amountIn; int24 tickSpacing; uint160 sqrtPriceLimitX96; }",
1758
1834
  "function quoteExactInputSingle(QuoteExactInputSingleParams memory params) external returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)"
1759
1835
  ]);
1760
- var positionManagerAbi = parseAbi3([
1836
+ var positionManagerAbi = parseAbi4([
1761
1837
  "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
1838
  "function mint(MintParams calldata params) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1)"
1763
1839
  ]);
@@ -1790,7 +1866,7 @@ var UniswapV3Adapter = class {
1790
1866
  async buildSwap(params) {
1791
1867
  const deadline = BigInt(params.deadline ?? 18446744073709551615n);
1792
1868
  const amountOutMinimum = 0n;
1793
- const data = encodeFunctionData3({
1869
+ const data = encodeFunctionData4({
1794
1870
  abi: swapRouterAbi,
1795
1871
  functionName: "exactInputSingle",
1796
1872
  args: [
@@ -1811,7 +1887,8 @@ var UniswapV3Adapter = class {
1811
1887
  to: this.router,
1812
1888
  data,
1813
1889
  value: 0n,
1814
- gas_estimate: 2e5
1890
+ gas_estimate: 2e5,
1891
+ approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
1815
1892
  };
1816
1893
  }
1817
1894
  async quote(params) {
@@ -1826,7 +1903,7 @@ var UniswapV3Adapter = class {
1826
1903
  tickSpacings.map(async (ts) => {
1827
1904
  const result = await client2.call({
1828
1905
  to: this.quoter,
1829
- data: encodeFunctionData3({
1906
+ data: encodeFunctionData4({
1830
1907
  abi: ramsesQuoterAbi,
1831
1908
  functionName: "quoteExactInputSingle",
1832
1909
  args: [
@@ -1872,7 +1949,7 @@ var UniswapV3Adapter = class {
1872
1949
  feeTiers.map(async (fee) => {
1873
1950
  const result = await client2.call({
1874
1951
  to: this.quoter,
1875
- data: encodeFunctionData3({
1952
+ data: encodeFunctionData4({
1876
1953
  abi: quoterAbi,
1877
1954
  functionName: "quoteExactInputSingle",
1878
1955
  args: [
@@ -1911,7 +1988,7 @@ var UniswapV3Adapter = class {
1911
1988
  }
1912
1989
  }
1913
1990
  const client = createPublicClient4({ transport: http4(this.rpcUrl) });
1914
- const callData = encodeFunctionData3({
1991
+ const callData = encodeFunctionData4({
1915
1992
  abi: swapRouterAbi,
1916
1993
  functionName: "exactInputSingle",
1917
1994
  args: [
@@ -1957,7 +2034,7 @@ var UniswapV3Adapter = class {
1957
2034
  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
2035
  const amount0 = rawAmount0 === 0n && rawAmount1 > 0n ? 1n : rawAmount0;
1959
2036
  const amount1 = rawAmount1 === 0n && rawAmount0 > 0n ? 1n : rawAmount1;
1960
- const data = encodeFunctionData3({
2037
+ const data = encodeFunctionData4({
1961
2038
  abi: positionManagerAbi,
1962
2039
  functionName: "mint",
1963
2040
  args: [
@@ -1981,7 +2058,11 @@ var UniswapV3Adapter = class {
1981
2058
  to: pm,
1982
2059
  data,
1983
2060
  value: 0n,
1984
- gas_estimate: 5e5
2061
+ gas_estimate: 5e5,
2062
+ approvals: [
2063
+ { token: token0, spender: pm, amount: amount0 },
2064
+ { token: token1, spender: pm, amount: amount1 }
2065
+ ]
1985
2066
  };
1986
2067
  }
1987
2068
  async buildRemoveLiquidity(_params) {
@@ -2040,7 +2121,8 @@ var UniswapV2Adapter = class {
2040
2121
  to: this.router,
2041
2122
  data,
2042
2123
  value: 0n,
2043
- gas_estimate: 15e4
2124
+ gas_estimate: 15e4,
2125
+ approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
2044
2126
  };
2045
2127
  }
2046
2128
  async quote(params) {
@@ -2159,7 +2241,11 @@ var UniswapV2Adapter = class {
2159
2241
  to: this.router,
2160
2242
  data,
2161
2243
  value: 0n,
2162
- gas_estimate: 3e5
2244
+ gas_estimate: 3e5,
2245
+ approvals: [
2246
+ { token: params.token_a, spender: this.router, amount: params.amount_a },
2247
+ { token: params.token_b, spender: this.router, amount: params.amount_b }
2248
+ ]
2163
2249
  };
2164
2250
  }
2165
2251
  async buildRemoveLiquidity(params) {
@@ -2246,7 +2332,8 @@ var AlgebraV3Adapter = class {
2246
2332
  to: this.router,
2247
2333
  data,
2248
2334
  value: 0n,
2249
- gas_estimate: 25e4
2335
+ gas_estimate: 25e4,
2336
+ approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
2250
2337
  };
2251
2338
  }
2252
2339
  async quote(params) {
@@ -2364,7 +2451,11 @@ var AlgebraV3Adapter = class {
2364
2451
  to: pm,
2365
2452
  data,
2366
2453
  value: 0n,
2367
- gas_estimate: 5e5
2454
+ gas_estimate: 5e5,
2455
+ approvals: [
2456
+ { token: token0, spender: pm, amount: amount0 },
2457
+ { token: token1, spender: pm, amount: amount1 }
2458
+ ]
2368
2459
  };
2369
2460
  }
2370
2461
  async buildRemoveLiquidity(_params) {
@@ -2373,7 +2464,7 @@ var AlgebraV3Adapter = class {
2373
2464
  );
2374
2465
  }
2375
2466
  };
2376
- var abi3 = parseAbi4([
2467
+ var abi3 = parseAbi42([
2377
2468
  "function swapSingleTokenExactIn(address pool, address tokenIn, address tokenOut, uint256 exactAmountIn, uint256 minAmountOut, uint256 deadline, bool wethIsEth, bytes calldata userData) external returns (uint256 amountOut)"
2378
2469
  ]);
2379
2470
  var BalancerV3Adapter = class {
@@ -2393,7 +2484,7 @@ var BalancerV3Adapter = class {
2393
2484
  async buildSwap(params) {
2394
2485
  const minAmountOut = 0n;
2395
2486
  const deadline = BigInt(params.deadline ?? 18446744073709551615n);
2396
- const data = encodeFunctionData4({
2487
+ const data = encodeFunctionData42({
2397
2488
  abi: abi3,
2398
2489
  functionName: "swapSingleTokenExactIn",
2399
2490
  args: [
@@ -2541,7 +2632,8 @@ var SolidlyAdapter = class {
2541
2632
  to: this.router,
2542
2633
  data,
2543
2634
  value: 0n,
2544
- gas_estimate: 2e5
2635
+ gas_estimate: 2e5,
2636
+ approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
2545
2637
  };
2546
2638
  }
2547
2639
  async callGetAmountsOut(client, callData) {
@@ -2624,7 +2716,11 @@ var SolidlyAdapter = class {
2624
2716
  to: this.router,
2625
2717
  data,
2626
2718
  value: 0n,
2627
- gas_estimate: 35e4
2719
+ gas_estimate: 35e4,
2720
+ approvals: [
2721
+ { token: params.token_a, spender: this.router, amount: params.amount_a },
2722
+ { token: params.token_b, spender: this.router, amount: params.amount_b }
2723
+ ]
2628
2724
  };
2629
2725
  }
2630
2726
  async buildRemoveLiquidity(params) {
@@ -2750,7 +2846,7 @@ var SolidlyGaugeAdapter = class {
2750
2846
  return this.protocolName;
2751
2847
  }
2752
2848
  // IGauge
2753
- async buildDeposit(gauge, amount, tokenId) {
2849
+ async buildDeposit(gauge, amount, tokenId, lpToken) {
2754
2850
  if (tokenId !== void 0) {
2755
2851
  const data2 = encodeFunctionData8({
2756
2852
  abi: gaugeAbi,
@@ -2762,7 +2858,8 @@ var SolidlyGaugeAdapter = class {
2762
2858
  to: gauge,
2763
2859
  data: data2,
2764
2860
  value: 0n,
2765
- gas_estimate: 2e5
2861
+ gas_estimate: 2e5,
2862
+ approvals: lpToken ? [{ token: lpToken, spender: gauge, amount }] : void 0
2766
2863
  };
2767
2864
  }
2768
2865
  const data = encodeFunctionData8({
@@ -2775,7 +2872,8 @@ var SolidlyGaugeAdapter = class {
2775
2872
  to: gauge,
2776
2873
  data,
2777
2874
  value: 0n,
2778
- gas_estimate: 2e5
2875
+ gas_estimate: 2e5,
2876
+ approvals: lpToken ? [{ token: lpToken, spender: gauge, amount }] : void 0
2779
2877
  };
2780
2878
  }
2781
2879
  async buildWithdraw(gauge, amount) {
@@ -3075,7 +3173,7 @@ var POOL_ABI = parseAbi10([
3075
3173
  "function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)",
3076
3174
  "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
3175
  ]);
3078
- var ERC20_ABI = parseAbi10([
3176
+ var ERC20_ABI2 = parseAbi10([
3079
3177
  "function totalSupply() external view returns (uint256)"
3080
3178
  ]);
3081
3179
  var INCENTIVES_ABI = parseAbi10([
@@ -3128,7 +3226,8 @@ var AaveV3Adapter = class {
3128
3226
  to: this.pool,
3129
3227
  data,
3130
3228
  value: 0n,
3131
- gas_estimate: 3e5
3229
+ gas_estimate: 3e5,
3230
+ approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
3132
3231
  };
3133
3232
  }
3134
3233
  async buildBorrow(params) {
@@ -3158,7 +3257,8 @@ var AaveV3Adapter = class {
3158
3257
  to: this.pool,
3159
3258
  data,
3160
3259
  value: 0n,
3161
- gas_estimate: 3e5
3260
+ gas_estimate: 3e5,
3261
+ approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
3162
3262
  };
3163
3263
  }
3164
3264
  async buildWithdraw(params) {
@@ -3200,12 +3300,12 @@ var AaveV3Adapter = class {
3200
3300
  const [totalSupply, totalBorrow] = await Promise.all([
3201
3301
  client.readContract({
3202
3302
  address: aTokenAddress,
3203
- abi: ERC20_ABI,
3303
+ abi: ERC20_ABI2,
3204
3304
  functionName: "totalSupply"
3205
3305
  }).catch(() => 0n),
3206
3306
  client.readContract({
3207
3307
  address: variableDebtTokenAddress,
3208
- abi: ERC20_ABI,
3308
+ abi: ERC20_ABI2,
3209
3309
  functionName: "totalSupply"
3210
3310
  }).catch(() => 0n)
3211
3311
  ]);
@@ -3429,7 +3529,7 @@ var POOL_ABI2 = parseAbi11([
3429
3529
  // [9]=variableDebtTokenAddress, [10]=interestRateStrategyAddress, [11]=id
3430
3530
  "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
3531
  ]);
3432
- var ERC20_ABI2 = parseAbi11([
3532
+ var ERC20_ABI22 = parseAbi11([
3433
3533
  "function totalSupply() external view returns (uint256)"
3434
3534
  ]);
3435
3535
  function u256ToF642(v) {
@@ -3462,7 +3562,8 @@ var AaveV2Adapter = class {
3462
3562
  to: this.pool,
3463
3563
  data,
3464
3564
  value: 0n,
3465
- gas_estimate: 3e5
3565
+ gas_estimate: 3e5,
3566
+ approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
3466
3567
  };
3467
3568
  }
3468
3569
  async buildBorrow(params) {
@@ -3492,7 +3593,8 @@ var AaveV2Adapter = class {
3492
3593
  to: this.pool,
3493
3594
  data,
3494
3595
  value: 0n,
3495
- gas_estimate: 3e5
3596
+ gas_estimate: 3e5,
3597
+ approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
3496
3598
  };
3497
3599
  }
3498
3600
  async buildWithdraw(params) {
@@ -3534,12 +3636,12 @@ var AaveV2Adapter = class {
3534
3636
  const [totalSupply, totalBorrow] = await Promise.all([
3535
3637
  client.readContract({
3536
3638
  address: aTokenAddress,
3537
- abi: ERC20_ABI2,
3639
+ abi: ERC20_ABI22,
3538
3640
  functionName: "totalSupply"
3539
3641
  }).catch(() => 0n),
3540
3642
  client.readContract({
3541
3643
  address: variableDebtTokenAddress,
3542
- abi: ERC20_ABI2,
3644
+ abi: ERC20_ABI22,
3543
3645
  functionName: "totalSupply"
3544
3646
  }).catch(() => 0n)
3545
3647
  ]);