@hypurrquant/defi-cli 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/protocols/dex/hybra.toml +91 -0
- package/config/protocols/dex/kittenswap.toml +21 -0
- package/config/protocols/dex/nest.toml +97 -0
- package/config/protocols/dex/ramses_cl.toml +56 -0
- package/config/protocols/dex/ramses_hl.toml +40 -0
- package/dist/index.js +2138 -501
- package/dist/index.js.map +1 -1
- package/dist/main.js +2144 -506
- package/dist/main.js.map +1 -1
- package/dist/mcp-server.js +1766 -310
- package/dist/mcp-server.js.map +1 -1
- package/package.json +1 -1
- package/config/protocols/dex/balancer.toml +0 -14
- package/config/protocols/dex/curve.toml +0 -12
- package/config/protocols/dex/hyperswap.toml +0 -14
- package/config/protocols/dex/hyperswap_v2.toml +0 -14
- package/config/protocols/dex/ring_few.toml +0 -14
- package/config/protocols/dex/woofi.toml +0 -12
package/dist/main.js
CHANGED
|
@@ -1023,6 +1023,24 @@ var Registry = class _Registry {
|
|
|
1023
1023
|
if (!token) throw new Error(`Token not found: ${symbol}`);
|
|
1024
1024
|
return token;
|
|
1025
1025
|
}
|
|
1026
|
+
/**
|
|
1027
|
+
* Resolve a pool by name (e.g. "WHYPE/USDC") from a protocol's pool list.
|
|
1028
|
+
* Returns the pool info or throws if not found.
|
|
1029
|
+
*/
|
|
1030
|
+
resolvePool(protocolSlug, poolName) {
|
|
1031
|
+
const protocol = this.getProtocol(protocolSlug);
|
|
1032
|
+
if (!protocol.pools || protocol.pools.length === 0) {
|
|
1033
|
+
throw new Error(`Protocol ${protocol.name} has no pools configured`);
|
|
1034
|
+
}
|
|
1035
|
+
const pool = protocol.pools.find(
|
|
1036
|
+
(p) => p.name.toLowerCase() === poolName.toLowerCase()
|
|
1037
|
+
);
|
|
1038
|
+
if (!pool) {
|
|
1039
|
+
const available = protocol.pools.map((p) => p.name).join(", ");
|
|
1040
|
+
throw new Error(`Pool '${poolName}' not found in ${protocol.name}. Available: ${available}`);
|
|
1041
|
+
}
|
|
1042
|
+
return pool;
|
|
1043
|
+
}
|
|
1026
1044
|
};
|
|
1027
1045
|
|
|
1028
1046
|
// src/executor.ts
|
|
@@ -1133,8 +1151,11 @@ var Executor = class _Executor {
|
|
|
1133
1151
|
return buffered > MAX_GAS_LIMIT ? MAX_GAS_LIMIT : buffered;
|
|
1134
1152
|
}
|
|
1135
1153
|
} catch {
|
|
1154
|
+
if (tx.gas_estimate) {
|
|
1155
|
+
return _Executor.applyGasBuffer(BigInt(tx.gas_estimate));
|
|
1156
|
+
}
|
|
1136
1157
|
}
|
|
1137
|
-
return
|
|
1158
|
+
return 0n;
|
|
1138
1159
|
}
|
|
1139
1160
|
/** Simulate a transaction via eth_call + eth_estimateGas */
|
|
1140
1161
|
async simulate(tx) {
|
|
@@ -1257,6 +1278,31 @@ var Executor = class _Executor {
|
|
|
1257
1278
|
}
|
|
1258
1279
|
const publicClient = createPublicClient2({ transport: http2(rpcUrl) });
|
|
1259
1280
|
const walletClient = createWalletClient({ account, transport: http2(rpcUrl) });
|
|
1281
|
+
if (tx.pre_txs && tx.pre_txs.length > 0) {
|
|
1282
|
+
for (const preTx of tx.pre_txs) {
|
|
1283
|
+
process.stderr.write(` Pre-tx: ${preTx.description}...
|
|
1284
|
+
`);
|
|
1285
|
+
const preGas = await this.estimateGasWithBuffer(rpcUrl, preTx, account.address);
|
|
1286
|
+
const preTxHash = await walletClient.sendTransaction({
|
|
1287
|
+
chain: null,
|
|
1288
|
+
to: preTx.to,
|
|
1289
|
+
data: preTx.data,
|
|
1290
|
+
value: preTx.value,
|
|
1291
|
+
gas: preGas > 0n ? preGas : void 0
|
|
1292
|
+
});
|
|
1293
|
+
const preTxUrl = this.explorerUrl ? `${this.explorerUrl}/tx/${preTxHash}` : void 0;
|
|
1294
|
+
process.stderr.write(` Pre-tx sent: ${preTxHash}
|
|
1295
|
+
`);
|
|
1296
|
+
if (preTxUrl) process.stderr.write(` Explorer: ${preTxUrl}
|
|
1297
|
+
`);
|
|
1298
|
+
const preReceipt = await publicClient.waitForTransactionReceipt({ hash: preTxHash });
|
|
1299
|
+
if (preReceipt.status !== "success") {
|
|
1300
|
+
throw new DefiError("TX_FAILED", `Pre-transaction failed: ${preTx.description}`);
|
|
1301
|
+
}
|
|
1302
|
+
process.stderr.write(` Pre-tx confirmed
|
|
1303
|
+
`);
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1260
1306
|
if (tx.approvals && tx.approvals.length > 0) {
|
|
1261
1307
|
for (const approval of tx.approvals) {
|
|
1262
1308
|
await this.checkAndApprove(
|
|
@@ -1294,20 +1340,37 @@ var Executor = class _Executor {
|
|
|
1294
1340
|
process.stderr.write("Waiting for confirmation...\n");
|
|
1295
1341
|
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
1296
1342
|
const status = receipt.status === "success" ? "confirmed" : "failed";
|
|
1343
|
+
let mintedTokenId;
|
|
1344
|
+
if (receipt.status === "success" && receipt.logs) {
|
|
1345
|
+
const TRANSFER_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
|
|
1346
|
+
const ZERO_TOPIC = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
1347
|
+
for (const log of receipt.logs) {
|
|
1348
|
+
if (log.topics.length >= 4 && log.topics[0] === TRANSFER_TOPIC && log.topics[1] === ZERO_TOPIC) {
|
|
1349
|
+
mintedTokenId = BigInt(log.topics[3]).toString();
|
|
1350
|
+
break;
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
const details = {
|
|
1355
|
+
to: tx.to,
|
|
1356
|
+
from: account.address,
|
|
1357
|
+
block_number: receipt.blockNumber?.toString(),
|
|
1358
|
+
gas_limit: gasLimit.toString(),
|
|
1359
|
+
gas_used: receipt.gasUsed?.toString(),
|
|
1360
|
+
explorer_url: txUrl,
|
|
1361
|
+
mode: "broadcast"
|
|
1362
|
+
};
|
|
1363
|
+
if (mintedTokenId) {
|
|
1364
|
+
details.minted_token_id = mintedTokenId;
|
|
1365
|
+
process.stderr.write(` Minted NFT tokenId: ${mintedTokenId}
|
|
1366
|
+
`);
|
|
1367
|
+
}
|
|
1297
1368
|
return {
|
|
1298
1369
|
tx_hash: txHash,
|
|
1299
1370
|
status,
|
|
1300
1371
|
gas_used: receipt.gasUsed ? Number(receipt.gasUsed) : void 0,
|
|
1301
1372
|
description: tx.description,
|
|
1302
|
-
details
|
|
1303
|
-
to: tx.to,
|
|
1304
|
-
from: account.address,
|
|
1305
|
-
block_number: receipt.blockNumber?.toString(),
|
|
1306
|
-
gas_limit: gasLimit.toString(),
|
|
1307
|
-
gas_used: receipt.gasUsed?.toString(),
|
|
1308
|
-
explorer_url: txUrl,
|
|
1309
|
-
mode: "broadcast"
|
|
1310
|
-
}
|
|
1373
|
+
details
|
|
1311
1374
|
};
|
|
1312
1375
|
}
|
|
1313
1376
|
};
|
|
@@ -1851,32 +1914,45 @@ import { encodeFunctionData as encodeFunctionData32, parseAbi as parseAbi32, cre
|
|
|
1851
1914
|
import { encodeFunctionData as encodeFunctionData42, parseAbi as parseAbi42, zeroAddress as zeroAddress2 } from "viem";
|
|
1852
1915
|
import { encodeFunctionData as encodeFunctionData5, parseAbi as parseAbi5 } from "viem";
|
|
1853
1916
|
import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6, decodeAbiParameters as decodeAbiParameters4 } from "viem";
|
|
1854
|
-
import { encodeFunctionData as encodeFunctionData7, parseAbi as parseAbi7, zeroAddress as zeroAddress3 } from "viem";
|
|
1855
|
-
import { createPublicClient as
|
|
1856
|
-
import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9,
|
|
1917
|
+
import { encodeFunctionData as encodeFunctionData7, parseAbi as parseAbi7, createPublicClient as createPublicClient42, http as http42, zeroAddress as zeroAddress3 } from "viem";
|
|
1918
|
+
import { createPublicClient as createPublicClient5, decodeFunctionResult as decodeFunctionResult22, encodeFunctionData as encodeFunctionData8, http as http5, parseAbi as parseAbi8, zeroAddress as zeroAddress4 } from "viem";
|
|
1919
|
+
import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9, zeroAddress as zeroAddress5 } from "viem";
|
|
1920
|
+
import { createPublicClient as createPublicClient6, decodeFunctionResult as decodeFunctionResult3, encodeFunctionData as encodeFunctionData10, http as http6, parseAbi as parseAbi10, zeroAddress as zeroAddress6 } from "viem";
|
|
1921
|
+
import { encodeFunctionData as encodeFunctionData11, parseAbi as parseAbi11, createPublicClient as createPublicClient7, http as http7 } from "viem";
|
|
1857
1922
|
import {
|
|
1858
|
-
encodeFunctionData as
|
|
1859
|
-
decodeFunctionResult as
|
|
1860
|
-
parseAbi as
|
|
1861
|
-
createPublicClient as
|
|
1862
|
-
http as
|
|
1923
|
+
encodeFunctionData as encodeFunctionData12,
|
|
1924
|
+
decodeFunctionResult as decodeFunctionResult4,
|
|
1925
|
+
parseAbi as parseAbi12,
|
|
1926
|
+
createPublicClient as createPublicClient8,
|
|
1927
|
+
http as http8
|
|
1863
1928
|
} from "viem";
|
|
1864
|
-
import {
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
import { createPublicClient as
|
|
1876
|
-
import { createPublicClient as
|
|
1929
|
+
import {
|
|
1930
|
+
decodeAbiParameters as decodeAbiParameters5,
|
|
1931
|
+
encodeFunctionData as encodeFunctionData13,
|
|
1932
|
+
encodeAbiParameters,
|
|
1933
|
+
http as http9,
|
|
1934
|
+
createPublicClient as createPublicClient9,
|
|
1935
|
+
keccak256,
|
|
1936
|
+
parseAbi as parseAbi13,
|
|
1937
|
+
decodeFunctionResult as decodeFunctionResult5,
|
|
1938
|
+
zeroAddress as zeroAddress7
|
|
1939
|
+
} from "viem";
|
|
1940
|
+
import { createPublicClient as createPublicClient10, http as http10, parseAbi as parseAbi14, encodeFunctionData as encodeFunctionData14, decodeFunctionResult as decodeFunctionResult6, zeroAddress as zeroAddress8 } from "viem";
|
|
1941
|
+
import { createPublicClient as createPublicClient11, http as http11, parseAbi as parseAbi15, encodeFunctionData as encodeFunctionData15, zeroAddress as zeroAddress9 } from "viem";
|
|
1942
|
+
import { createPublicClient as createPublicClient12, http as http12, parseAbi as parseAbi16 } from "viem";
|
|
1943
|
+
import { createPublicClient as createPublicClient13, http as http13, parseAbi as parseAbi17, encodeFunctionData as encodeFunctionData16 } from "viem";
|
|
1944
|
+
import { createPublicClient as createPublicClient14, http as http14, parseAbi as parseAbi18, encodeFunctionData as encodeFunctionData17 } from "viem";
|
|
1945
|
+
import { createPublicClient as createPublicClient15, http as http15, parseAbi as parseAbi19, encodeFunctionData as encodeFunctionData18 } from "viem";
|
|
1946
|
+
import { parseAbi as parseAbi20, encodeFunctionData as encodeFunctionData19, decodeFunctionResult as decodeFunctionResult7, zeroAddress as zeroAddress10 } from "viem";
|
|
1947
|
+
import { createPublicClient as createPublicClient16, http as http16, parseAbi as parseAbi21, encodeFunctionData as encodeFunctionData20, zeroAddress as zeroAddress11 } from "viem";
|
|
1948
|
+
import { createPublicClient as createPublicClient17, http as http17, parseAbi as parseAbi222 } from "viem";
|
|
1949
|
+
import { createPublicClient as createPublicClient18, http as http18, parseAbi as parseAbi23, encodeFunctionData as encodeFunctionData21 } from "viem";
|
|
1877
1950
|
import { parseAbi as parseAbi24, encodeFunctionData as encodeFunctionData222 } from "viem";
|
|
1878
|
-
import { parseAbi as parseAbi25, encodeFunctionData as encodeFunctionData23 } from "viem";
|
|
1879
|
-
import { createPublicClient as
|
|
1951
|
+
import { createPublicClient as createPublicClient19, http as http19, parseAbi as parseAbi25, encodeFunctionData as encodeFunctionData23, zeroAddress as zeroAddress12 } from "viem";
|
|
1952
|
+
import { createPublicClient as createPublicClient20, http as http20, parseAbi as parseAbi26, encodeFunctionData as encodeFunctionData24, zeroAddress as zeroAddress13 } from "viem";
|
|
1953
|
+
import { parseAbi as parseAbi27, encodeFunctionData as encodeFunctionData25 } from "viem";
|
|
1954
|
+
import { parseAbi as parseAbi28, encodeFunctionData as encodeFunctionData26 } from "viem";
|
|
1955
|
+
import { createPublicClient as createPublicClient21, http as http21, parseAbi as parseAbi29 } from "viem";
|
|
1880
1956
|
var DEFAULT_FEE = 3e3;
|
|
1881
1957
|
var swapRouterAbi = parseAbi4([
|
|
1882
1958
|
"struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; }",
|
|
@@ -2328,6 +2404,22 @@ var UniswapV2Adapter = class {
|
|
|
2328
2404
|
};
|
|
2329
2405
|
}
|
|
2330
2406
|
};
|
|
2407
|
+
function pctToTickDelta(pct) {
|
|
2408
|
+
return Math.round(Math.log(1 + pct / 100) / Math.log(1.0001));
|
|
2409
|
+
}
|
|
2410
|
+
function alignTickDown(tick, tickSpacing) {
|
|
2411
|
+
return Math.floor(tick / tickSpacing) * tickSpacing;
|
|
2412
|
+
}
|
|
2413
|
+
function alignTickUp(tick, tickSpacing) {
|
|
2414
|
+
return Math.ceil(tick / tickSpacing) * tickSpacing;
|
|
2415
|
+
}
|
|
2416
|
+
function rangeToTicks(currentTick, rangePct, tickSpacing) {
|
|
2417
|
+
const delta = pctToTickDelta(rangePct);
|
|
2418
|
+
return {
|
|
2419
|
+
tickLower: alignTickDown(currentTick - delta, tickSpacing),
|
|
2420
|
+
tickUpper: alignTickUp(currentTick + delta, tickSpacing)
|
|
2421
|
+
};
|
|
2422
|
+
}
|
|
2331
2423
|
var abi2 = parseAbi32([
|
|
2332
2424
|
"struct ExactInputSingleParams { address tokenIn; address tokenOut; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 limitSqrtPrice; }",
|
|
2333
2425
|
"function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut)"
|
|
@@ -2338,7 +2430,11 @@ var algebraQuoterAbi = parseAbi32([
|
|
|
2338
2430
|
var algebraSingleQuoterAbi = parseAbi32([
|
|
2339
2431
|
"function quoteExactInputSingle((address tokenIn, address tokenOut, uint256 amountIn, uint160 limitSqrtPrice) params) external returns (uint256 amountOut, uint256 amountIn, uint160 sqrtPriceX96After)"
|
|
2340
2432
|
]);
|
|
2341
|
-
var
|
|
2433
|
+
var algebraIntegralPmAbi = parseAbi32([
|
|
2434
|
+
"struct MintParams { address token0; address token1; address deployer; int24 tickLower; int24 tickUpper; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; address recipient; uint256 deadline; }",
|
|
2435
|
+
"function mint(MintParams calldata params) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1)"
|
|
2436
|
+
]);
|
|
2437
|
+
var algebraV2PmAbi = parseAbi32([
|
|
2342
2438
|
"struct MintParams { address token0; address token1; int24 tickLower; int24 tickUpper; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; address recipient; uint256 deadline; }",
|
|
2343
2439
|
"function mint(MintParams calldata params) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1)"
|
|
2344
2440
|
]);
|
|
@@ -2483,36 +2579,58 @@ var AlgebraV3Adapter = class {
|
|
|
2483
2579
|
throw new DefiError("CONTRACT_ERROR", "Position manager address not configured");
|
|
2484
2580
|
}
|
|
2485
2581
|
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];
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
const
|
|
2489
|
-
|
|
2582
|
+
let tickLower = params.tick_lower ?? -887220;
|
|
2583
|
+
let tickUpper = params.tick_upper ?? 887220;
|
|
2584
|
+
const isSingleSide = rawAmount0 === 0n || rawAmount1 === 0n;
|
|
2585
|
+
const needsAutoTick = params.range_pct !== void 0 || isSingleSide && !params.tick_lower && !params.tick_upper;
|
|
2586
|
+
if (needsAutoTick) {
|
|
2587
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC URL required for auto tick detection");
|
|
2588
|
+
const poolAddr = params.pool;
|
|
2589
|
+
if (!poolAddr) throw new DefiError("CONTRACT_ERROR", "Pool address required (use --pool)");
|
|
2590
|
+
const client = createPublicClient32({ transport: http32(this.rpcUrl) });
|
|
2591
|
+
const algebraPoolAbi = parseAbi32([
|
|
2592
|
+
"function globalState() view returns (uint160 price, int24 tick, uint16 lastFee, uint8 pluginConfig, uint16 communityFee, bool unlocked)",
|
|
2593
|
+
"function tickSpacing() view returns (int24)"
|
|
2594
|
+
]);
|
|
2595
|
+
const [globalState, spacing] = await Promise.all([
|
|
2596
|
+
client.readContract({ address: poolAddr, abi: algebraPoolAbi, functionName: "globalState" }),
|
|
2597
|
+
client.readContract({ address: poolAddr, abi: algebraPoolAbi, functionName: "tickSpacing" })
|
|
2598
|
+
]);
|
|
2599
|
+
const currentTick = Number(globalState[1]);
|
|
2600
|
+
const tickSpace = Number(spacing);
|
|
2601
|
+
if (params.range_pct !== void 0) {
|
|
2602
|
+
const range = rangeToTicks(currentTick, params.range_pct, tickSpace);
|
|
2603
|
+
tickLower = range.tickLower;
|
|
2604
|
+
tickUpper = range.tickUpper;
|
|
2605
|
+
} else if (rawAmount0 > 0n && rawAmount1 === 0n) {
|
|
2606
|
+
tickLower = alignTickUp(currentTick + tickSpace, tickSpace);
|
|
2607
|
+
tickUpper = 887220;
|
|
2608
|
+
} else {
|
|
2609
|
+
tickLower = -887220;
|
|
2610
|
+
tickUpper = alignTickDown(currentTick - tickSpace, tickSpace);
|
|
2611
|
+
}
|
|
2612
|
+
}
|
|
2613
|
+
const amount0 = rawAmount0;
|
|
2614
|
+
const amount1 = rawAmount1;
|
|
2615
|
+
const data = this.useSingleQuoter ? encodeFunctionData32({
|
|
2616
|
+
abi: algebraV2PmAbi,
|
|
2490
2617
|
functionName: "mint",
|
|
2491
|
-
args: [
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
tickUpper: 887220,
|
|
2497
|
-
amount0Desired: amount0,
|
|
2498
|
-
amount1Desired: amount1,
|
|
2499
|
-
amount0Min: 0n,
|
|
2500
|
-
amount1Min: 0n,
|
|
2501
|
-
recipient: params.recipient,
|
|
2502
|
-
deadline: BigInt("18446744073709551615")
|
|
2503
|
-
}
|
|
2504
|
-
]
|
|
2618
|
+
args: [{ token0, token1, tickLower, tickUpper, amount0Desired: amount0, amount1Desired: amount1, amount0Min: 0n, amount1Min: 0n, recipient: params.recipient, deadline: BigInt("18446744073709551615") }]
|
|
2619
|
+
}) : encodeFunctionData32({
|
|
2620
|
+
abi: algebraIntegralPmAbi,
|
|
2621
|
+
functionName: "mint",
|
|
2622
|
+
args: [{ token0, token1, deployer: zeroAddress, tickLower, tickUpper, amount0Desired: amount0, amount1Desired: amount1, amount0Min: 0n, amount1Min: 0n, recipient: params.recipient, deadline: BigInt("18446744073709551615") }]
|
|
2505
2623
|
});
|
|
2624
|
+
const approvals = [];
|
|
2625
|
+
if (amount0 > 0n) approvals.push({ token: token0, spender: pm, amount: amount0 });
|
|
2626
|
+
if (amount1 > 0n) approvals.push({ token: token1, spender: pm, amount: amount1 });
|
|
2506
2627
|
return {
|
|
2507
|
-
description: `[${this.protocolName}] Add liquidity`,
|
|
2628
|
+
description: `[${this.protocolName}] Add liquidity [${tickLower}, ${tickUpper}]`,
|
|
2508
2629
|
to: pm,
|
|
2509
2630
|
data,
|
|
2510
2631
|
value: 0n,
|
|
2511
2632
|
gas_estimate: 5e5,
|
|
2512
|
-
approvals
|
|
2513
|
-
{ token: token0, spender: pm, amount: amount0 },
|
|
2514
|
-
{ token: token1, spender: pm, amount: amount1 }
|
|
2515
|
-
]
|
|
2633
|
+
approvals
|
|
2516
2634
|
};
|
|
2517
2635
|
}
|
|
2518
2636
|
async buildRemoveLiquidity(_params) {
|
|
@@ -2804,228 +2922,1105 @@ var SolidlyAdapter = class {
|
|
|
2804
2922
|
};
|
|
2805
2923
|
}
|
|
2806
2924
|
};
|
|
2807
|
-
var
|
|
2808
|
-
"
|
|
2925
|
+
var thenaPmAbi = parseAbi7([
|
|
2926
|
+
"struct MintParams { address token0; address token1; int24 tickSpacing; int24 tickLower; int24 tickUpper; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; address recipient; uint256 deadline; uint160 sqrtPriceX96; }",
|
|
2927
|
+
"function mint(MintParams calldata params) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1)"
|
|
2809
2928
|
]);
|
|
2810
|
-
var
|
|
2929
|
+
var thenaRouterAbi = parseAbi7([
|
|
2930
|
+
"struct ExactInputSingleParams { address tokenIn; address tokenOut; int24 tickSpacing; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; }",
|
|
2931
|
+
"function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut)"
|
|
2932
|
+
]);
|
|
2933
|
+
var thenaPoolAbi = parseAbi7([
|
|
2934
|
+
"function slot0() view returns (uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, bool unlocked)",
|
|
2935
|
+
"function tickSpacing() view returns (int24)",
|
|
2936
|
+
"function token0() view returns (address)",
|
|
2937
|
+
"function token1() view returns (address)"
|
|
2938
|
+
]);
|
|
2939
|
+
var thenaFactoryAbi = parseAbi7([
|
|
2940
|
+
"function getPool(address tokenA, address tokenB, int24 tickSpacing) view returns (address)"
|
|
2941
|
+
]);
|
|
2942
|
+
var ThenaCLAdapter = class {
|
|
2811
2943
|
protocolName;
|
|
2812
2944
|
router;
|
|
2813
|
-
|
|
2945
|
+
positionManager;
|
|
2946
|
+
factory;
|
|
2947
|
+
rpcUrl;
|
|
2948
|
+
defaultTickSpacing;
|
|
2949
|
+
constructor(entry, rpcUrl) {
|
|
2814
2950
|
this.protocolName = entry.name;
|
|
2815
2951
|
const router = entry.contracts?.["router"];
|
|
2816
|
-
if (!router)
|
|
2817
|
-
throw new DefiError("CONTRACT_ERROR", "Missing 'router' contract");
|
|
2818
|
-
}
|
|
2952
|
+
if (!router) throw new DefiError("CONTRACT_ERROR", "Missing 'router' contract address");
|
|
2819
2953
|
this.router = router;
|
|
2954
|
+
this.positionManager = entry.contracts?.["position_manager"];
|
|
2955
|
+
this.factory = entry.contracts?.["pool_factory"];
|
|
2956
|
+
this.rpcUrl = rpcUrl;
|
|
2957
|
+
this.defaultTickSpacing = 50;
|
|
2820
2958
|
}
|
|
2821
2959
|
name() {
|
|
2822
2960
|
return this.protocolName;
|
|
2823
2961
|
}
|
|
2824
2962
|
async buildSwap(params) {
|
|
2825
|
-
const minToAmount = 0n;
|
|
2826
2963
|
const data = encodeFunctionData7({
|
|
2827
|
-
abi:
|
|
2828
|
-
functionName: "
|
|
2829
|
-
args: [
|
|
2830
|
-
params.token_in,
|
|
2831
|
-
params.token_out,
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
params.
|
|
2835
|
-
|
|
2836
|
-
|
|
2964
|
+
abi: thenaRouterAbi,
|
|
2965
|
+
functionName: "exactInputSingle",
|
|
2966
|
+
args: [{
|
|
2967
|
+
tokenIn: params.token_in,
|
|
2968
|
+
tokenOut: params.token_out,
|
|
2969
|
+
tickSpacing: this.defaultTickSpacing,
|
|
2970
|
+
recipient: params.recipient,
|
|
2971
|
+
deadline: BigInt(params.deadline ?? 18446744073709551615n),
|
|
2972
|
+
amountIn: params.amount_in,
|
|
2973
|
+
amountOutMinimum: 0n,
|
|
2974
|
+
sqrtPriceLimitX96: 0n
|
|
2975
|
+
}]
|
|
2837
2976
|
});
|
|
2838
2977
|
return {
|
|
2839
|
-
description: `[${this.protocolName}] Swap
|
|
2978
|
+
description: `[${this.protocolName}] Swap`,
|
|
2840
2979
|
to: this.router,
|
|
2841
2980
|
data,
|
|
2842
2981
|
value: 0n,
|
|
2843
|
-
gas_estimate:
|
|
2982
|
+
gas_estimate: 3e5,
|
|
2983
|
+
approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
|
|
2844
2984
|
};
|
|
2845
2985
|
}
|
|
2846
2986
|
async quote(_params) {
|
|
2847
|
-
throw DefiError.unsupported(`[${this.protocolName}] quote
|
|
2987
|
+
throw DefiError.unsupported(`[${this.protocolName}] quote not yet implemented \u2014 use swap router`);
|
|
2848
2988
|
}
|
|
2849
|
-
async buildAddLiquidity(
|
|
2850
|
-
|
|
2989
|
+
async buildAddLiquidity(params) {
|
|
2990
|
+
const pm = this.positionManager;
|
|
2991
|
+
if (!pm) throw new DefiError("CONTRACT_ERROR", "Position manager not configured");
|
|
2992
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC URL required");
|
|
2993
|
+
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];
|
|
2994
|
+
const client = createPublicClient42({ transport: http42(this.rpcUrl) });
|
|
2995
|
+
const poolAddr = params.pool;
|
|
2996
|
+
let tickSpacing = this.defaultTickSpacing;
|
|
2997
|
+
let tickLower = params.tick_lower ?? 0;
|
|
2998
|
+
let tickUpper = params.tick_upper ?? 0;
|
|
2999
|
+
if (poolAddr || !params.tick_lower || !params.tick_upper) {
|
|
3000
|
+
let pool = poolAddr;
|
|
3001
|
+
if (!pool && this.factory) {
|
|
3002
|
+
pool = await client.readContract({
|
|
3003
|
+
address: this.factory,
|
|
3004
|
+
abi: thenaFactoryAbi,
|
|
3005
|
+
functionName: "getPool",
|
|
3006
|
+
args: [token0, token1, tickSpacing]
|
|
3007
|
+
});
|
|
3008
|
+
if (pool === zeroAddress3) throw new DefiError("CONTRACT_ERROR", "Pool not found");
|
|
3009
|
+
}
|
|
3010
|
+
if (pool) {
|
|
3011
|
+
const [slot0, ts] = await Promise.all([
|
|
3012
|
+
client.readContract({ address: pool, abi: thenaPoolAbi, functionName: "slot0" }),
|
|
3013
|
+
client.readContract({ address: pool, abi: thenaPoolAbi, functionName: "tickSpacing" })
|
|
3014
|
+
]);
|
|
3015
|
+
const currentTick = Number(slot0[1]);
|
|
3016
|
+
tickSpacing = Number(ts);
|
|
3017
|
+
if (params.range_pct !== void 0) {
|
|
3018
|
+
const range = rangeToTicks(currentTick, params.range_pct, tickSpacing);
|
|
3019
|
+
tickLower = range.tickLower;
|
|
3020
|
+
tickUpper = range.tickUpper;
|
|
3021
|
+
} else if (!params.tick_lower && !params.tick_upper) {
|
|
3022
|
+
const isSingleSide = rawAmount0 === 0n || rawAmount1 === 0n;
|
|
3023
|
+
if (isSingleSide) {
|
|
3024
|
+
if (rawAmount0 > 0n) {
|
|
3025
|
+
tickLower = alignTickUp(currentTick + tickSpacing, tickSpacing);
|
|
3026
|
+
tickUpper = Math.floor(887272 / tickSpacing) * tickSpacing;
|
|
3027
|
+
} else {
|
|
3028
|
+
tickLower = Math.ceil(-887272 / tickSpacing) * tickSpacing;
|
|
3029
|
+
tickUpper = alignTickDown(currentTick - tickSpacing, tickSpacing);
|
|
3030
|
+
}
|
|
3031
|
+
} else {
|
|
3032
|
+
tickLower = Math.ceil(-887272 / tickSpacing) * tickSpacing;
|
|
3033
|
+
tickUpper = Math.floor(887272 / tickSpacing) * tickSpacing;
|
|
3034
|
+
}
|
|
3035
|
+
}
|
|
3036
|
+
}
|
|
3037
|
+
}
|
|
3038
|
+
if (params.tick_lower !== void 0) tickLower = params.tick_lower;
|
|
3039
|
+
if (params.tick_upper !== void 0) tickUpper = params.tick_upper;
|
|
3040
|
+
const data = encodeFunctionData7({
|
|
3041
|
+
abi: thenaPmAbi,
|
|
3042
|
+
functionName: "mint",
|
|
3043
|
+
args: [{
|
|
3044
|
+
token0,
|
|
3045
|
+
token1,
|
|
3046
|
+
tickSpacing,
|
|
3047
|
+
tickLower,
|
|
3048
|
+
tickUpper,
|
|
3049
|
+
amount0Desired: rawAmount0,
|
|
3050
|
+
amount1Desired: rawAmount1,
|
|
3051
|
+
amount0Min: 0n,
|
|
3052
|
+
amount1Min: 0n,
|
|
3053
|
+
recipient: params.recipient,
|
|
3054
|
+
deadline: BigInt("18446744073709551615"),
|
|
3055
|
+
sqrtPriceX96: 0n
|
|
3056
|
+
}]
|
|
3057
|
+
});
|
|
3058
|
+
const approvals = [];
|
|
3059
|
+
if (rawAmount0 > 0n) approvals.push({ token: token0, spender: pm, amount: rawAmount0 });
|
|
3060
|
+
if (rawAmount1 > 0n) approvals.push({ token: token1, spender: pm, amount: rawAmount1 });
|
|
3061
|
+
return {
|
|
3062
|
+
description: `[${this.protocolName}] Add liquidity [${tickLower}, ${tickUpper}]`,
|
|
3063
|
+
to: pm,
|
|
3064
|
+
data,
|
|
3065
|
+
value: 0n,
|
|
3066
|
+
gas_estimate: 7e5,
|
|
3067
|
+
approvals
|
|
3068
|
+
};
|
|
2851
3069
|
}
|
|
2852
3070
|
async buildRemoveLiquidity(_params) {
|
|
2853
|
-
throw DefiError.unsupported(`[${this.protocolName}]
|
|
3071
|
+
throw DefiError.unsupported(`[${this.protocolName}] remove_liquidity requires tokenId`);
|
|
2854
3072
|
}
|
|
2855
3073
|
};
|
|
2856
|
-
var
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
3074
|
+
var _addressDecodeAbi = parseAbi8(["function f() external view returns (address)"]);
|
|
3075
|
+
function decodeAddress(data) {
|
|
3076
|
+
if (!data) return null;
|
|
3077
|
+
try {
|
|
3078
|
+
return decodeFunctionResult22({ abi: _addressDecodeAbi, functionName: "f", data });
|
|
3079
|
+
} catch {
|
|
3080
|
+
return null;
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
var _symbolDecodeAbi = parseAbi8(["function symbol() external view returns (string)"]);
|
|
3084
|
+
function decodeSymbol(data) {
|
|
3085
|
+
if (!data) return "?";
|
|
3086
|
+
try {
|
|
3087
|
+
return decodeFunctionResult22({ abi: _symbolDecodeAbi, functionName: "symbol", data });
|
|
3088
|
+
} catch {
|
|
3089
|
+
return "?";
|
|
3090
|
+
}
|
|
3091
|
+
}
|
|
3092
|
+
var gaugeManagerAbi = parseAbi8([
|
|
3093
|
+
"function gauges(address pool) view returns (address gauge)",
|
|
3094
|
+
"function isGauge(address gauge) view returns (bool)",
|
|
3095
|
+
"function isAlive(address gauge) view returns (bool)",
|
|
3096
|
+
"function claimRewards(address gauge, uint256[] tokenIds, uint8 redeemType) external"
|
|
3097
|
+
]);
|
|
3098
|
+
var gaugeCLAbi = parseAbi8([
|
|
3099
|
+
"function deposit(uint256 tokenId) external",
|
|
3100
|
+
"function withdraw(uint256 tokenId, uint8 redeemType) external",
|
|
3101
|
+
"function earned(uint256 tokenId) view returns (uint256)",
|
|
3102
|
+
"function balanceOf(uint256 tokenId) view returns (uint256)",
|
|
3103
|
+
"function rewardToken() view returns (address)"
|
|
3104
|
+
]);
|
|
3105
|
+
var nfpmAbi = parseAbi8([
|
|
3106
|
+
"function approve(address to, uint256 tokenId) external",
|
|
3107
|
+
"function getApproved(uint256 tokenId) view returns (address)"
|
|
2868
3108
|
]);
|
|
2869
3109
|
var veAbi = parseAbi8([
|
|
2870
3110
|
"function create_lock(uint256 value, uint256 lock_duration) external returns (uint256)",
|
|
2871
3111
|
"function increase_amount(uint256 tokenId, uint256 value) external",
|
|
2872
3112
|
"function increase_unlock_time(uint256 tokenId, uint256 lock_duration) external",
|
|
2873
|
-
"function withdraw(uint256 tokenId) external"
|
|
2874
|
-
"function balanceOfNFT(uint256 tokenId) external view returns (uint256)",
|
|
2875
|
-
"function locked(uint256 tokenId) external view returns (uint256 amount, uint256 end)"
|
|
3113
|
+
"function withdraw(uint256 tokenId) external"
|
|
2876
3114
|
]);
|
|
2877
3115
|
var voterAbi = parseAbi8([
|
|
2878
|
-
"function vote(uint256 tokenId, address[]
|
|
2879
|
-
"function claimBribes(address[]
|
|
2880
|
-
"function claimFees(address[]
|
|
2881
|
-
"function gauges(address pool) external view returns (address)"
|
|
3116
|
+
"function vote(uint256 tokenId, address[] pools, uint256[] weights) external",
|
|
3117
|
+
"function claimBribes(address[] bribes, address[][] tokens, uint256 tokenId) external",
|
|
3118
|
+
"function claimFees(address[] fees, address[][] tokens, uint256 tokenId) external"
|
|
2882
3119
|
]);
|
|
2883
|
-
var
|
|
3120
|
+
var HybraGaugeAdapter = class {
|
|
2884
3121
|
protocolName;
|
|
2885
|
-
|
|
3122
|
+
gaugeManager;
|
|
2886
3123
|
veToken;
|
|
3124
|
+
voter;
|
|
3125
|
+
positionManager;
|
|
3126
|
+
poolFactory;
|
|
2887
3127
|
rpcUrl;
|
|
2888
3128
|
constructor(entry, rpcUrl) {
|
|
2889
3129
|
this.protocolName = entry.name;
|
|
2890
|
-
const
|
|
2891
|
-
if (!
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
this.
|
|
2899
|
-
this.veToken = veToken;
|
|
3130
|
+
const gm = entry.contracts?.["gauge_manager"];
|
|
3131
|
+
if (!gm) throw new DefiError("CONTRACT_ERROR", "Missing 'gauge_manager' contract");
|
|
3132
|
+
this.gaugeManager = gm;
|
|
3133
|
+
const ve = entry.contracts?.["ve_token"];
|
|
3134
|
+
if (!ve) throw new DefiError("CONTRACT_ERROR", "Missing 've_token' contract");
|
|
3135
|
+
this.veToken = ve;
|
|
3136
|
+
this.voter = entry.contracts?.["voter"] ?? zeroAddress4;
|
|
3137
|
+
this.positionManager = entry.contracts?.["position_manager"] ?? zeroAddress4;
|
|
3138
|
+
this.poolFactory = entry.contracts?.["pool_factory"];
|
|
2900
3139
|
this.rpcUrl = rpcUrl;
|
|
2901
3140
|
}
|
|
2902
3141
|
name() {
|
|
2903
3142
|
return this.protocolName;
|
|
2904
3143
|
}
|
|
2905
|
-
//
|
|
2906
|
-
async
|
|
2907
|
-
if (
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
3144
|
+
// ─── Gauge Discovery ──────────────────────────────────────
|
|
3145
|
+
async discoverGaugedPools() {
|
|
3146
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC URL required for gauge discovery");
|
|
3147
|
+
if (!this.poolFactory) throw new DefiError("CONTRACT_ERROR", "Missing 'pool_factory' contract");
|
|
3148
|
+
const factoryAbi = parseAbi8([
|
|
3149
|
+
"function allPoolsLength() external view returns (uint256)",
|
|
3150
|
+
"function allPools(uint256) external view returns (address)"
|
|
3151
|
+
]);
|
|
3152
|
+
const poolAbi2 = parseAbi8([
|
|
3153
|
+
"function token0() external view returns (address)",
|
|
3154
|
+
"function token1() external view returns (address)"
|
|
3155
|
+
]);
|
|
3156
|
+
const erc20SymbolAbi = parseAbi8(["function symbol() external view returns (string)"]);
|
|
3157
|
+
const gaugesAbi = parseAbi8(["function gauges(address pool) view returns (address gauge)"]);
|
|
3158
|
+
const client = createPublicClient5({ transport: http5(this.rpcUrl) });
|
|
3159
|
+
let poolCount;
|
|
3160
|
+
try {
|
|
3161
|
+
poolCount = await client.readContract({
|
|
3162
|
+
address: this.poolFactory,
|
|
3163
|
+
abi: factoryAbi,
|
|
3164
|
+
functionName: "allPoolsLength"
|
|
2912
3165
|
});
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
to: gauge,
|
|
2916
|
-
data: data2,
|
|
2917
|
-
value: 0n,
|
|
2918
|
-
gas_estimate: 2e5,
|
|
2919
|
-
approvals: lpToken ? [{ token: lpToken, spender: gauge, amount }] : void 0
|
|
2920
|
-
};
|
|
3166
|
+
} catch {
|
|
3167
|
+
return [];
|
|
2921
3168
|
}
|
|
2922
|
-
const
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
3169
|
+
const count = Number(poolCount);
|
|
3170
|
+
if (count === 0) return [];
|
|
3171
|
+
const poolAddressCalls = [];
|
|
3172
|
+
for (let i = 0; i < count; i++) {
|
|
3173
|
+
poolAddressCalls.push([
|
|
3174
|
+
this.poolFactory,
|
|
3175
|
+
encodeFunctionData8({ abi: factoryAbi, functionName: "allPools", args: [BigInt(i)] })
|
|
3176
|
+
]);
|
|
3177
|
+
}
|
|
3178
|
+
const poolAddressResults = await multicallRead(this.rpcUrl, poolAddressCalls);
|
|
3179
|
+
const pools = poolAddressResults.map((r) => decodeAddress(r)).filter((a) => a !== null && a !== zeroAddress4);
|
|
3180
|
+
if (pools.length === 0) return [];
|
|
3181
|
+
const gaugeCalls = pools.map((pool) => [
|
|
3182
|
+
this.gaugeManager,
|
|
3183
|
+
encodeFunctionData8({ abi: gaugesAbi, functionName: "gauges", args: [pool] })
|
|
3184
|
+
]);
|
|
3185
|
+
const gaugeResults = await multicallRead(this.rpcUrl, gaugeCalls);
|
|
3186
|
+
const gaugedPools = [];
|
|
3187
|
+
for (let i = 0; i < pools.length; i++) {
|
|
3188
|
+
const gauge = decodeAddress(gaugeResults[i] ?? null);
|
|
3189
|
+
if (gauge && gauge !== zeroAddress4) {
|
|
3190
|
+
gaugedPools.push({ pool: pools[i], gauge });
|
|
3191
|
+
}
|
|
3192
|
+
}
|
|
3193
|
+
if (gaugedPools.length === 0) return [];
|
|
3194
|
+
const tokenCalls = [];
|
|
3195
|
+
for (const { pool } of gaugedPools) {
|
|
3196
|
+
tokenCalls.push([pool, encodeFunctionData8({ abi: poolAbi2, functionName: "token0" })]);
|
|
3197
|
+
tokenCalls.push([pool, encodeFunctionData8({ abi: poolAbi2, functionName: "token1" })]);
|
|
3198
|
+
}
|
|
3199
|
+
const tokenResults = await multicallRead(this.rpcUrl, tokenCalls);
|
|
3200
|
+
const tokenAddrs = /* @__PURE__ */ new Set();
|
|
3201
|
+
for (let i = 0; i < gaugedPools.length; i++) {
|
|
3202
|
+
const t0 = decodeAddress(tokenResults[i * 2] ?? null);
|
|
3203
|
+
const t1 = decodeAddress(tokenResults[i * 2 + 1] ?? null);
|
|
3204
|
+
if (t0 && t0 !== zeroAddress4) tokenAddrs.add(t0);
|
|
3205
|
+
if (t1 && t1 !== zeroAddress4) tokenAddrs.add(t1);
|
|
3206
|
+
}
|
|
3207
|
+
const uniqueTokens = Array.from(tokenAddrs);
|
|
3208
|
+
const symbolCalls = uniqueTokens.map((t) => [
|
|
3209
|
+
t,
|
|
3210
|
+
encodeFunctionData8({ abi: erc20SymbolAbi, functionName: "symbol" })
|
|
3211
|
+
]);
|
|
3212
|
+
const symbolResults = await multicallRead(this.rpcUrl, symbolCalls);
|
|
3213
|
+
const symbolMap = /* @__PURE__ */ new Map();
|
|
3214
|
+
for (let i = 0; i < uniqueTokens.length; i++) {
|
|
3215
|
+
symbolMap.set(uniqueTokens[i], decodeSymbol(symbolResults[i] ?? null));
|
|
3216
|
+
}
|
|
3217
|
+
const out = [];
|
|
3218
|
+
for (let i = 0; i < gaugedPools.length; i++) {
|
|
3219
|
+
const { pool, gauge } = gaugedPools[i];
|
|
3220
|
+
const t0 = decodeAddress(tokenResults[i * 2] ?? null);
|
|
3221
|
+
const t1 = decodeAddress(tokenResults[i * 2 + 1] ?? null);
|
|
3222
|
+
out.push({
|
|
3223
|
+
pool,
|
|
3224
|
+
gauge,
|
|
3225
|
+
token0: t0 ? symbolMap.get(t0) ?? t0.slice(0, 10) : "?",
|
|
3226
|
+
token1: t1 ? symbolMap.get(t1) ?? t1.slice(0, 10) : "?",
|
|
3227
|
+
type: "CL"
|
|
3228
|
+
});
|
|
3229
|
+
}
|
|
3230
|
+
return out;
|
|
3231
|
+
}
|
|
3232
|
+
// ─── Gauge Lookup ──────────────────────────────────────────
|
|
3233
|
+
async resolveGauge(pool) {
|
|
3234
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC required");
|
|
3235
|
+
const client = createPublicClient5({ transport: http5(this.rpcUrl) });
|
|
3236
|
+
const gauge = await client.readContract({
|
|
3237
|
+
address: this.gaugeManager,
|
|
3238
|
+
abi: gaugeManagerAbi,
|
|
3239
|
+
functionName: "gauges",
|
|
3240
|
+
args: [pool]
|
|
3241
|
+
});
|
|
3242
|
+
if (gauge === zeroAddress4) throw new DefiError("CONTRACT_ERROR", `No gauge for pool ${pool}`);
|
|
3243
|
+
return gauge;
|
|
3244
|
+
}
|
|
3245
|
+
// ─── CL Gauge: NFT Deposit/Withdraw ──────────────────────────
|
|
3246
|
+
async buildDeposit(gauge, _amount, tokenId) {
|
|
3247
|
+
if (tokenId === void 0) throw new DefiError("CONTRACT_ERROR", "tokenId required for CL gauge deposit");
|
|
3248
|
+
const approveTx = {
|
|
3249
|
+
description: `[${this.protocolName}] Approve NFT #${tokenId} to gauge`,
|
|
3250
|
+
to: this.positionManager,
|
|
3251
|
+
data: encodeFunctionData8({ abi: nfpmAbi, functionName: "approve", args: [gauge, tokenId] }),
|
|
3252
|
+
value: 0n,
|
|
3253
|
+
gas_estimate: 8e4
|
|
3254
|
+
};
|
|
2927
3255
|
return {
|
|
2928
|
-
description: `[${this.protocolName}] Deposit
|
|
3256
|
+
description: `[${this.protocolName}] Deposit NFT #${tokenId} to gauge`,
|
|
2929
3257
|
to: gauge,
|
|
2930
|
-
data,
|
|
3258
|
+
data: encodeFunctionData8({ abi: gaugeCLAbi, functionName: "deposit", args: [tokenId] }),
|
|
2931
3259
|
value: 0n,
|
|
2932
|
-
gas_estimate:
|
|
2933
|
-
|
|
3260
|
+
gas_estimate: 5e5,
|
|
3261
|
+
pre_txs: [approveTx]
|
|
2934
3262
|
};
|
|
2935
3263
|
}
|
|
2936
|
-
async buildWithdraw(gauge,
|
|
2937
|
-
|
|
2938
|
-
abi: gaugeAbi,
|
|
2939
|
-
functionName: "withdraw",
|
|
2940
|
-
args: [amount]
|
|
2941
|
-
});
|
|
3264
|
+
async buildWithdraw(gauge, _amount, tokenId) {
|
|
3265
|
+
if (tokenId === void 0) throw new DefiError("CONTRACT_ERROR", "tokenId required for CL gauge withdraw");
|
|
2942
3266
|
return {
|
|
2943
|
-
description: `[${this.protocolName}] Withdraw
|
|
3267
|
+
description: `[${this.protocolName}] Withdraw NFT #${tokenId} from gauge`,
|
|
2944
3268
|
to: gauge,
|
|
2945
|
-
data,
|
|
3269
|
+
data: encodeFunctionData8({ abi: gaugeCLAbi, functionName: "withdraw", args: [tokenId, 1] }),
|
|
2946
3270
|
value: 0n,
|
|
2947
|
-
gas_estimate:
|
|
3271
|
+
gas_estimate: 1e6
|
|
2948
3272
|
};
|
|
2949
3273
|
}
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
address: gauge,
|
|
2956
|
-
abi: gaugeAbi,
|
|
2957
|
-
functionName: "rewardsListLength"
|
|
2958
|
-
});
|
|
2959
|
-
if (listLen > 0n) {
|
|
2960
|
-
const data2 = encodeFunctionData8({
|
|
2961
|
-
abi: gaugeAbi,
|
|
2962
|
-
functionName: "getReward",
|
|
2963
|
-
args: [account, []]
|
|
2964
|
-
});
|
|
2965
|
-
return {
|
|
2966
|
-
description: `[${this.protocolName}] Claim gauge rewards`,
|
|
2967
|
-
to: gauge,
|
|
2968
|
-
data: data2,
|
|
2969
|
-
value: 0n,
|
|
2970
|
-
gas_estimate: 3e5
|
|
2971
|
-
};
|
|
2972
|
-
}
|
|
2973
|
-
} catch {
|
|
2974
|
-
}
|
|
2975
|
-
}
|
|
2976
|
-
const data = encodeFunctionData8({
|
|
2977
|
-
abi: gaugeAbi,
|
|
2978
|
-
functionName: "getReward",
|
|
2979
|
-
args: [account ?? zeroAddress4]
|
|
2980
|
-
});
|
|
3274
|
+
// ─── Claim: via GaugeManager ──────────────────────────────────
|
|
3275
|
+
async buildClaimRewards(gauge, _account) {
|
|
3276
|
+
throw DefiError.unsupported(`[${this.protocolName}] Use buildClaimRewardsByTokenId for CL gauges`);
|
|
3277
|
+
}
|
|
3278
|
+
async buildClaimRewardsByTokenId(gauge, tokenId) {
|
|
2981
3279
|
return {
|
|
2982
|
-
description: `[${this.protocolName}] Claim
|
|
2983
|
-
to:
|
|
2984
|
-
data
|
|
3280
|
+
description: `[${this.protocolName}] Claim rewards for NFT #${tokenId}`,
|
|
3281
|
+
to: this.gaugeManager,
|
|
3282
|
+
data: encodeFunctionData8({
|
|
3283
|
+
abi: gaugeManagerAbi,
|
|
3284
|
+
functionName: "claimRewards",
|
|
3285
|
+
args: [gauge, [tokenId], 1]
|
|
3286
|
+
// redeemType=1
|
|
3287
|
+
}),
|
|
2985
3288
|
value: 0n,
|
|
2986
|
-
gas_estimate:
|
|
3289
|
+
gas_estimate: 1e6
|
|
2987
3290
|
};
|
|
2988
3291
|
}
|
|
2989
|
-
|
|
2990
|
-
|
|
3292
|
+
// ─── Pending Rewards ──────────────────────────────────────────
|
|
3293
|
+
async getPendingRewards(gauge, _user) {
|
|
3294
|
+
throw DefiError.unsupported(`[${this.protocolName}] Use getPendingRewardsByTokenId for CL gauges`);
|
|
2991
3295
|
}
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
const
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
3296
|
+
async getPendingRewardsByTokenId(gauge, tokenId) {
|
|
3297
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC required");
|
|
3298
|
+
const client = createPublicClient5({ transport: http5(this.rpcUrl) });
|
|
3299
|
+
return await client.readContract({
|
|
3300
|
+
address: gauge,
|
|
3301
|
+
abi: gaugeCLAbi,
|
|
3302
|
+
functionName: "earned",
|
|
3303
|
+
args: [tokenId]
|
|
2998
3304
|
});
|
|
3305
|
+
}
|
|
3306
|
+
// ─── VoteEscrow ──────────────────────────────────────────────
|
|
3307
|
+
async buildCreateLock(amount, lockDuration) {
|
|
2999
3308
|
return {
|
|
3000
|
-
description: `[${this.protocolName}] Create veNFT lock
|
|
3309
|
+
description: `[${this.protocolName}] Create veNFT lock`,
|
|
3001
3310
|
to: this.veToken,
|
|
3002
|
-
data,
|
|
3311
|
+
data: encodeFunctionData8({ abi: veAbi, functionName: "create_lock", args: [amount, BigInt(lockDuration)] }),
|
|
3003
3312
|
value: 0n,
|
|
3004
3313
|
gas_estimate: 3e5
|
|
3005
3314
|
};
|
|
3006
3315
|
}
|
|
3007
3316
|
async buildIncreaseAmount(tokenId, amount) {
|
|
3008
|
-
const data = encodeFunctionData8({
|
|
3009
|
-
abi: veAbi,
|
|
3010
|
-
functionName: "increase_amount",
|
|
3011
|
-
args: [tokenId, amount]
|
|
3012
|
-
});
|
|
3013
3317
|
return {
|
|
3014
|
-
description: `[${this.protocolName}] Increase veNFT #${tokenId}
|
|
3318
|
+
description: `[${this.protocolName}] Increase veNFT #${tokenId}`,
|
|
3015
3319
|
to: this.veToken,
|
|
3016
|
-
data,
|
|
3320
|
+
data: encodeFunctionData8({ abi: veAbi, functionName: "increase_amount", args: [tokenId, amount] }),
|
|
3017
3321
|
value: 0n,
|
|
3018
3322
|
gas_estimate: 2e5
|
|
3019
3323
|
};
|
|
3020
3324
|
}
|
|
3021
3325
|
async buildIncreaseUnlockTime(tokenId, lockDuration) {
|
|
3022
|
-
const data = encodeFunctionData8({
|
|
3023
|
-
abi: veAbi,
|
|
3024
|
-
functionName: "increase_unlock_time",
|
|
3025
|
-
args: [tokenId, BigInt(lockDuration)]
|
|
3026
|
-
});
|
|
3027
3326
|
return {
|
|
3028
|
-
description: `[${this.protocolName}] Extend veNFT #${tokenId} lock
|
|
3327
|
+
description: `[${this.protocolName}] Extend veNFT #${tokenId} lock`,
|
|
3328
|
+
to: this.veToken,
|
|
3329
|
+
data: encodeFunctionData8({ abi: veAbi, functionName: "increase_unlock_time", args: [tokenId, BigInt(lockDuration)] }),
|
|
3330
|
+
value: 0n,
|
|
3331
|
+
gas_estimate: 2e5
|
|
3332
|
+
};
|
|
3333
|
+
}
|
|
3334
|
+
async buildWithdrawExpired(tokenId) {
|
|
3335
|
+
return {
|
|
3336
|
+
description: `[${this.protocolName}] Withdraw expired veNFT #${tokenId}`,
|
|
3337
|
+
to: this.veToken,
|
|
3338
|
+
data: encodeFunctionData8({ abi: veAbi, functionName: "withdraw", args: [tokenId] }),
|
|
3339
|
+
value: 0n,
|
|
3340
|
+
gas_estimate: 2e5
|
|
3341
|
+
};
|
|
3342
|
+
}
|
|
3343
|
+
// ─── Voter ──────────────────────────────────────────────────
|
|
3344
|
+
async buildVote(tokenId, pools, weights) {
|
|
3345
|
+
return {
|
|
3346
|
+
description: `[${this.protocolName}] Vote with veNFT #${tokenId}`,
|
|
3347
|
+
to: this.voter,
|
|
3348
|
+
data: encodeFunctionData8({ abi: voterAbi, functionName: "vote", args: [tokenId, pools, weights] }),
|
|
3349
|
+
value: 0n,
|
|
3350
|
+
gas_estimate: 5e5
|
|
3351
|
+
};
|
|
3352
|
+
}
|
|
3353
|
+
async buildClaimBribes(bribes, tokenId) {
|
|
3354
|
+
const tokensPerBribe = bribes.map(() => []);
|
|
3355
|
+
return {
|
|
3356
|
+
description: `[${this.protocolName}] Claim bribes for veNFT #${tokenId}`,
|
|
3357
|
+
to: this.voter,
|
|
3358
|
+
data: encodeFunctionData8({ abi: voterAbi, functionName: "claimBribes", args: [bribes, tokensPerBribe, tokenId] }),
|
|
3359
|
+
value: 0n,
|
|
3360
|
+
gas_estimate: 3e5
|
|
3361
|
+
};
|
|
3362
|
+
}
|
|
3363
|
+
async buildClaimFees(fees, tokenId) {
|
|
3364
|
+
const tokensPerFee = fees.map(() => []);
|
|
3365
|
+
return {
|
|
3366
|
+
description: `[${this.protocolName}] Claim fees for veNFT #${tokenId}`,
|
|
3367
|
+
to: this.voter,
|
|
3368
|
+
data: encodeFunctionData8({ abi: voterAbi, functionName: "claimFees", args: [fees, tokensPerFee, tokenId] }),
|
|
3369
|
+
value: 0n,
|
|
3370
|
+
gas_estimate: 3e5
|
|
3371
|
+
};
|
|
3372
|
+
}
|
|
3373
|
+
};
|
|
3374
|
+
var abi5 = parseAbi9([
|
|
3375
|
+
"function swap(address fromToken, address toToken, uint256 fromAmount, uint256 minToAmount, address to, address rebateTo) external payable returns (uint256 realToAmount)"
|
|
3376
|
+
]);
|
|
3377
|
+
var WooFiAdapter = class {
|
|
3378
|
+
protocolName;
|
|
3379
|
+
router;
|
|
3380
|
+
constructor(entry, _rpcUrl) {
|
|
3381
|
+
this.protocolName = entry.name;
|
|
3382
|
+
const router = entry.contracts?.["router"];
|
|
3383
|
+
if (!router) {
|
|
3384
|
+
throw new DefiError("CONTRACT_ERROR", "Missing 'router' contract");
|
|
3385
|
+
}
|
|
3386
|
+
this.router = router;
|
|
3387
|
+
}
|
|
3388
|
+
name() {
|
|
3389
|
+
return this.protocolName;
|
|
3390
|
+
}
|
|
3391
|
+
async buildSwap(params) {
|
|
3392
|
+
const minToAmount = 0n;
|
|
3393
|
+
const data = encodeFunctionData9({
|
|
3394
|
+
abi: abi5,
|
|
3395
|
+
functionName: "swap",
|
|
3396
|
+
args: [
|
|
3397
|
+
params.token_in,
|
|
3398
|
+
params.token_out,
|
|
3399
|
+
params.amount_in,
|
|
3400
|
+
minToAmount,
|
|
3401
|
+
params.recipient,
|
|
3402
|
+
zeroAddress5
|
|
3403
|
+
]
|
|
3404
|
+
});
|
|
3405
|
+
return {
|
|
3406
|
+
description: `[${this.protocolName}] Swap ${params.amount_in} via WOOFi`,
|
|
3407
|
+
to: this.router,
|
|
3408
|
+
data,
|
|
3409
|
+
value: 0n,
|
|
3410
|
+
gas_estimate: 2e5
|
|
3411
|
+
};
|
|
3412
|
+
}
|
|
3413
|
+
async quote(_params) {
|
|
3414
|
+
throw DefiError.unsupported(`[${this.protocolName}] quote requires RPC`);
|
|
3415
|
+
}
|
|
3416
|
+
async buildAddLiquidity(_params) {
|
|
3417
|
+
throw DefiError.unsupported(`[${this.protocolName}] WOOFi does not support LP positions via router`);
|
|
3418
|
+
}
|
|
3419
|
+
async buildRemoveLiquidity(_params) {
|
|
3420
|
+
throw DefiError.unsupported(`[${this.protocolName}] WOOFi does not support LP positions via router`);
|
|
3421
|
+
}
|
|
3422
|
+
};
|
|
3423
|
+
var gaugeAbi = parseAbi10([
|
|
3424
|
+
"function deposit(uint256 amount) external",
|
|
3425
|
+
"function depositFor(uint256 amount, uint256 tokenId) external",
|
|
3426
|
+
"function withdraw(uint256 amount) external",
|
|
3427
|
+
"function getReward() external",
|
|
3428
|
+
"function getReward(address account) external",
|
|
3429
|
+
"function getReward(address account, address[] tokens) external",
|
|
3430
|
+
"function getReward(uint256 tokenId) external",
|
|
3431
|
+
"function earned(address account) external view returns (uint256)",
|
|
3432
|
+
"function earned(address token, address account) external view returns (uint256)",
|
|
3433
|
+
"function earned(uint256 tokenId) external view returns (uint256)",
|
|
3434
|
+
"function rewardRate() external view returns (uint256)",
|
|
3435
|
+
"function rewardToken() external view returns (address)",
|
|
3436
|
+
"function totalSupply() external view returns (uint256)",
|
|
3437
|
+
"function rewardsListLength() external view returns (uint256)",
|
|
3438
|
+
"function rewardData(address token) external view returns (uint256 periodFinish, uint256 rewardRate, uint256 lastUpdateTime, uint256 rewardPerTokenStored)",
|
|
3439
|
+
"function nonfungiblePositionManager() external view returns (address)"
|
|
3440
|
+
]);
|
|
3441
|
+
var veAbi2 = parseAbi10([
|
|
3442
|
+
"function create_lock(uint256 value, uint256 lock_duration) external returns (uint256)",
|
|
3443
|
+
"function increase_amount(uint256 tokenId, uint256 value) external",
|
|
3444
|
+
"function increase_unlock_time(uint256 tokenId, uint256 lock_duration) external",
|
|
3445
|
+
"function withdraw(uint256 tokenId) external",
|
|
3446
|
+
"function balanceOfNFT(uint256 tokenId) external view returns (uint256)",
|
|
3447
|
+
"function locked(uint256 tokenId) external view returns (uint256 amount, uint256 end)"
|
|
3448
|
+
]);
|
|
3449
|
+
var voterAbi2 = parseAbi10([
|
|
3450
|
+
"function vote(uint256 tokenId, address[] calldata pools, uint256[] calldata weights) external",
|
|
3451
|
+
"function claimBribes(address[] calldata bribes, address[][] calldata tokens, uint256 tokenId) external",
|
|
3452
|
+
"function claimFees(address[] calldata fees, address[][] calldata tokens, uint256 tokenId) external",
|
|
3453
|
+
"function gauges(address pool) external view returns (address)",
|
|
3454
|
+
"function gaugeForPool(address pool) external view returns (address)",
|
|
3455
|
+
"function poolToGauge(address pool) external view returns (address)"
|
|
3456
|
+
]);
|
|
3457
|
+
var _addressDecodeAbi2 = parseAbi10(["function f() external view returns (address)"]);
|
|
3458
|
+
function decodeAddress2(data) {
|
|
3459
|
+
if (!data) return null;
|
|
3460
|
+
try {
|
|
3461
|
+
return decodeFunctionResult3({ abi: _addressDecodeAbi2, functionName: "f", data });
|
|
3462
|
+
} catch {
|
|
3463
|
+
return null;
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
var _symbolDecodeAbi2 = parseAbi10(["function symbol() external view returns (string)"]);
|
|
3467
|
+
function decodeSymbol2(data) {
|
|
3468
|
+
if (!data) return "?";
|
|
3469
|
+
try {
|
|
3470
|
+
return decodeFunctionResult3({ abi: _symbolDecodeAbi2, functionName: "symbol", data });
|
|
3471
|
+
} catch {
|
|
3472
|
+
return "?";
|
|
3473
|
+
}
|
|
3474
|
+
}
|
|
3475
|
+
var _boolDecodeAbi = parseAbi10(["function f() external view returns (bool)"]);
|
|
3476
|
+
function decodeBoolean(data) {
|
|
3477
|
+
try {
|
|
3478
|
+
return decodeFunctionResult3({ abi: _boolDecodeAbi, functionName: "f", data });
|
|
3479
|
+
} catch {
|
|
3480
|
+
return false;
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3483
|
+
var HYPEREVM_TOKENS = {
|
|
3484
|
+
WHYPE: "0x5555555555555555555555555555555555555555",
|
|
3485
|
+
USDC: "0xb88339CB7199b77E23DB6E890353E22632Ba630f",
|
|
3486
|
+
USDT0: "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
|
|
3487
|
+
UETH: "0xBe6727B535545C67d5cAa73dEa54865B92CF7907",
|
|
3488
|
+
UBTC: "0x9FDBdA0A5e284c32744D2f17Ee5c74B284993463",
|
|
3489
|
+
USDH: "0x111111a1a0667d36bD57c0A9f569b98057111111",
|
|
3490
|
+
USDe: "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34",
|
|
3491
|
+
sUSDe: "0x211Cc4DD073734dA055fbF44a2b4667d5E5fE5d2",
|
|
3492
|
+
XAUt0: "0xf4D9235269a96aaDaFc9aDAe454a0618eBE37949",
|
|
3493
|
+
kHYPE: "0xfD739d4e423301CE9385c1fb8850539D657C296D",
|
|
3494
|
+
RAM: "0x555570a286F15EbDFE42B66eDE2f724Aa1AB5555",
|
|
3495
|
+
hyperRAM: "0xAAAE8378809bb8815c08D3C59Eb0c7D1529aD769"
|
|
3496
|
+
};
|
|
3497
|
+
var CL_TICK_SPACINGS = [1, 5, 10, 50, 100, 200];
|
|
3498
|
+
var SolidlyGaugeAdapter = class {
|
|
3499
|
+
protocolName;
|
|
3500
|
+
voter;
|
|
3501
|
+
veToken;
|
|
3502
|
+
rpcUrl;
|
|
3503
|
+
clFactory;
|
|
3504
|
+
v2Factory;
|
|
3505
|
+
constructor(entry, rpcUrl) {
|
|
3506
|
+
this.protocolName = entry.name;
|
|
3507
|
+
const voter = entry.contracts?.["voter"];
|
|
3508
|
+
if (!voter) {
|
|
3509
|
+
throw new DefiError("CONTRACT_ERROR", "Missing 'voter' contract");
|
|
3510
|
+
}
|
|
3511
|
+
const veToken = entry.contracts?.["ve_token"];
|
|
3512
|
+
if (!veToken) {
|
|
3513
|
+
throw new DefiError("CONTRACT_ERROR", "Missing 've_token' contract");
|
|
3514
|
+
}
|
|
3515
|
+
this.voter = voter;
|
|
3516
|
+
this.veToken = veToken;
|
|
3517
|
+
this.rpcUrl = rpcUrl;
|
|
3518
|
+
this.clFactory = entry.contracts?.["cl_factory"] ?? entry.contracts?.["factory"];
|
|
3519
|
+
this.v2Factory = entry.contracts?.["pair_factory"] ?? entry.contracts?.["factory"];
|
|
3520
|
+
}
|
|
3521
|
+
name() {
|
|
3522
|
+
return this.protocolName;
|
|
3523
|
+
}
|
|
3524
|
+
/** Scan V2 and CL factories for pools that have active emission gauges. */
|
|
3525
|
+
async discoverGaugedPools() {
|
|
3526
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC URL required for gauge discovery");
|
|
3527
|
+
const results = [];
|
|
3528
|
+
await Promise.all([
|
|
3529
|
+
this._discoverV2GaugedPools(results),
|
|
3530
|
+
this._discoverCLGaugedPools(results)
|
|
3531
|
+
]);
|
|
3532
|
+
return results;
|
|
3533
|
+
}
|
|
3534
|
+
async _discoverV2GaugedPools(out) {
|
|
3535
|
+
if (!this.rpcUrl || !this.v2Factory) return;
|
|
3536
|
+
const v2FactoryAbi = parseAbi10([
|
|
3537
|
+
"function allPairsLength() external view returns (uint256)",
|
|
3538
|
+
"function allPairs(uint256) external view returns (address)"
|
|
3539
|
+
]);
|
|
3540
|
+
const pairAbi = parseAbi10([
|
|
3541
|
+
"function token0() external view returns (address)",
|
|
3542
|
+
"function token1() external view returns (address)",
|
|
3543
|
+
"function stable() external view returns (bool)"
|
|
3544
|
+
]);
|
|
3545
|
+
const erc20SymbolAbi = parseAbi10(["function symbol() external view returns (string)"]);
|
|
3546
|
+
const client = createPublicClient6({ transport: http6(this.rpcUrl) });
|
|
3547
|
+
let pairCount;
|
|
3548
|
+
try {
|
|
3549
|
+
pairCount = await client.readContract({
|
|
3550
|
+
address: this.v2Factory,
|
|
3551
|
+
abi: v2FactoryAbi,
|
|
3552
|
+
functionName: "allPairsLength"
|
|
3553
|
+
});
|
|
3554
|
+
} catch {
|
|
3555
|
+
return;
|
|
3556
|
+
}
|
|
3557
|
+
const count = Number(pairCount);
|
|
3558
|
+
if (count === 0) return;
|
|
3559
|
+
const pairAddressCalls = [];
|
|
3560
|
+
for (let i = 0; i < count; i++) {
|
|
3561
|
+
pairAddressCalls.push([
|
|
3562
|
+
this.v2Factory,
|
|
3563
|
+
encodeFunctionData10({ abi: v2FactoryAbi, functionName: "allPairs", args: [BigInt(i)] })
|
|
3564
|
+
]);
|
|
3565
|
+
}
|
|
3566
|
+
const pairAddressResults = await multicallRead(this.rpcUrl, pairAddressCalls);
|
|
3567
|
+
const pairs = pairAddressResults.map((r) => decodeAddress2(r)).filter((a) => a !== null && a !== zeroAddress6);
|
|
3568
|
+
if (pairs.length === 0) return;
|
|
3569
|
+
const gaugeForPoolAbi = parseAbi10(["function gaugeForPool(address) external view returns (address)"]);
|
|
3570
|
+
const poolToGaugeAbi = parseAbi10(["function poolToGauge(address) external view returns (address)"]);
|
|
3571
|
+
const gaugeCalls = pairs.map((pair) => [
|
|
3572
|
+
this.voter,
|
|
3573
|
+
encodeFunctionData10({ abi: gaugeForPoolAbi, functionName: "gaugeForPool", args: [pair] })
|
|
3574
|
+
]);
|
|
3575
|
+
let gaugeResults = await multicallRead(this.rpcUrl, gaugeCalls);
|
|
3576
|
+
const allNullV2 = gaugeResults.every((r) => !r || decodeAddress2(r) === zeroAddress6 || decodeAddress2(r) === null);
|
|
3577
|
+
if (allNullV2) {
|
|
3578
|
+
const fallbackCalls = pairs.map((pair) => [
|
|
3579
|
+
this.voter,
|
|
3580
|
+
encodeFunctionData10({ abi: poolToGaugeAbi, functionName: "poolToGauge", args: [pair] })
|
|
3581
|
+
]);
|
|
3582
|
+
gaugeResults = await multicallRead(this.rpcUrl, fallbackCalls);
|
|
3583
|
+
}
|
|
3584
|
+
const gaugedPairs = [];
|
|
3585
|
+
for (let i = 0; i < pairs.length; i++) {
|
|
3586
|
+
const gauge = decodeAddress2(gaugeResults[i] ?? null);
|
|
3587
|
+
if (gauge && gauge !== zeroAddress6) {
|
|
3588
|
+
gaugedPairs.push({ pair: pairs[i], gauge });
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3591
|
+
if (gaugedPairs.length === 0) return;
|
|
3592
|
+
const metaCalls = [];
|
|
3593
|
+
for (const { pair } of gaugedPairs) {
|
|
3594
|
+
metaCalls.push([pair, encodeFunctionData10({ abi: pairAbi, functionName: "token0" })]);
|
|
3595
|
+
metaCalls.push([pair, encodeFunctionData10({ abi: pairAbi, functionName: "token1" })]);
|
|
3596
|
+
metaCalls.push([pair, encodeFunctionData10({ abi: pairAbi, functionName: "stable" })]);
|
|
3597
|
+
}
|
|
3598
|
+
const metaResults = await multicallRead(this.rpcUrl, metaCalls);
|
|
3599
|
+
const tokenAddrs = /* @__PURE__ */ new Set();
|
|
3600
|
+
for (let i = 0; i < gaugedPairs.length; i++) {
|
|
3601
|
+
const t0 = decodeAddress2(metaResults[i * 3] ?? null);
|
|
3602
|
+
const t1 = decodeAddress2(metaResults[i * 3 + 1] ?? null);
|
|
3603
|
+
if (t0 && t0 !== zeroAddress6) tokenAddrs.add(t0);
|
|
3604
|
+
if (t1 && t1 !== zeroAddress6) tokenAddrs.add(t1);
|
|
3605
|
+
}
|
|
3606
|
+
const uniqueTokens = Array.from(tokenAddrs);
|
|
3607
|
+
const symbolCalls = uniqueTokens.map((t) => [
|
|
3608
|
+
t,
|
|
3609
|
+
encodeFunctionData10({ abi: erc20SymbolAbi, functionName: "symbol" })
|
|
3610
|
+
]);
|
|
3611
|
+
const symbolResults = await multicallRead(this.rpcUrl, symbolCalls);
|
|
3612
|
+
const symbolMap = /* @__PURE__ */ new Map();
|
|
3613
|
+
for (let i = 0; i < uniqueTokens.length; i++) {
|
|
3614
|
+
symbolMap.set(uniqueTokens[i], decodeSymbol2(symbolResults[i] ?? null));
|
|
3615
|
+
}
|
|
3616
|
+
for (let i = 0; i < gaugedPairs.length; i++) {
|
|
3617
|
+
const { pair, gauge } = gaugedPairs[i];
|
|
3618
|
+
const t0 = decodeAddress2(metaResults[i * 3] ?? null);
|
|
3619
|
+
const t1 = decodeAddress2(metaResults[i * 3 + 1] ?? null);
|
|
3620
|
+
const stableRaw = metaResults[i * 3 + 2];
|
|
3621
|
+
const stable = stableRaw ? decodeBoolean(stableRaw) : false;
|
|
3622
|
+
out.push({
|
|
3623
|
+
pool: pair,
|
|
3624
|
+
gauge,
|
|
3625
|
+
token0: t0 ? symbolMap.get(t0) ?? t0.slice(0, 10) : "?",
|
|
3626
|
+
token1: t1 ? symbolMap.get(t1) ?? t1.slice(0, 10) : "?",
|
|
3627
|
+
type: "V2",
|
|
3628
|
+
stable
|
|
3629
|
+
});
|
|
3630
|
+
}
|
|
3631
|
+
}
|
|
3632
|
+
async _discoverCLGaugedPools(out) {
|
|
3633
|
+
if (!this.rpcUrl || !this.clFactory) return;
|
|
3634
|
+
const clFactoryAbi = parseAbi10([
|
|
3635
|
+
"function getPool(address tokenA, address tokenB, int24 tickSpacing) external view returns (address pool)"
|
|
3636
|
+
]);
|
|
3637
|
+
const algebraFactoryAbi2 = parseAbi10([
|
|
3638
|
+
"function poolByPair(address tokenA, address tokenB) external view returns (address pool)"
|
|
3639
|
+
]);
|
|
3640
|
+
const poolAbi2 = parseAbi10([
|
|
3641
|
+
"function token0() external view returns (address)",
|
|
3642
|
+
"function token1() external view returns (address)"
|
|
3643
|
+
]);
|
|
3644
|
+
const erc20SymbolAbi = parseAbi10(["function symbol() external view returns (string)"]);
|
|
3645
|
+
const gaugeForPoolAbi = parseAbi10(["function gaugeForPool(address) external view returns (address)"]);
|
|
3646
|
+
const poolToGaugeAbi = parseAbi10(["function poolToGauge(address) external view returns (address)"]);
|
|
3647
|
+
const tokenEntries = Object.entries(HYPEREVM_TOKENS);
|
|
3648
|
+
const tokenAddresses = tokenEntries.map(([, addr]) => addr);
|
|
3649
|
+
const pairs = [];
|
|
3650
|
+
for (let i = 0; i < tokenAddresses.length; i++) {
|
|
3651
|
+
for (let j = i + 1; j < tokenAddresses.length; j++) {
|
|
3652
|
+
pairs.push([tokenAddresses[i], tokenAddresses[j]]);
|
|
3653
|
+
}
|
|
3654
|
+
}
|
|
3655
|
+
const isAlgebra = await (async () => {
|
|
3656
|
+
try {
|
|
3657
|
+
const [result] = await multicallRead(this.rpcUrl, [[
|
|
3658
|
+
this.clFactory,
|
|
3659
|
+
encodeFunctionData10({ abi: algebraFactoryAbi2, functionName: "poolByPair", args: [tokenAddresses[0], tokenAddresses[1]] })
|
|
3660
|
+
]]);
|
|
3661
|
+
return result !== null && result.length >= 66;
|
|
3662
|
+
} catch {
|
|
3663
|
+
return false;
|
|
3664
|
+
}
|
|
3665
|
+
})();
|
|
3666
|
+
const getPoolCalls = [];
|
|
3667
|
+
const callMeta = [];
|
|
3668
|
+
if (isAlgebra) {
|
|
3669
|
+
for (let p = 0; p < pairs.length; p++) {
|
|
3670
|
+
const [tokenA, tokenB] = pairs[p];
|
|
3671
|
+
getPoolCalls.push([
|
|
3672
|
+
this.clFactory,
|
|
3673
|
+
encodeFunctionData10({ abi: algebraFactoryAbi2, functionName: "poolByPair", args: [tokenA, tokenB] })
|
|
3674
|
+
]);
|
|
3675
|
+
callMeta.push({ pairIdx: p, tickSpacing: 0 });
|
|
3676
|
+
}
|
|
3677
|
+
} else {
|
|
3678
|
+
for (let p = 0; p < pairs.length; p++) {
|
|
3679
|
+
const [tokenA, tokenB] = pairs[p];
|
|
3680
|
+
for (const ts of CL_TICK_SPACINGS) {
|
|
3681
|
+
getPoolCalls.push([
|
|
3682
|
+
this.clFactory,
|
|
3683
|
+
encodeFunctionData10({ abi: clFactoryAbi, functionName: "getPool", args: [tokenA, tokenB, ts] })
|
|
3684
|
+
]);
|
|
3685
|
+
callMeta.push({ pairIdx: p, tickSpacing: ts });
|
|
3686
|
+
}
|
|
3687
|
+
}
|
|
3688
|
+
}
|
|
3689
|
+
const getPoolResults = await multicallRead(this.rpcUrl, getPoolCalls);
|
|
3690
|
+
const candidatePools = [];
|
|
3691
|
+
for (let i = 0; i < getPoolCalls.length; i++) {
|
|
3692
|
+
const pool = decodeAddress2(getPoolResults[i] ?? null);
|
|
3693
|
+
if (pool && pool !== zeroAddress6) {
|
|
3694
|
+
const { pairIdx, tickSpacing } = callMeta[i];
|
|
3695
|
+
const [tokenA, tokenB] = pairs[pairIdx];
|
|
3696
|
+
candidatePools.push({ pool, tokenA, tokenB, tickSpacing });
|
|
3697
|
+
}
|
|
3698
|
+
}
|
|
3699
|
+
if (candidatePools.length === 0) return;
|
|
3700
|
+
const gaugeCalls = candidatePools.map(({ pool }) => [
|
|
3701
|
+
this.voter,
|
|
3702
|
+
encodeFunctionData10({ abi: gaugeForPoolAbi, functionName: "gaugeForPool", args: [pool] })
|
|
3703
|
+
]);
|
|
3704
|
+
let gaugeResults = await multicallRead(this.rpcUrl, gaugeCalls);
|
|
3705
|
+
const allNull = gaugeResults.every((r) => !r || decodeAddress2(r) === zeroAddress6 || decodeAddress2(r) === null);
|
|
3706
|
+
if (allNull) {
|
|
3707
|
+
const fallbackCalls = candidatePools.map(({ pool }) => [
|
|
3708
|
+
this.voter,
|
|
3709
|
+
encodeFunctionData10({ abi: poolToGaugeAbi, functionName: "poolToGauge", args: [pool] })
|
|
3710
|
+
]);
|
|
3711
|
+
gaugeResults = await multicallRead(this.rpcUrl, fallbackCalls);
|
|
3712
|
+
}
|
|
3713
|
+
const gaugedCL = [];
|
|
3714
|
+
for (let i = 0; i < candidatePools.length; i++) {
|
|
3715
|
+
const gauge = decodeAddress2(gaugeResults[i] ?? null);
|
|
3716
|
+
if (gauge && gauge !== zeroAddress6) {
|
|
3717
|
+
gaugedCL.push({ ...candidatePools[i], gauge });
|
|
3718
|
+
}
|
|
3719
|
+
}
|
|
3720
|
+
if (gaugedCL.length === 0) return;
|
|
3721
|
+
const tokenAddrsInPools = /* @__PURE__ */ new Set();
|
|
3722
|
+
for (const { tokenA, tokenB } of gaugedCL) {
|
|
3723
|
+
tokenAddrsInPools.add(tokenA);
|
|
3724
|
+
tokenAddrsInPools.add(tokenB);
|
|
3725
|
+
}
|
|
3726
|
+
const uniqueTokens = Array.from(tokenAddrsInPools);
|
|
3727
|
+
const symbolCalls = uniqueTokens.map((t) => [
|
|
3728
|
+
t,
|
|
3729
|
+
encodeFunctionData10({ abi: erc20SymbolAbi, functionName: "symbol" })
|
|
3730
|
+
]);
|
|
3731
|
+
const symbolResults = await multicallRead(this.rpcUrl, symbolCalls);
|
|
3732
|
+
const symbolMap = /* @__PURE__ */ new Map();
|
|
3733
|
+
for (let i = 0; i < uniqueTokens.length; i++) {
|
|
3734
|
+
symbolMap.set(uniqueTokens[i], decodeSymbol2(symbolResults[i] ?? null));
|
|
3735
|
+
}
|
|
3736
|
+
const poolTokenCalls = [];
|
|
3737
|
+
for (const { pool } of gaugedCL) {
|
|
3738
|
+
poolTokenCalls.push([pool, encodeFunctionData10({ abi: poolAbi2, functionName: "token0" })]);
|
|
3739
|
+
poolTokenCalls.push([pool, encodeFunctionData10({ abi: poolAbi2, functionName: "token1" })]);
|
|
3740
|
+
}
|
|
3741
|
+
const poolTokenResults = await multicallRead(this.rpcUrl, poolTokenCalls);
|
|
3742
|
+
for (let i = 0; i < gaugedCL.length; i++) {
|
|
3743
|
+
const { pool, gauge, tokenA, tokenB, tickSpacing } = gaugedCL[i];
|
|
3744
|
+
const rawT0 = decodeAddress2(poolTokenResults[i * 2] ?? null);
|
|
3745
|
+
const rawT1 = decodeAddress2(poolTokenResults[i * 2 + 1] ?? null);
|
|
3746
|
+
const t0 = rawT0 && rawT0 !== zeroAddress6 ? rawT0 : tokenA;
|
|
3747
|
+
const t1 = rawT1 && rawT1 !== zeroAddress6 ? rawT1 : tokenB;
|
|
3748
|
+
out.push({
|
|
3749
|
+
pool,
|
|
3750
|
+
gauge,
|
|
3751
|
+
token0: symbolMap.get(t0) ?? t0.slice(0, 10),
|
|
3752
|
+
token1: symbolMap.get(t1) ?? t1.slice(0, 10),
|
|
3753
|
+
type: "CL",
|
|
3754
|
+
tickSpacing
|
|
3755
|
+
});
|
|
3756
|
+
}
|
|
3757
|
+
}
|
|
3758
|
+
// IGauge
|
|
3759
|
+
async buildDeposit(gauge, amount, tokenId, lpToken) {
|
|
3760
|
+
if (tokenId !== void 0) {
|
|
3761
|
+
const data2 = encodeFunctionData10({
|
|
3762
|
+
abi: gaugeAbi,
|
|
3763
|
+
functionName: "depositFor",
|
|
3764
|
+
args: [amount, tokenId]
|
|
3765
|
+
});
|
|
3766
|
+
return {
|
|
3767
|
+
description: `[${this.protocolName}] Deposit ${amount} LP to gauge (boost veNFT #${tokenId})`,
|
|
3768
|
+
to: gauge,
|
|
3769
|
+
data: data2,
|
|
3770
|
+
value: 0n,
|
|
3771
|
+
gas_estimate: 2e5,
|
|
3772
|
+
approvals: lpToken ? [{ token: lpToken, spender: gauge, amount }] : void 0
|
|
3773
|
+
};
|
|
3774
|
+
}
|
|
3775
|
+
const data = encodeFunctionData10({
|
|
3776
|
+
abi: gaugeAbi,
|
|
3777
|
+
functionName: "deposit",
|
|
3778
|
+
args: [amount]
|
|
3779
|
+
});
|
|
3780
|
+
return {
|
|
3781
|
+
description: `[${this.protocolName}] Deposit ${amount} LP to gauge`,
|
|
3782
|
+
to: gauge,
|
|
3783
|
+
data,
|
|
3784
|
+
value: 0n,
|
|
3785
|
+
gas_estimate: 2e5,
|
|
3786
|
+
approvals: lpToken ? [{ token: lpToken, spender: gauge, amount }] : void 0
|
|
3787
|
+
};
|
|
3788
|
+
}
|
|
3789
|
+
async buildWithdraw(gauge, amount) {
|
|
3790
|
+
const data = encodeFunctionData10({
|
|
3791
|
+
abi: gaugeAbi,
|
|
3792
|
+
functionName: "withdraw",
|
|
3793
|
+
args: [amount]
|
|
3794
|
+
});
|
|
3795
|
+
return {
|
|
3796
|
+
description: `[${this.protocolName}] Withdraw ${amount} LP from gauge`,
|
|
3797
|
+
to: gauge,
|
|
3798
|
+
data,
|
|
3799
|
+
value: 0n,
|
|
3800
|
+
gas_estimate: 2e5
|
|
3801
|
+
};
|
|
3802
|
+
}
|
|
3803
|
+
/**
|
|
3804
|
+
* Resolve gauge address from a pool address via voter contract.
|
|
3805
|
+
* Tries gaugeForPool (Ramses), poolToGauge (NEST), gauges (classic Solidly).
|
|
3806
|
+
*/
|
|
3807
|
+
async resolveGauge(pool) {
|
|
3808
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC URL required for gauge lookup");
|
|
3809
|
+
const client = createPublicClient6({ transport: http6(this.rpcUrl) });
|
|
3810
|
+
for (const fn of ["gaugeForPool", "poolToGauge", "gauges"]) {
|
|
3811
|
+
try {
|
|
3812
|
+
const gauge = await client.readContract({
|
|
3813
|
+
address: this.voter,
|
|
3814
|
+
abi: voterAbi2,
|
|
3815
|
+
functionName: fn,
|
|
3816
|
+
args: [pool]
|
|
3817
|
+
});
|
|
3818
|
+
if (gauge !== zeroAddress6) return gauge;
|
|
3819
|
+
} catch {
|
|
3820
|
+
}
|
|
3821
|
+
}
|
|
3822
|
+
throw new DefiError("CONTRACT_ERROR", `[${this.protocolName}] No gauge found for pool ${pool}`);
|
|
3823
|
+
}
|
|
3824
|
+
/**
|
|
3825
|
+
* Discover reward tokens for a gauge.
|
|
3826
|
+
* Returns { tokens, multiToken } where multiToken indicates getReward(account, tokens[]) support.
|
|
3827
|
+
*/
|
|
3828
|
+
async discoverRewardTokens(gauge) {
|
|
3829
|
+
if (!this.rpcUrl) return { tokens: [], multiToken: false };
|
|
3830
|
+
const client = createPublicClient6({ transport: http6(this.rpcUrl) });
|
|
3831
|
+
try {
|
|
3832
|
+
const len = await client.readContract({
|
|
3833
|
+
address: gauge,
|
|
3834
|
+
abi: gaugeAbi,
|
|
3835
|
+
functionName: "rewardsListLength"
|
|
3836
|
+
});
|
|
3837
|
+
if (Number(len) > 0) {
|
|
3838
|
+
const candidates = [
|
|
3839
|
+
"0x5555555555555555555555555555555555555555",
|
|
3840
|
+
// WHYPE
|
|
3841
|
+
"0x555570a286F15EbDFE42B66eDE2f724Aa1AB5555",
|
|
3842
|
+
// xRAM
|
|
3843
|
+
"0x067b0C72aa4C6Bd3BFEFfF443c536DCd6a25a9C8",
|
|
3844
|
+
// HYBR
|
|
3845
|
+
"0x07c57E32a3C29D5659bda1d3EFC2E7BF004E3035"
|
|
3846
|
+
// NEST token
|
|
3847
|
+
];
|
|
3848
|
+
const found = [];
|
|
3849
|
+
for (const token of candidates) {
|
|
3850
|
+
try {
|
|
3851
|
+
const rd = await client.readContract({
|
|
3852
|
+
address: gauge,
|
|
3853
|
+
abi: gaugeAbi,
|
|
3854
|
+
functionName: "rewardData",
|
|
3855
|
+
args: [token]
|
|
3856
|
+
});
|
|
3857
|
+
if (rd[0] > 0n || rd[1] > 0n) found.push(token);
|
|
3858
|
+
} catch {
|
|
3859
|
+
}
|
|
3860
|
+
}
|
|
3861
|
+
if (found.length > 0) return { tokens: found, multiToken: true };
|
|
3862
|
+
return { tokens: [], multiToken: true };
|
|
3863
|
+
}
|
|
3864
|
+
} catch {
|
|
3865
|
+
}
|
|
3866
|
+
try {
|
|
3867
|
+
const rt = await client.readContract({
|
|
3868
|
+
address: gauge,
|
|
3869
|
+
abi: gaugeAbi,
|
|
3870
|
+
functionName: "rewardToken"
|
|
3871
|
+
});
|
|
3872
|
+
if (rt !== zeroAddress6) return { tokens: [rt], multiToken: false };
|
|
3873
|
+
} catch {
|
|
3874
|
+
}
|
|
3875
|
+
return { tokens: [], multiToken: false };
|
|
3876
|
+
}
|
|
3877
|
+
async buildClaimRewards(gauge, account) {
|
|
3878
|
+
if (!this.rpcUrl || !account) {
|
|
3879
|
+
const data2 = encodeFunctionData10({
|
|
3880
|
+
abi: gaugeAbi,
|
|
3881
|
+
functionName: "getReward",
|
|
3882
|
+
args: [account ?? zeroAddress6]
|
|
3883
|
+
});
|
|
3884
|
+
return { description: `[${this.protocolName}] Claim gauge rewards`, to: gauge, data: data2, value: 0n, gas_estimate: 2e5 };
|
|
3885
|
+
}
|
|
3886
|
+
const { tokens, multiToken } = await this.discoverRewardTokens(gauge);
|
|
3887
|
+
if (multiToken && tokens.length > 0) {
|
|
3888
|
+
const data2 = encodeFunctionData10({
|
|
3889
|
+
abi: gaugeAbi,
|
|
3890
|
+
functionName: "getReward",
|
|
3891
|
+
args: [account, tokens]
|
|
3892
|
+
});
|
|
3893
|
+
return {
|
|
3894
|
+
description: `[${this.protocolName}] Claim gauge rewards (${tokens.length} tokens)`,
|
|
3895
|
+
to: gauge,
|
|
3896
|
+
data: data2,
|
|
3897
|
+
value: 0n,
|
|
3898
|
+
gas_estimate: 3e5
|
|
3899
|
+
};
|
|
3900
|
+
}
|
|
3901
|
+
const data = encodeFunctionData10({
|
|
3902
|
+
abi: gaugeAbi,
|
|
3903
|
+
functionName: "getReward",
|
|
3904
|
+
args: []
|
|
3905
|
+
});
|
|
3906
|
+
return {
|
|
3907
|
+
description: `[${this.protocolName}] Claim gauge rewards`,
|
|
3908
|
+
to: gauge,
|
|
3909
|
+
data,
|
|
3910
|
+
value: 0n,
|
|
3911
|
+
gas_estimate: 2e5
|
|
3912
|
+
};
|
|
3913
|
+
}
|
|
3914
|
+
/**
|
|
3915
|
+
* Claim rewards for a CL gauge by NFT tokenId (Hybra V4 style).
|
|
3916
|
+
*/
|
|
3917
|
+
async buildClaimRewardsByTokenId(gauge, tokenId) {
|
|
3918
|
+
const data = encodeFunctionData10({
|
|
3919
|
+
abi: gaugeAbi,
|
|
3920
|
+
functionName: "getReward",
|
|
3921
|
+
args: [tokenId]
|
|
3922
|
+
});
|
|
3923
|
+
return {
|
|
3924
|
+
description: `[${this.protocolName}] Claim gauge rewards for NFT #${tokenId}`,
|
|
3925
|
+
to: gauge,
|
|
3926
|
+
data,
|
|
3927
|
+
value: 0n,
|
|
3928
|
+
gas_estimate: 3e5
|
|
3929
|
+
};
|
|
3930
|
+
}
|
|
3931
|
+
async getPendingRewards(gauge, user) {
|
|
3932
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC URL required");
|
|
3933
|
+
const client = createPublicClient6({ transport: http6(this.rpcUrl) });
|
|
3934
|
+
const results = [];
|
|
3935
|
+
const { tokens, multiToken } = await this.discoverRewardTokens(gauge);
|
|
3936
|
+
if (multiToken && tokens.length > 0) {
|
|
3937
|
+
for (const token of tokens) {
|
|
3938
|
+
try {
|
|
3939
|
+
const earned = await client.readContract({
|
|
3940
|
+
address: gauge,
|
|
3941
|
+
abi: gaugeAbi,
|
|
3942
|
+
functionName: "earned",
|
|
3943
|
+
args: [token, user]
|
|
3944
|
+
});
|
|
3945
|
+
results.push({ token, symbol: token.slice(0, 10), amount: earned });
|
|
3946
|
+
} catch {
|
|
3947
|
+
}
|
|
3948
|
+
}
|
|
3949
|
+
} else if (tokens.length > 0) {
|
|
3950
|
+
try {
|
|
3951
|
+
const earned = await client.readContract({
|
|
3952
|
+
address: gauge,
|
|
3953
|
+
abi: gaugeAbi,
|
|
3954
|
+
functionName: "earned",
|
|
3955
|
+
args: [user]
|
|
3956
|
+
});
|
|
3957
|
+
results.push({ token: tokens[0], symbol: tokens[0].slice(0, 10), amount: earned });
|
|
3958
|
+
} catch {
|
|
3959
|
+
}
|
|
3960
|
+
} else {
|
|
3961
|
+
try {
|
|
3962
|
+
const earned = await client.readContract({
|
|
3963
|
+
address: gauge,
|
|
3964
|
+
abi: gaugeAbi,
|
|
3965
|
+
functionName: "earned",
|
|
3966
|
+
args: [user]
|
|
3967
|
+
});
|
|
3968
|
+
results.push({ token: zeroAddress6, symbol: "unknown", amount: earned });
|
|
3969
|
+
} catch {
|
|
3970
|
+
}
|
|
3971
|
+
}
|
|
3972
|
+
return results;
|
|
3973
|
+
}
|
|
3974
|
+
/**
|
|
3975
|
+
* Get pending rewards for a CL gauge NFT position (Hybra V4 style).
|
|
3976
|
+
*/
|
|
3977
|
+
async getPendingRewardsByTokenId(gauge, tokenId) {
|
|
3978
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC URL required");
|
|
3979
|
+
const client = createPublicClient6({ transport: http6(this.rpcUrl) });
|
|
3980
|
+
return await client.readContract({
|
|
3981
|
+
address: gauge,
|
|
3982
|
+
abi: gaugeAbi,
|
|
3983
|
+
functionName: "earned",
|
|
3984
|
+
args: [tokenId]
|
|
3985
|
+
});
|
|
3986
|
+
}
|
|
3987
|
+
// IVoteEscrow
|
|
3988
|
+
async buildCreateLock(amount, lockDuration) {
|
|
3989
|
+
const data = encodeFunctionData10({
|
|
3990
|
+
abi: veAbi2,
|
|
3991
|
+
functionName: "create_lock",
|
|
3992
|
+
args: [amount, BigInt(lockDuration)]
|
|
3993
|
+
});
|
|
3994
|
+
return {
|
|
3995
|
+
description: `[${this.protocolName}] Create veNFT lock: ${amount} tokens for ${lockDuration}s`,
|
|
3996
|
+
to: this.veToken,
|
|
3997
|
+
data,
|
|
3998
|
+
value: 0n,
|
|
3999
|
+
gas_estimate: 3e5
|
|
4000
|
+
};
|
|
4001
|
+
}
|
|
4002
|
+
async buildIncreaseAmount(tokenId, amount) {
|
|
4003
|
+
const data = encodeFunctionData10({
|
|
4004
|
+
abi: veAbi2,
|
|
4005
|
+
functionName: "increase_amount",
|
|
4006
|
+
args: [tokenId, amount]
|
|
4007
|
+
});
|
|
4008
|
+
return {
|
|
4009
|
+
description: `[${this.protocolName}] Increase veNFT #${tokenId} by ${amount}`,
|
|
4010
|
+
to: this.veToken,
|
|
4011
|
+
data,
|
|
4012
|
+
value: 0n,
|
|
4013
|
+
gas_estimate: 2e5
|
|
4014
|
+
};
|
|
4015
|
+
}
|
|
4016
|
+
async buildIncreaseUnlockTime(tokenId, lockDuration) {
|
|
4017
|
+
const data = encodeFunctionData10({
|
|
4018
|
+
abi: veAbi2,
|
|
4019
|
+
functionName: "increase_unlock_time",
|
|
4020
|
+
args: [tokenId, BigInt(lockDuration)]
|
|
4021
|
+
});
|
|
4022
|
+
return {
|
|
4023
|
+
description: `[${this.protocolName}] Extend veNFT #${tokenId} lock by ${lockDuration}s`,
|
|
3029
4024
|
to: this.veToken,
|
|
3030
4025
|
data,
|
|
3031
4026
|
value: 0n,
|
|
@@ -3033,8 +4028,8 @@ var SolidlyGaugeAdapter = class {
|
|
|
3033
4028
|
};
|
|
3034
4029
|
}
|
|
3035
4030
|
async buildWithdrawExpired(tokenId) {
|
|
3036
|
-
const data =
|
|
3037
|
-
abi:
|
|
4031
|
+
const data = encodeFunctionData10({
|
|
4032
|
+
abi: veAbi2,
|
|
3038
4033
|
functionName: "withdraw",
|
|
3039
4034
|
args: [tokenId]
|
|
3040
4035
|
});
|
|
@@ -3048,8 +4043,8 @@ var SolidlyGaugeAdapter = class {
|
|
|
3048
4043
|
}
|
|
3049
4044
|
// IVoter
|
|
3050
4045
|
async buildVote(tokenId, pools, weights) {
|
|
3051
|
-
const data =
|
|
3052
|
-
abi:
|
|
4046
|
+
const data = encodeFunctionData10({
|
|
4047
|
+
abi: voterAbi2,
|
|
3053
4048
|
functionName: "vote",
|
|
3054
4049
|
args: [tokenId, pools, weights]
|
|
3055
4050
|
});
|
|
@@ -3063,8 +4058,8 @@ var SolidlyGaugeAdapter = class {
|
|
|
3063
4058
|
}
|
|
3064
4059
|
async buildClaimBribes(bribes, tokenId) {
|
|
3065
4060
|
const tokensPerBribe = bribes.map(() => []);
|
|
3066
|
-
const data =
|
|
3067
|
-
abi:
|
|
4061
|
+
const data = encodeFunctionData10({
|
|
4062
|
+
abi: voterAbi2,
|
|
3068
4063
|
functionName: "claimBribes",
|
|
3069
4064
|
args: [bribes, tokensPerBribe, tokenId]
|
|
3070
4065
|
});
|
|
@@ -3078,8 +4073,8 @@ var SolidlyGaugeAdapter = class {
|
|
|
3078
4073
|
}
|
|
3079
4074
|
async buildClaimFees(fees, tokenId) {
|
|
3080
4075
|
const tokensPerFee = fees.map(() => []);
|
|
3081
|
-
const data =
|
|
3082
|
-
abi:
|
|
4076
|
+
const data = encodeFunctionData10({
|
|
4077
|
+
abi: voterAbi2,
|
|
3083
4078
|
functionName: "claimFees",
|
|
3084
4079
|
args: [fees, tokensPerFee, tokenId]
|
|
3085
4080
|
});
|
|
@@ -3092,7 +4087,7 @@ var SolidlyGaugeAdapter = class {
|
|
|
3092
4087
|
};
|
|
3093
4088
|
}
|
|
3094
4089
|
};
|
|
3095
|
-
var masterchefAbi =
|
|
4090
|
+
var masterchefAbi = parseAbi11([
|
|
3096
4091
|
"function deposit(uint256 pid, uint256 amount) external",
|
|
3097
4092
|
"function withdraw(uint256 pid, uint256 amount) external",
|
|
3098
4093
|
"function claim(uint256[] calldata pids) external",
|
|
@@ -3123,7 +4118,7 @@ var MasterChefAdapter = class {
|
|
|
3123
4118
|
*/
|
|
3124
4119
|
async buildDeposit(gauge, amount, tokenId) {
|
|
3125
4120
|
const pid = tokenId ?? 0n;
|
|
3126
|
-
const data =
|
|
4121
|
+
const data = encodeFunctionData11({
|
|
3127
4122
|
abi: masterchefAbi,
|
|
3128
4123
|
functionName: "deposit",
|
|
3129
4124
|
args: [pid, amount]
|
|
@@ -3144,7 +4139,7 @@ var MasterChefAdapter = class {
|
|
|
3144
4139
|
*/
|
|
3145
4140
|
async buildWithdraw(gauge, amount) {
|
|
3146
4141
|
const pid = 0n;
|
|
3147
|
-
const data =
|
|
4142
|
+
const data = encodeFunctionData11({
|
|
3148
4143
|
abi: masterchefAbi,
|
|
3149
4144
|
functionName: "withdraw",
|
|
3150
4145
|
args: [pid, amount]
|
|
@@ -3159,7 +4154,7 @@ var MasterChefAdapter = class {
|
|
|
3159
4154
|
}
|
|
3160
4155
|
/** Withdraw LP tokens specifying a pid explicitly (MasterChef extension beyond IGauge). */
|
|
3161
4156
|
async buildWithdrawPid(pid, amount) {
|
|
3162
|
-
const data =
|
|
4157
|
+
const data = encodeFunctionData11({
|
|
3163
4158
|
abi: masterchefAbi,
|
|
3164
4159
|
functionName: "withdraw",
|
|
3165
4160
|
args: [pid, amount]
|
|
@@ -3175,7 +4170,7 @@ var MasterChefAdapter = class {
|
|
|
3175
4170
|
/** Claim pending MOE rewards. IGauge interface provides no pid — defaults to pid=0. */
|
|
3176
4171
|
async buildClaimRewards(gauge) {
|
|
3177
4172
|
const pid = 0n;
|
|
3178
|
-
const data =
|
|
4173
|
+
const data = encodeFunctionData11({
|
|
3179
4174
|
abi: masterchefAbi,
|
|
3180
4175
|
functionName: "claim",
|
|
3181
4176
|
args: [[pid]]
|
|
@@ -3190,7 +4185,7 @@ var MasterChefAdapter = class {
|
|
|
3190
4185
|
}
|
|
3191
4186
|
/** Claim pending MOE rewards for a specific pid (MasterChef extension beyond IGauge). */
|
|
3192
4187
|
async buildClaimRewardsPid(pid) {
|
|
3193
|
-
const data =
|
|
4188
|
+
const data = encodeFunctionData11({
|
|
3194
4189
|
abi: masterchefAbi,
|
|
3195
4190
|
functionName: "claim",
|
|
3196
4191
|
args: [[pid]]
|
|
@@ -3208,7 +4203,7 @@ var MasterChefAdapter = class {
|
|
|
3208
4203
|
if (!this.rpcUrl) {
|
|
3209
4204
|
throw DefiError.unsupported(`[${this.protocolName}] getPendingRewards requires RPC`);
|
|
3210
4205
|
}
|
|
3211
|
-
const client =
|
|
4206
|
+
const client = createPublicClient7({ transport: http7(this.rpcUrl) });
|
|
3212
4207
|
const rewards = await client.readContract({
|
|
3213
4208
|
address: this.masterchef,
|
|
3214
4209
|
abi: masterchefAbi,
|
|
@@ -3222,16 +4217,16 @@ var MasterChefAdapter = class {
|
|
|
3222
4217
|
}));
|
|
3223
4218
|
}
|
|
3224
4219
|
};
|
|
3225
|
-
var lbRouterAbi =
|
|
4220
|
+
var lbRouterAbi = parseAbi12([
|
|
3226
4221
|
"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
4222
|
"function addLiquidity(LiquidityParameters calldata liquidityParameters) external returns (uint256 amountXAdded, uint256 amountYAdded, uint256 amountXLeft, uint256 amountYLeft, uint256[] memory depositIds, uint256[] memory liquidityMinted)",
|
|
3228
4223
|
"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
4224
|
]);
|
|
3230
|
-
var lbFactoryAbi =
|
|
4225
|
+
var lbFactoryAbi = parseAbi12([
|
|
3231
4226
|
"function getNumberOfLBPairs() external view returns (uint256)",
|
|
3232
4227
|
"function getLBPairAtIndex(uint256 index) external view returns (address)"
|
|
3233
4228
|
]);
|
|
3234
|
-
var lbPairAbi =
|
|
4229
|
+
var lbPairAbi = parseAbi12([
|
|
3235
4230
|
"function getLBHooksParameters() external view returns (bytes32)",
|
|
3236
4231
|
"function getActiveId() external view returns (uint24)",
|
|
3237
4232
|
"function getBinStep() external view returns (uint16)",
|
|
@@ -3240,7 +4235,7 @@ var lbPairAbi = parseAbi10([
|
|
|
3240
4235
|
"function balanceOf(address account, uint256 id) external view returns (uint256)",
|
|
3241
4236
|
"function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory)"
|
|
3242
4237
|
]);
|
|
3243
|
-
var lbRewarderAbi =
|
|
4238
|
+
var lbRewarderAbi = parseAbi12([
|
|
3244
4239
|
"function getRewardToken() external view returns (address)",
|
|
3245
4240
|
"function getRewardedRange() external view returns (uint256 minBinId, uint256 maxBinId)",
|
|
3246
4241
|
"function getPendingRewards(address user, uint256[] calldata ids) external view returns (uint256 pendingRewards)",
|
|
@@ -3250,50 +4245,50 @@ var lbRewarderAbi = parseAbi10([
|
|
|
3250
4245
|
"function getLBPair() external view returns (address)",
|
|
3251
4246
|
"function getMasterChef() external view returns (address)"
|
|
3252
4247
|
]);
|
|
3253
|
-
var masterChefAbi =
|
|
4248
|
+
var masterChefAbi = parseAbi12([
|
|
3254
4249
|
"function getMoePerSecond() external view returns (uint256)",
|
|
3255
4250
|
"function getTreasuryShare() external view returns (uint256)",
|
|
3256
4251
|
"function getStaticShare() external view returns (uint256)",
|
|
3257
4252
|
"function getVeMoe() external view returns (address)"
|
|
3258
4253
|
]);
|
|
3259
|
-
var veMoeAbi =
|
|
4254
|
+
var veMoeAbi = parseAbi12([
|
|
3260
4255
|
"function getWeight(uint256 pid) external view returns (uint256)",
|
|
3261
4256
|
"function getTotalWeight() external view returns (uint256)",
|
|
3262
4257
|
"function getTopPoolIds() external view returns (uint256[] memory)"
|
|
3263
4258
|
]);
|
|
3264
|
-
var lbPairBinAbi =
|
|
4259
|
+
var lbPairBinAbi = parseAbi12([
|
|
3265
4260
|
"function getBin(uint24 id) external view returns (uint128 reserveX, uint128 reserveY)",
|
|
3266
4261
|
"function getActiveId() external view returns (uint24)"
|
|
3267
4262
|
]);
|
|
3268
|
-
var lbQuoterAbi2 =
|
|
4263
|
+
var lbQuoterAbi2 = parseAbi12([
|
|
3269
4264
|
"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
4265
|
]);
|
|
3271
|
-
var erc20Abi2 =
|
|
4266
|
+
var erc20Abi2 = parseAbi12([
|
|
3272
4267
|
"function symbol() external view returns (string)"
|
|
3273
4268
|
]);
|
|
3274
|
-
var _addressAbi =
|
|
4269
|
+
var _addressAbi = parseAbi12(["function f() external view returns (address)"]);
|
|
3275
4270
|
function decodeAddressResult(data) {
|
|
3276
4271
|
if (!data) return null;
|
|
3277
4272
|
try {
|
|
3278
|
-
return
|
|
4273
|
+
return decodeFunctionResult4({ abi: _addressAbi, functionName: "f", data });
|
|
3279
4274
|
} catch {
|
|
3280
4275
|
return null;
|
|
3281
4276
|
}
|
|
3282
4277
|
}
|
|
3283
|
-
var _uint256Abi =
|
|
4278
|
+
var _uint256Abi = parseAbi12(["function f() external view returns (uint256)"]);
|
|
3284
4279
|
function decodeUint256Result(data) {
|
|
3285
4280
|
if (!data) return null;
|
|
3286
4281
|
try {
|
|
3287
|
-
return
|
|
4282
|
+
return decodeFunctionResult4({ abi: _uint256Abi, functionName: "f", data });
|
|
3288
4283
|
} catch {
|
|
3289
4284
|
return null;
|
|
3290
4285
|
}
|
|
3291
4286
|
}
|
|
3292
|
-
var _boolAbi =
|
|
4287
|
+
var _boolAbi = parseAbi12(["function f() external view returns (bool)"]);
|
|
3293
4288
|
function decodeBoolResult(data) {
|
|
3294
4289
|
if (!data) return null;
|
|
3295
4290
|
try {
|
|
3296
|
-
return
|
|
4291
|
+
return decodeFunctionResult4({ abi: _boolAbi, functionName: "f", data });
|
|
3297
4292
|
} catch {
|
|
3298
4293
|
return null;
|
|
3299
4294
|
}
|
|
@@ -3301,34 +4296,34 @@ function decodeBoolResult(data) {
|
|
|
3301
4296
|
function decodeStringResult(data) {
|
|
3302
4297
|
if (!data) return "?";
|
|
3303
4298
|
try {
|
|
3304
|
-
return
|
|
4299
|
+
return decodeFunctionResult4({ abi: erc20Abi2, functionName: "symbol", data });
|
|
3305
4300
|
} catch {
|
|
3306
4301
|
return "?";
|
|
3307
4302
|
}
|
|
3308
4303
|
}
|
|
3309
|
-
var _rangeAbi =
|
|
4304
|
+
var _rangeAbi = parseAbi12(["function f() external view returns (uint256 minBinId, uint256 maxBinId)"]);
|
|
3310
4305
|
function decodeRangeResult(data) {
|
|
3311
4306
|
if (!data) return null;
|
|
3312
4307
|
try {
|
|
3313
|
-
return
|
|
4308
|
+
return decodeFunctionResult4({ abi: _rangeAbi, functionName: "f", data });
|
|
3314
4309
|
} catch {
|
|
3315
4310
|
return null;
|
|
3316
4311
|
}
|
|
3317
4312
|
}
|
|
3318
|
-
var _binAbi =
|
|
4313
|
+
var _binAbi = parseAbi12(["function f() external view returns (uint128 reserveX, uint128 reserveY)"]);
|
|
3319
4314
|
function decodeBinResult(data) {
|
|
3320
4315
|
if (!data) return null;
|
|
3321
4316
|
try {
|
|
3322
|
-
return
|
|
4317
|
+
return decodeFunctionResult4({ abi: _binAbi, functionName: "f", data });
|
|
3323
4318
|
} catch {
|
|
3324
4319
|
return null;
|
|
3325
4320
|
}
|
|
3326
4321
|
}
|
|
3327
|
-
var _uint256ArrayAbi =
|
|
4322
|
+
var _uint256ArrayAbi = parseAbi12(["function f() external view returns (uint256[] memory)"]);
|
|
3328
4323
|
function decodeUint256ArrayResult(data) {
|
|
3329
4324
|
if (!data) return null;
|
|
3330
4325
|
try {
|
|
3331
|
-
return
|
|
4326
|
+
return decodeFunctionResult4({ abi: _uint256ArrayAbi, functionName: "f", data });
|
|
3332
4327
|
} catch {
|
|
3333
4328
|
return null;
|
|
3334
4329
|
}
|
|
@@ -3414,7 +4409,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3414
4409
|
let activeIdDesired = params.activeIdDesired;
|
|
3415
4410
|
if (activeIdDesired === void 0) {
|
|
3416
4411
|
const rpcUrl = this.requireRpc();
|
|
3417
|
-
const client =
|
|
4412
|
+
const client = createPublicClient8({ transport: http8(rpcUrl) });
|
|
3418
4413
|
const activeId = await client.readContract({
|
|
3419
4414
|
address: params.pool,
|
|
3420
4415
|
abi: lbPairAbi,
|
|
@@ -3427,7 +4422,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3427
4422
|
deltaIds.push(d);
|
|
3428
4423
|
}
|
|
3429
4424
|
const { distributionX, distributionY } = buildUniformDistribution(deltaIds);
|
|
3430
|
-
const data =
|
|
4425
|
+
const data = encodeFunctionData12({
|
|
3431
4426
|
abi: lbRouterAbi,
|
|
3432
4427
|
functionName: "addLiquidity",
|
|
3433
4428
|
args: [
|
|
@@ -3467,7 +4462,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3467
4462
|
*/
|
|
3468
4463
|
async buildRemoveLiquidity(params) {
|
|
3469
4464
|
const deadline = params.deadline ?? BigInt("18446744073709551615");
|
|
3470
|
-
const data =
|
|
4465
|
+
const data = encodeFunctionData12({
|
|
3471
4466
|
abi: lbRouterAbi,
|
|
3472
4467
|
functionName: "removeLiquidity",
|
|
3473
4468
|
args: [
|
|
@@ -3496,7 +4491,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3496
4491
|
*/
|
|
3497
4492
|
async autoDetectBins(pool) {
|
|
3498
4493
|
const rpcUrl = this.requireRpc();
|
|
3499
|
-
const client =
|
|
4494
|
+
const client = createPublicClient8({ transport: http8(rpcUrl) });
|
|
3500
4495
|
const hooksParams = await client.readContract({
|
|
3501
4496
|
address: pool,
|
|
3502
4497
|
abi: lbPairAbi,
|
|
@@ -3531,7 +4526,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3531
4526
|
*/
|
|
3532
4527
|
async getPendingRewards(user, pool, binIds) {
|
|
3533
4528
|
const rpcUrl = this.requireRpc();
|
|
3534
|
-
const client =
|
|
4529
|
+
const client = createPublicClient8({ transport: http8(rpcUrl) });
|
|
3535
4530
|
const hooksParams = await client.readContract({
|
|
3536
4531
|
address: pool,
|
|
3537
4532
|
abi: lbPairAbi,
|
|
@@ -3580,7 +4575,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3580
4575
|
*/
|
|
3581
4576
|
async buildClaimRewards(user, pool, binIds) {
|
|
3582
4577
|
const rpcUrl = this.requireRpc();
|
|
3583
|
-
const client =
|
|
4578
|
+
const client = createPublicClient8({ transport: http8(rpcUrl) });
|
|
3584
4579
|
const hooksParams = await client.readContract({
|
|
3585
4580
|
address: pool,
|
|
3586
4581
|
abi: lbPairAbi,
|
|
@@ -3602,7 +4597,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3602
4597
|
resolvedBinIds = [];
|
|
3603
4598
|
for (let b = min; b <= max; b++) resolvedBinIds.push(b);
|
|
3604
4599
|
}
|
|
3605
|
-
const data =
|
|
4600
|
+
const data = encodeFunctionData12({
|
|
3606
4601
|
abi: lbRewarderAbi,
|
|
3607
4602
|
functionName: "claim",
|
|
3608
4603
|
args: [user, resolvedBinIds.map(BigInt)]
|
|
@@ -3630,7 +4625,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3630
4625
|
*/
|
|
3631
4626
|
async discoverRewardedPools() {
|
|
3632
4627
|
const rpcUrl = this.requireRpc();
|
|
3633
|
-
const client =
|
|
4628
|
+
const client = createPublicClient8({ transport: http8(rpcUrl) });
|
|
3634
4629
|
const pairCount = await client.readContract({
|
|
3635
4630
|
address: this.lbFactory,
|
|
3636
4631
|
abi: lbFactoryAbi,
|
|
@@ -3640,14 +4635,14 @@ var MerchantMoeLBAdapter = class {
|
|
|
3640
4635
|
if (count === 0) return [];
|
|
3641
4636
|
const batch1Calls = Array.from({ length: count }, (_, i) => [
|
|
3642
4637
|
this.lbFactory,
|
|
3643
|
-
|
|
4638
|
+
encodeFunctionData12({ abi: lbFactoryAbi, functionName: "getLBPairAtIndex", args: [BigInt(i)] })
|
|
3644
4639
|
]);
|
|
3645
4640
|
const batch1Results = await multicallRead(rpcUrl, batch1Calls);
|
|
3646
4641
|
const pairAddresses = batch1Results.map((r) => decodeAddressResult(r)).filter((a) => a !== null);
|
|
3647
4642
|
if (pairAddresses.length === 0) return [];
|
|
3648
4643
|
const batch2Calls = pairAddresses.map((pair) => [
|
|
3649
4644
|
pair,
|
|
3650
|
-
|
|
4645
|
+
encodeFunctionData12({ abi: lbPairAbi, functionName: "getLBHooksParameters" })
|
|
3651
4646
|
]);
|
|
3652
4647
|
const batch2Results = await multicallRead(rpcUrl, batch2Calls);
|
|
3653
4648
|
const rewardedPairs = [];
|
|
@@ -3656,8 +4651,8 @@ var MerchantMoeLBAdapter = class {
|
|
|
3656
4651
|
if (!raw) continue;
|
|
3657
4652
|
let hooksBytes;
|
|
3658
4653
|
try {
|
|
3659
|
-
const _bytes32Abi =
|
|
3660
|
-
hooksBytes =
|
|
4654
|
+
const _bytes32Abi = parseAbi12(["function f() external view returns (bytes32)"]);
|
|
4655
|
+
hooksBytes = decodeFunctionResult4({ abi: _bytes32Abi, functionName: "f", data: raw });
|
|
3661
4656
|
} catch {
|
|
3662
4657
|
continue;
|
|
3663
4658
|
}
|
|
@@ -3669,17 +4664,17 @@ var MerchantMoeLBAdapter = class {
|
|
|
3669
4664
|
if (rewardedPairs.length === 0) return [];
|
|
3670
4665
|
const batch3Calls = [];
|
|
3671
4666
|
for (const { rewarder } of rewardedPairs) {
|
|
3672
|
-
batch3Calls.push([rewarder,
|
|
3673
|
-
batch3Calls.push([rewarder,
|
|
3674
|
-
batch3Calls.push([rewarder,
|
|
3675
|
-
batch3Calls.push([rewarder,
|
|
3676
|
-
batch3Calls.push([rewarder,
|
|
4667
|
+
batch3Calls.push([rewarder, encodeFunctionData12({ abi: lbRewarderAbi, functionName: "isStopped" })]);
|
|
4668
|
+
batch3Calls.push([rewarder, encodeFunctionData12({ abi: lbRewarderAbi, functionName: "getRewardedRange" })]);
|
|
4669
|
+
batch3Calls.push([rewarder, encodeFunctionData12({ abi: lbRewarderAbi, functionName: "getRewardToken" })]);
|
|
4670
|
+
batch3Calls.push([rewarder, encodeFunctionData12({ abi: lbRewarderAbi, functionName: "getPid" })]);
|
|
4671
|
+
batch3Calls.push([rewarder, encodeFunctionData12({ abi: lbRewarderAbi, functionName: "getMasterChef" })]);
|
|
3677
4672
|
}
|
|
3678
4673
|
const batch3Results = await multicallRead(rpcUrl, batch3Calls);
|
|
3679
4674
|
const batch4aCalls = [];
|
|
3680
4675
|
for (const { pool } of rewardedPairs) {
|
|
3681
|
-
batch4aCalls.push([pool,
|
|
3682
|
-
batch4aCalls.push([pool,
|
|
4676
|
+
batch4aCalls.push([pool, encodeFunctionData12({ abi: lbPairAbi, functionName: "getTokenX" })]);
|
|
4677
|
+
batch4aCalls.push([pool, encodeFunctionData12({ abi: lbPairAbi, functionName: "getTokenY" })]);
|
|
3683
4678
|
}
|
|
3684
4679
|
const batch4aResults = await multicallRead(rpcUrl, batch4aCalls);
|
|
3685
4680
|
const tokenXAddresses = [];
|
|
@@ -3693,7 +4688,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3693
4688
|
);
|
|
3694
4689
|
const batch4bCalls = uniqueTokens.map((token) => [
|
|
3695
4690
|
token,
|
|
3696
|
-
|
|
4691
|
+
encodeFunctionData12({ abi: erc20Abi2, functionName: "symbol" })
|
|
3697
4692
|
]);
|
|
3698
4693
|
const batch4bResults = await multicallRead(rpcUrl, batch4bCalls);
|
|
3699
4694
|
const symbolMap = /* @__PURE__ */ new Map();
|
|
@@ -3724,11 +4719,11 @@ var MerchantMoeLBAdapter = class {
|
|
|
3724
4719
|
functionName: "getVeMoe"
|
|
3725
4720
|
});
|
|
3726
4721
|
const batch5Calls = [
|
|
3727
|
-
[masterChefAddr,
|
|
3728
|
-
[masterChefAddr,
|
|
3729
|
-
[masterChefAddr,
|
|
3730
|
-
[veMoeAddr,
|
|
3731
|
-
[veMoeAddr,
|
|
4722
|
+
[masterChefAddr, encodeFunctionData12({ abi: masterChefAbi, functionName: "getMoePerSecond" })],
|
|
4723
|
+
[masterChefAddr, encodeFunctionData12({ abi: masterChefAbi, functionName: "getTreasuryShare" })],
|
|
4724
|
+
[masterChefAddr, encodeFunctionData12({ abi: masterChefAbi, functionName: "getStaticShare" })],
|
|
4725
|
+
[veMoeAddr, encodeFunctionData12({ abi: veMoeAbi, functionName: "getTotalWeight" })],
|
|
4726
|
+
[veMoeAddr, encodeFunctionData12({ abi: veMoeAbi, functionName: "getTopPoolIds" })]
|
|
3732
4727
|
];
|
|
3733
4728
|
const batch5Results = await multicallRead(rpcUrl, batch5Calls);
|
|
3734
4729
|
const moePerSecRaw = decodeUint256Result(batch5Results[0] ?? null) ?? 0n;
|
|
@@ -3745,7 +4740,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3745
4740
|
if (veMoeAddr && rewardedPairs.length > 0) {
|
|
3746
4741
|
const batch6Calls = poolData.map((d) => [
|
|
3747
4742
|
veMoeAddr,
|
|
3748
|
-
|
|
4743
|
+
encodeFunctionData12({ abi: veMoeAbi, functionName: "getWeight", args: [BigInt(d.pid)] })
|
|
3749
4744
|
]);
|
|
3750
4745
|
const batch6Results = await multicallRead(rpcUrl, batch6Calls);
|
|
3751
4746
|
for (let i = 0; i < poolData.length; i++) {
|
|
@@ -3792,7 +4787,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3792
4787
|
if (binRequests.length > 0) {
|
|
3793
4788
|
const batch7Calls = binRequests.map(({ poolIdx, binId }) => [
|
|
3794
4789
|
rewardedPairs[poolIdx].pool,
|
|
3795
|
-
|
|
4790
|
+
encodeFunctionData12({ abi: lbPairBinAbi, functionName: "getBin", args: [binId] })
|
|
3796
4791
|
]);
|
|
3797
4792
|
const batch7Results = await multicallRead(rpcUrl, batch7Calls);
|
|
3798
4793
|
for (let j = 0; j < binRequests.length; j++) {
|
|
@@ -3878,26 +4873,460 @@ var MerchantMoeLBAdapter = class {
|
|
|
3878
4873
|
}
|
|
3879
4874
|
return results;
|
|
3880
4875
|
}
|
|
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 =
|
|
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
|
-
}
|
|
4876
|
+
/**
|
|
4877
|
+
* Get a user's LB positions (bin balances) across a range of bin IDs.
|
|
4878
|
+
* If binIds is omitted, auto-detects from the rewarder's rewarded range (or active ± 50).
|
|
4879
|
+
*/
|
|
4880
|
+
async getUserPositions(user, pool, binIds) {
|
|
4881
|
+
const rpcUrl = this.requireRpc();
|
|
4882
|
+
const client = createPublicClient8({ transport: http8(rpcUrl) });
|
|
4883
|
+
const resolvedBinIds = binIds && binIds.length > 0 ? binIds : await this.autoDetectBins(pool);
|
|
4884
|
+
const accounts = resolvedBinIds.map(() => user);
|
|
4885
|
+
const ids = resolvedBinIds.map(BigInt);
|
|
4886
|
+
const balances = await client.readContract({
|
|
4887
|
+
address: pool,
|
|
4888
|
+
abi: lbPairAbi,
|
|
4889
|
+
functionName: "balanceOfBatch",
|
|
4890
|
+
args: [accounts, ids]
|
|
4891
|
+
});
|
|
4892
|
+
return resolvedBinIds.map((binId, i) => ({ binId, balance: balances[i] ?? 0n })).filter((p) => p.balance > 0n);
|
|
4893
|
+
}
|
|
4894
|
+
};
|
|
4895
|
+
var KITTEN_TOKEN = "0x618275f8efe54c2afa87bfb9f210a52f0ff89364";
|
|
4896
|
+
var WHYPE_TOKEN = "0x5555555555555555555555555555555555555555";
|
|
4897
|
+
var MAX_NONCE_SCAN = 60;
|
|
4898
|
+
var HYPEREVM_TOKENS2 = [
|
|
4899
|
+
"0x5555555555555555555555555555555555555555",
|
|
4900
|
+
// WHYPE
|
|
4901
|
+
"0xb88339CB7199b77E23DB6E890353E22632Ba630f",
|
|
4902
|
+
// USDC
|
|
4903
|
+
"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
|
|
4904
|
+
// USDT0
|
|
4905
|
+
"0xBe6727B535545C67d5cAa73dEa54865B92CF7907",
|
|
4906
|
+
// UETH
|
|
4907
|
+
"0x9FDBdA0A5e284c32744D2f17Ee5c74B284993463",
|
|
4908
|
+
// UBTC
|
|
4909
|
+
"0x111111a1a0667d36bD57c0A9f569b98057111111",
|
|
4910
|
+
// USDH
|
|
4911
|
+
"0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34",
|
|
4912
|
+
// USDe
|
|
4913
|
+
"0x211Cc4DD073734dA055fbF44a2b4667d5E5fE5d2",
|
|
4914
|
+
// sUSDe
|
|
4915
|
+
"0xf4D9235269a96aaDaFc9aDAe454a0618eBE37949",
|
|
4916
|
+
// XAUt0
|
|
4917
|
+
"0xfD739d4e423301CE9385c1fb8850539D657C296D",
|
|
4918
|
+
// kHYPE
|
|
4919
|
+
KITTEN_TOKEN
|
|
4920
|
+
// KITTEN
|
|
4921
|
+
];
|
|
4922
|
+
var farmingCenterAbi = parseAbi13([
|
|
4923
|
+
"function multicall(bytes[] calldata data) external payable returns (bytes[] memory results)",
|
|
4924
|
+
"function enterFarming((address rewardToken, address bonusRewardToken, address pool, uint256 nonce) key, uint256 tokenId) external",
|
|
4925
|
+
"function exitFarming((address rewardToken, address bonusRewardToken, address pool, uint256 nonce) key, uint256 tokenId) external",
|
|
4926
|
+
"function collectRewards((address rewardToken, address bonusRewardToken, address pool, uint256 nonce) key, uint256 tokenId) external",
|
|
4927
|
+
"function claimReward(address rewardToken, address to, uint128 amountRequested) external returns (uint256 reward)"
|
|
4928
|
+
]);
|
|
4929
|
+
var positionManagerAbi2 = parseAbi13([
|
|
4930
|
+
"function approveForFarming(uint256 tokenId, bool approve, address farmingAddress) external",
|
|
4931
|
+
"function farmingApprovals(uint256 tokenId) external view returns (address)"
|
|
4932
|
+
]);
|
|
4933
|
+
var eternalFarmingAbi = parseAbi13([
|
|
4934
|
+
"function incentives(bytes32 incentiveId) external view returns (uint256 totalReward, uint256 bonusReward, address virtualPoolAddress, uint24 minimalPositionWidth, bool deactivated, address pluginAddress)",
|
|
4935
|
+
"function getRewardInfo((address rewardToken, address bonusRewardToken, address pool, uint256 nonce) key, uint256 tokenId) external view returns (uint256 reward, uint256 bonusReward)"
|
|
4936
|
+
]);
|
|
4937
|
+
var algebraFactoryAbi = parseAbi13([
|
|
4938
|
+
"function poolByPair(address tokenA, address tokenB) external view returns (address pool)"
|
|
4939
|
+
]);
|
|
4940
|
+
var _addressDecodeAbi3 = parseAbi13(["function f() external view returns (address)"]);
|
|
4941
|
+
function decodeAddress3(data) {
|
|
4942
|
+
if (!data) return null;
|
|
4943
|
+
try {
|
|
4944
|
+
return decodeFunctionResult5({ abi: _addressDecodeAbi3, functionName: "f", data });
|
|
4945
|
+
} catch {
|
|
4946
|
+
return null;
|
|
4947
|
+
}
|
|
4948
|
+
}
|
|
4949
|
+
function incentiveId(key) {
|
|
4950
|
+
return keccak256(
|
|
4951
|
+
encodeAbiParameters(
|
|
4952
|
+
[
|
|
4953
|
+
{ name: "rewardToken", type: "address" },
|
|
4954
|
+
{ name: "bonusRewardToken", type: "address" },
|
|
4955
|
+
{ name: "pool", type: "address" },
|
|
4956
|
+
{ name: "nonce", type: "uint256" }
|
|
4957
|
+
],
|
|
4958
|
+
[key.rewardToken, key.bonusRewardToken, key.pool, key.nonce]
|
|
4959
|
+
)
|
|
4960
|
+
);
|
|
4961
|
+
}
|
|
4962
|
+
function encodeEnterFarming(key, tokenId) {
|
|
4963
|
+
return encodeFunctionData13({
|
|
4964
|
+
abi: farmingCenterAbi,
|
|
4965
|
+
functionName: "enterFarming",
|
|
4966
|
+
args: [key, tokenId]
|
|
4967
|
+
});
|
|
4968
|
+
}
|
|
4969
|
+
function encodeExitFarming(key, tokenId) {
|
|
4970
|
+
return encodeFunctionData13({
|
|
4971
|
+
abi: farmingCenterAbi,
|
|
4972
|
+
functionName: "exitFarming",
|
|
4973
|
+
args: [key, tokenId]
|
|
4974
|
+
});
|
|
4975
|
+
}
|
|
4976
|
+
function encodeCollectRewards(key, tokenId) {
|
|
4977
|
+
return encodeFunctionData13({
|
|
4978
|
+
abi: farmingCenterAbi,
|
|
4979
|
+
functionName: "collectRewards",
|
|
4980
|
+
args: [key, tokenId]
|
|
4981
|
+
});
|
|
4982
|
+
}
|
|
4983
|
+
function encodeClaimReward(rewardToken, to) {
|
|
4984
|
+
return encodeFunctionData13({
|
|
4985
|
+
abi: farmingCenterAbi,
|
|
4986
|
+
functionName: "claimReward",
|
|
4987
|
+
args: [rewardToken, to, 2n ** 128n - 1n]
|
|
4988
|
+
// max uint128
|
|
4989
|
+
});
|
|
4990
|
+
}
|
|
4991
|
+
function encodeMulticall(calls) {
|
|
4992
|
+
return encodeFunctionData13({
|
|
4993
|
+
abi: farmingCenterAbi,
|
|
4994
|
+
functionName: "multicall",
|
|
4995
|
+
args: [calls]
|
|
4996
|
+
});
|
|
4997
|
+
}
|
|
4998
|
+
var nonceCache = /* @__PURE__ */ new Map();
|
|
4999
|
+
var KittenSwapFarmingAdapter = class {
|
|
5000
|
+
protocolName;
|
|
5001
|
+
farmingCenter;
|
|
5002
|
+
eternalFarming;
|
|
5003
|
+
positionManager;
|
|
5004
|
+
rpcUrl;
|
|
5005
|
+
factory;
|
|
5006
|
+
constructor(protocolName, farmingCenter, eternalFarming, positionManager, rpcUrl, factory) {
|
|
5007
|
+
this.protocolName = protocolName;
|
|
5008
|
+
this.farmingCenter = farmingCenter;
|
|
5009
|
+
this.eternalFarming = eternalFarming;
|
|
5010
|
+
this.positionManager = positionManager;
|
|
5011
|
+
this.rpcUrl = rpcUrl;
|
|
5012
|
+
this.factory = factory;
|
|
5013
|
+
}
|
|
5014
|
+
name() {
|
|
5015
|
+
return this.protocolName;
|
|
5016
|
+
}
|
|
5017
|
+
/**
|
|
5018
|
+
* Discover the active IncentiveKey for a given pool.
|
|
5019
|
+
* 1. Check runtime cache
|
|
5020
|
+
* 2. Batch-query nonces 0-60 via single multicall (61 calls)
|
|
5021
|
+
* 3. Return first non-zero incentive (totalReward > 0 and not deactivated)
|
|
5022
|
+
*/
|
|
5023
|
+
async discoverIncentiveKey(pool) {
|
|
5024
|
+
const poolLc = pool.toLowerCase();
|
|
5025
|
+
if (nonceCache.has(poolLc)) {
|
|
5026
|
+
return {
|
|
5027
|
+
rewardToken: KITTEN_TOKEN,
|
|
5028
|
+
bonusRewardToken: WHYPE_TOKEN,
|
|
5029
|
+
pool,
|
|
5030
|
+
nonce: nonceCache.get(poolLc)
|
|
5031
|
+
};
|
|
5032
|
+
}
|
|
5033
|
+
const calls = [];
|
|
5034
|
+
const nonces = [];
|
|
5035
|
+
for (let n = 0; n <= MAX_NONCE_SCAN; n++) {
|
|
5036
|
+
const nonce = BigInt(n);
|
|
5037
|
+
nonces.push(nonce);
|
|
5038
|
+
const key = {
|
|
5039
|
+
rewardToken: KITTEN_TOKEN,
|
|
5040
|
+
bonusRewardToken: WHYPE_TOKEN,
|
|
5041
|
+
pool,
|
|
5042
|
+
nonce
|
|
5043
|
+
};
|
|
5044
|
+
calls.push([
|
|
5045
|
+
this.eternalFarming,
|
|
5046
|
+
encodeFunctionData13({
|
|
5047
|
+
abi: eternalFarmingAbi,
|
|
5048
|
+
functionName: "incentives",
|
|
5049
|
+
args: [incentiveId(key)]
|
|
5050
|
+
})
|
|
5051
|
+
]);
|
|
5052
|
+
}
|
|
5053
|
+
const results = await multicallRead(this.rpcUrl, calls);
|
|
5054
|
+
for (let i = 0; i < results.length; i++) {
|
|
5055
|
+
const data = results[i];
|
|
5056
|
+
if (!data || data.length < 66) continue;
|
|
5057
|
+
try {
|
|
5058
|
+
const decoded = decodeAbiParameters5(
|
|
5059
|
+
[
|
|
5060
|
+
{ name: "totalReward", type: "uint256" },
|
|
5061
|
+
{ name: "bonusReward", type: "uint256" },
|
|
5062
|
+
{ name: "virtualPoolAddress", type: "address" },
|
|
5063
|
+
{ name: "minimalPositionWidth", type: "uint24" },
|
|
5064
|
+
{ name: "deactivated", type: "bool" },
|
|
5065
|
+
{ name: "pluginAddress", type: "address" }
|
|
5066
|
+
],
|
|
5067
|
+
data
|
|
5068
|
+
);
|
|
5069
|
+
const totalReward = decoded[0];
|
|
5070
|
+
const deactivated = decoded[4];
|
|
5071
|
+
if (totalReward > 0n && !deactivated) {
|
|
5072
|
+
const nonce = nonces[i];
|
|
5073
|
+
nonceCache.set(poolLc, nonce);
|
|
5074
|
+
return {
|
|
5075
|
+
rewardToken: KITTEN_TOKEN,
|
|
5076
|
+
bonusRewardToken: WHYPE_TOKEN,
|
|
5077
|
+
pool,
|
|
5078
|
+
nonce
|
|
5079
|
+
};
|
|
5080
|
+
}
|
|
5081
|
+
} catch {
|
|
5082
|
+
}
|
|
5083
|
+
}
|
|
5084
|
+
return null;
|
|
5085
|
+
}
|
|
5086
|
+
/**
|
|
5087
|
+
* Build approveForFarming tx on the PositionManager.
|
|
5088
|
+
* Required before enterFarming if not already approved.
|
|
5089
|
+
*/
|
|
5090
|
+
async buildApproveForFarming(tokenId) {
|
|
5091
|
+
const client = createPublicClient9({ transport: http9(this.rpcUrl) });
|
|
5092
|
+
const currentApproval = await client.readContract({
|
|
5093
|
+
address: this.positionManager,
|
|
5094
|
+
abi: positionManagerAbi2,
|
|
5095
|
+
functionName: "farmingApprovals",
|
|
5096
|
+
args: [tokenId]
|
|
5097
|
+
});
|
|
5098
|
+
if (currentApproval.toLowerCase() === this.farmingCenter.toLowerCase()) {
|
|
5099
|
+
return null;
|
|
5100
|
+
}
|
|
5101
|
+
return {
|
|
5102
|
+
description: `[${this.protocolName}] Approve NFT #${tokenId} for farming`,
|
|
5103
|
+
to: this.positionManager,
|
|
5104
|
+
data: encodeFunctionData13({
|
|
5105
|
+
abi: positionManagerAbi2,
|
|
5106
|
+
functionName: "approveForFarming",
|
|
5107
|
+
args: [tokenId, true, this.farmingCenter]
|
|
5108
|
+
}),
|
|
5109
|
+
value: 0n,
|
|
5110
|
+
gas_estimate: 6e4
|
|
5111
|
+
};
|
|
5112
|
+
}
|
|
5113
|
+
/**
|
|
5114
|
+
* Build enterFarming tx for a position NFT.
|
|
5115
|
+
* Checks farming approval first and returns pre_txs if needed.
|
|
5116
|
+
*/
|
|
5117
|
+
async buildEnterFarming(tokenId, pool, _owner) {
|
|
5118
|
+
const key = await this.discoverIncentiveKey(pool);
|
|
5119
|
+
if (!key) {
|
|
5120
|
+
throw new DefiError(
|
|
5121
|
+
"CONTRACT_ERROR",
|
|
5122
|
+
`[${this.protocolName}] No active incentive found for pool ${pool}`
|
|
5123
|
+
);
|
|
5124
|
+
}
|
|
5125
|
+
const approveTx = await this.buildApproveForFarming(tokenId);
|
|
5126
|
+
return {
|
|
5127
|
+
description: `[${this.protocolName}] Enter farming for NFT #${tokenId} in pool ${pool}`,
|
|
5128
|
+
to: this.farmingCenter,
|
|
5129
|
+
data: encodeEnterFarming(key, tokenId),
|
|
5130
|
+
value: 0n,
|
|
5131
|
+
gas_estimate: 4e5,
|
|
5132
|
+
pre_txs: approveTx ? [approveTx] : void 0
|
|
5133
|
+
};
|
|
5134
|
+
}
|
|
5135
|
+
/**
|
|
5136
|
+
* Build a tx that exits farming for a position NFT (unstakes).
|
|
5137
|
+
*/
|
|
5138
|
+
async buildExitFarming(tokenId, pool) {
|
|
5139
|
+
const key = await this.discoverIncentiveKey(pool);
|
|
5140
|
+
if (!key) {
|
|
5141
|
+
throw new DefiError(
|
|
5142
|
+
"CONTRACT_ERROR",
|
|
5143
|
+
`[${this.protocolName}] No active incentive found for pool ${pool}`
|
|
5144
|
+
);
|
|
5145
|
+
}
|
|
5146
|
+
return {
|
|
5147
|
+
description: `[${this.protocolName}] Exit farming for NFT #${tokenId} in pool ${pool}`,
|
|
5148
|
+
to: this.farmingCenter,
|
|
5149
|
+
data: encodeExitFarming(key, tokenId),
|
|
5150
|
+
value: 0n,
|
|
5151
|
+
gas_estimate: 3e5
|
|
5152
|
+
};
|
|
5153
|
+
}
|
|
5154
|
+
/**
|
|
5155
|
+
* Build a multicall tx that collects rewards for a staked position and claims them.
|
|
5156
|
+
* Pattern: multicall([collectRewards(key, tokenId), claimReward(KITTEN, owner, max), claimReward(WHYPE, owner, max)])
|
|
5157
|
+
*/
|
|
5158
|
+
async buildCollectRewards(tokenId, pool, owner) {
|
|
5159
|
+
const key = await this.discoverIncentiveKey(pool);
|
|
5160
|
+
if (!key) {
|
|
5161
|
+
throw new DefiError(
|
|
5162
|
+
"CONTRACT_ERROR",
|
|
5163
|
+
`[${this.protocolName}] No active incentive found for pool ${pool}`
|
|
5164
|
+
);
|
|
5165
|
+
}
|
|
5166
|
+
const calls = [
|
|
5167
|
+
encodeCollectRewards(key, tokenId),
|
|
5168
|
+
encodeClaimReward(KITTEN_TOKEN, owner),
|
|
5169
|
+
encodeClaimReward(WHYPE_TOKEN, owner)
|
|
5170
|
+
];
|
|
5171
|
+
return {
|
|
5172
|
+
description: `[${this.protocolName}] Collect + claim rewards for NFT #${tokenId} in pool ${pool}`,
|
|
5173
|
+
to: this.farmingCenter,
|
|
5174
|
+
data: encodeMulticall(calls),
|
|
5175
|
+
value: 0n,
|
|
5176
|
+
gas_estimate: 4e5
|
|
5177
|
+
};
|
|
5178
|
+
}
|
|
5179
|
+
/**
|
|
5180
|
+
* Build a tx that only claims already-accumulated rewards (no position change needed).
|
|
5181
|
+
*/
|
|
5182
|
+
async buildClaimReward(owner) {
|
|
5183
|
+
const calls = [
|
|
5184
|
+
encodeClaimReward(KITTEN_TOKEN, owner),
|
|
5185
|
+
encodeClaimReward(WHYPE_TOKEN, owner)
|
|
5186
|
+
];
|
|
5187
|
+
return {
|
|
5188
|
+
description: `[${this.protocolName}] Claim KITTEN + WHYPE farming rewards to ${owner}`,
|
|
5189
|
+
to: this.farmingCenter,
|
|
5190
|
+
data: encodeMulticall(calls),
|
|
5191
|
+
value: 0n,
|
|
5192
|
+
gas_estimate: 2e5
|
|
5193
|
+
};
|
|
5194
|
+
}
|
|
5195
|
+
/**
|
|
5196
|
+
* Query pending rewards for a staked position NFT.
|
|
5197
|
+
*/
|
|
5198
|
+
async getPendingRewards(tokenId, pool) {
|
|
5199
|
+
const key = await this.discoverIncentiveKey(pool);
|
|
5200
|
+
if (!key) {
|
|
5201
|
+
return { reward: 0n, bonusReward: 0n };
|
|
5202
|
+
}
|
|
5203
|
+
const client = createPublicClient9({ transport: http9(this.rpcUrl) });
|
|
5204
|
+
const result = await client.readContract({
|
|
5205
|
+
address: this.eternalFarming,
|
|
5206
|
+
abi: eternalFarmingAbi,
|
|
5207
|
+
functionName: "getRewardInfo",
|
|
5208
|
+
args: [key, tokenId]
|
|
5209
|
+
});
|
|
5210
|
+
return { reward: result[0], bonusReward: result[1] };
|
|
5211
|
+
}
|
|
5212
|
+
/**
|
|
5213
|
+
* Discover all KittenSwap pools with active farming incentives.
|
|
5214
|
+
*
|
|
5215
|
+
* Steps:
|
|
5216
|
+
* 1. Generate all unique token pair combos from HYPEREVM_TOKENS (includes KITTEN)
|
|
5217
|
+
* 2. Batch poolByPair calls via multicall against the Algebra factory
|
|
5218
|
+
* 3. For each found pool, batch-scan nonces 0-60 via multicall
|
|
5219
|
+
* 4. Return enriched FarmingPool[] for pools with active incentives
|
|
5220
|
+
*/
|
|
5221
|
+
async discoverFarmingPools() {
|
|
5222
|
+
if (!this.factory) {
|
|
5223
|
+
return [];
|
|
5224
|
+
}
|
|
5225
|
+
const pairs = [];
|
|
5226
|
+
for (let i = 0; i < HYPEREVM_TOKENS2.length; i++) {
|
|
5227
|
+
for (let j = i + 1; j < HYPEREVM_TOKENS2.length; j++) {
|
|
5228
|
+
pairs.push([HYPEREVM_TOKENS2[i], HYPEREVM_TOKENS2[j]]);
|
|
5229
|
+
}
|
|
5230
|
+
}
|
|
5231
|
+
const poolByPairCalls = pairs.map(([tokenA, tokenB]) => [
|
|
5232
|
+
this.factory,
|
|
5233
|
+
encodeFunctionData13({
|
|
5234
|
+
abi: algebraFactoryAbi,
|
|
5235
|
+
functionName: "poolByPair",
|
|
5236
|
+
args: [tokenA, tokenB]
|
|
5237
|
+
})
|
|
5238
|
+
]);
|
|
5239
|
+
const poolResults = await multicallRead(this.rpcUrl, poolByPairCalls);
|
|
5240
|
+
const poolSet = /* @__PURE__ */ new Set();
|
|
5241
|
+
for (const data of poolResults) {
|
|
5242
|
+
const addr = decodeAddress3(data);
|
|
5243
|
+
if (addr && addr !== zeroAddress7) {
|
|
5244
|
+
poolSet.add(addr.toLowerCase());
|
|
5245
|
+
}
|
|
5246
|
+
}
|
|
5247
|
+
if (poolSet.size === 0) return [];
|
|
5248
|
+
const pools = Array.from(poolSet);
|
|
5249
|
+
const NONCE_COUNT = MAX_NONCE_SCAN + 1;
|
|
5250
|
+
const allNonceCalls = [];
|
|
5251
|
+
for (const pool of pools) {
|
|
5252
|
+
for (let n = 0; n <= MAX_NONCE_SCAN; n++) {
|
|
5253
|
+
const key = {
|
|
5254
|
+
rewardToken: KITTEN_TOKEN,
|
|
5255
|
+
bonusRewardToken: WHYPE_TOKEN,
|
|
5256
|
+
pool,
|
|
5257
|
+
nonce: BigInt(n)
|
|
5258
|
+
};
|
|
5259
|
+
allNonceCalls.push([
|
|
5260
|
+
this.eternalFarming,
|
|
5261
|
+
encodeFunctionData13({
|
|
5262
|
+
abi: eternalFarmingAbi,
|
|
5263
|
+
functionName: "incentives",
|
|
5264
|
+
args: [incentiveId(key)]
|
|
5265
|
+
})
|
|
5266
|
+
]);
|
|
5267
|
+
}
|
|
5268
|
+
}
|
|
5269
|
+
const allNonceResults = await multicallRead(this.rpcUrl, allNonceCalls);
|
|
5270
|
+
const results = [];
|
|
5271
|
+
for (let pi = 0; pi < pools.length; pi++) {
|
|
5272
|
+
const pool = pools[pi];
|
|
5273
|
+
const poolLc = pool.toLowerCase();
|
|
5274
|
+
const base = pi * NONCE_COUNT;
|
|
5275
|
+
let bestKey = null;
|
|
5276
|
+
let bestTotalReward = 0n;
|
|
5277
|
+
let bestBonusReward = 0n;
|
|
5278
|
+
let bestActive = false;
|
|
5279
|
+
for (let n = 0; n <= MAX_NONCE_SCAN; n++) {
|
|
5280
|
+
const data = allNonceResults[base + n];
|
|
5281
|
+
if (!data || data.length < 66) continue;
|
|
5282
|
+
try {
|
|
5283
|
+
const decoded = decodeAbiParameters5(
|
|
5284
|
+
[
|
|
5285
|
+
{ name: "totalReward", type: "uint256" },
|
|
5286
|
+
{ name: "bonusReward", type: "uint256" },
|
|
5287
|
+
{ name: "virtualPoolAddress", type: "address" },
|
|
5288
|
+
{ name: "minimalPositionWidth", type: "uint24" },
|
|
5289
|
+
{ name: "deactivated", type: "bool" },
|
|
5290
|
+
{ name: "pluginAddress", type: "address" }
|
|
5291
|
+
],
|
|
5292
|
+
data
|
|
5293
|
+
);
|
|
5294
|
+
const totalReward = decoded[0];
|
|
5295
|
+
const bonusReward = decoded[1];
|
|
5296
|
+
const deactivated = decoded[4];
|
|
5297
|
+
if (totalReward > 0n) {
|
|
5298
|
+
const nonce = BigInt(n);
|
|
5299
|
+
const isActive = !deactivated;
|
|
5300
|
+
if (!bestKey || isActive && !bestActive || isActive === bestActive && nonce > bestKey.nonce) {
|
|
5301
|
+
bestKey = {
|
|
5302
|
+
rewardToken: KITTEN_TOKEN,
|
|
5303
|
+
bonusRewardToken: WHYPE_TOKEN,
|
|
5304
|
+
pool,
|
|
5305
|
+
nonce
|
|
5306
|
+
};
|
|
5307
|
+
bestTotalReward = totalReward;
|
|
5308
|
+
bestBonusReward = bonusReward;
|
|
5309
|
+
bestActive = isActive;
|
|
5310
|
+
}
|
|
5311
|
+
}
|
|
5312
|
+
} catch {
|
|
5313
|
+
}
|
|
5314
|
+
}
|
|
5315
|
+
if (bestKey) {
|
|
5316
|
+
nonceCache.set(poolLc, bestKey.nonce);
|
|
5317
|
+
results.push({
|
|
5318
|
+
pool,
|
|
5319
|
+
key: bestKey,
|
|
5320
|
+
totalReward: bestTotalReward,
|
|
5321
|
+
bonusReward: bestBonusReward,
|
|
5322
|
+
active: bestActive
|
|
5323
|
+
});
|
|
5324
|
+
}
|
|
5325
|
+
}
|
|
5326
|
+
return results;
|
|
5327
|
+
}
|
|
3899
5328
|
};
|
|
3900
|
-
var POOL_ABI =
|
|
5329
|
+
var POOL_ABI = parseAbi14([
|
|
3901
5330
|
"function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
|
|
3902
5331
|
"function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
|
|
3903
5332
|
"function repay(address asset, uint256 amount, uint256 interestRateMode, address onBehalfOf) external returns (uint256)",
|
|
@@ -3905,27 +5334,27 @@ var POOL_ABI = parseAbi11([
|
|
|
3905
5334
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)",
|
|
3906
5335
|
"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)"
|
|
3907
5336
|
]);
|
|
3908
|
-
var ERC20_ABI2 =
|
|
5337
|
+
var ERC20_ABI2 = parseAbi14([
|
|
3909
5338
|
"function totalSupply() external view returns (uint256)"
|
|
3910
5339
|
]);
|
|
3911
|
-
var INCENTIVES_ABI =
|
|
5340
|
+
var INCENTIVES_ABI = parseAbi14([
|
|
3912
5341
|
"function getIncentivesController() external view returns (address)"
|
|
3913
5342
|
]);
|
|
3914
|
-
var REWARDS_CONTROLLER_ABI =
|
|
5343
|
+
var REWARDS_CONTROLLER_ABI = parseAbi14([
|
|
3915
5344
|
"function getRewardsByAsset(address asset) external view returns (address[])",
|
|
3916
5345
|
"function getRewardsData(address asset, address reward) external view returns (uint256 index, uint256 emissionsPerSecond, uint256 lastUpdateTimestamp, uint256 distributionEnd)"
|
|
3917
5346
|
]);
|
|
3918
|
-
var POOL_PROVIDER_ABI =
|
|
5347
|
+
var POOL_PROVIDER_ABI = parseAbi14([
|
|
3919
5348
|
"function ADDRESSES_PROVIDER() external view returns (address)"
|
|
3920
5349
|
]);
|
|
3921
|
-
var ADDRESSES_PROVIDER_ABI =
|
|
5350
|
+
var ADDRESSES_PROVIDER_ABI = parseAbi14([
|
|
3922
5351
|
"function getPriceOracle() external view returns (address)"
|
|
3923
5352
|
]);
|
|
3924
|
-
var ORACLE_ABI =
|
|
5353
|
+
var ORACLE_ABI = parseAbi14([
|
|
3925
5354
|
"function getAssetPrice(address asset) external view returns (uint256)",
|
|
3926
5355
|
"function BASE_CURRENCY_UNIT() external view returns (uint256)"
|
|
3927
5356
|
]);
|
|
3928
|
-
var ERC20_DECIMALS_ABI =
|
|
5357
|
+
var ERC20_DECIMALS_ABI = parseAbi14([
|
|
3929
5358
|
"function decimals() external view returns (uint8)"
|
|
3930
5359
|
]);
|
|
3931
5360
|
function u256ToF64(v) {
|
|
@@ -3933,14 +5362,14 @@ function u256ToF64(v) {
|
|
|
3933
5362
|
if (v > MAX_U128) return Infinity;
|
|
3934
5363
|
return Number(v);
|
|
3935
5364
|
}
|
|
3936
|
-
function
|
|
5365
|
+
function decodeAddress4(data) {
|
|
3937
5366
|
if (!data || data.length < 66) return null;
|
|
3938
5367
|
return `0x${data.slice(26, 66)}`;
|
|
3939
5368
|
}
|
|
3940
5369
|
function decodeAddressArray(data) {
|
|
3941
5370
|
if (!data) return [];
|
|
3942
5371
|
try {
|
|
3943
|
-
return
|
|
5372
|
+
return decodeFunctionResult6({
|
|
3944
5373
|
abi: REWARDS_CONTROLLER_ABI,
|
|
3945
5374
|
functionName: "getRewardsByAsset",
|
|
3946
5375
|
data
|
|
@@ -3952,7 +5381,7 @@ function decodeAddressArray(data) {
|
|
|
3952
5381
|
function decodeReserveData(data) {
|
|
3953
5382
|
if (!data) return null;
|
|
3954
5383
|
try {
|
|
3955
|
-
return
|
|
5384
|
+
return decodeFunctionResult6({
|
|
3956
5385
|
abi: POOL_ABI,
|
|
3957
5386
|
functionName: "getReserveData",
|
|
3958
5387
|
data
|
|
@@ -3964,7 +5393,7 @@ function decodeReserveData(data) {
|
|
|
3964
5393
|
function decodeRewardsData(data) {
|
|
3965
5394
|
if (!data) return null;
|
|
3966
5395
|
try {
|
|
3967
|
-
return
|
|
5396
|
+
return decodeFunctionResult6({
|
|
3968
5397
|
abi: REWARDS_CONTROLLER_ABI,
|
|
3969
5398
|
functionName: "getRewardsData",
|
|
3970
5399
|
data
|
|
@@ -3988,7 +5417,7 @@ var AaveV3Adapter = class {
|
|
|
3988
5417
|
return this.protocolName;
|
|
3989
5418
|
}
|
|
3990
5419
|
async buildSupply(params) {
|
|
3991
|
-
const data =
|
|
5420
|
+
const data = encodeFunctionData14({
|
|
3992
5421
|
abi: POOL_ABI,
|
|
3993
5422
|
functionName: "supply",
|
|
3994
5423
|
args: [params.asset, params.amount, params.on_behalf_of, 0]
|
|
@@ -4004,7 +5433,7 @@ var AaveV3Adapter = class {
|
|
|
4004
5433
|
}
|
|
4005
5434
|
async buildBorrow(params) {
|
|
4006
5435
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
4007
|
-
const data =
|
|
5436
|
+
const data = encodeFunctionData14({
|
|
4008
5437
|
abi: POOL_ABI,
|
|
4009
5438
|
functionName: "borrow",
|
|
4010
5439
|
args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
|
|
@@ -4019,7 +5448,7 @@ var AaveV3Adapter = class {
|
|
|
4019
5448
|
}
|
|
4020
5449
|
async buildRepay(params) {
|
|
4021
5450
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
4022
|
-
const data =
|
|
5451
|
+
const data = encodeFunctionData14({
|
|
4023
5452
|
abi: POOL_ABI,
|
|
4024
5453
|
functionName: "repay",
|
|
4025
5454
|
args: [params.asset, params.amount, rateMode, params.on_behalf_of]
|
|
@@ -4034,7 +5463,7 @@ var AaveV3Adapter = class {
|
|
|
4034
5463
|
};
|
|
4035
5464
|
}
|
|
4036
5465
|
async buildWithdraw(params) {
|
|
4037
|
-
const data =
|
|
5466
|
+
const data = encodeFunctionData14({
|
|
4038
5467
|
abi: POOL_ABI,
|
|
4039
5468
|
functionName: "withdraw",
|
|
4040
5469
|
args: [params.asset, params.amount, params.to]
|
|
@@ -4049,7 +5478,7 @@ var AaveV3Adapter = class {
|
|
|
4049
5478
|
}
|
|
4050
5479
|
async getRates(asset) {
|
|
4051
5480
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4052
|
-
const reserveCallData =
|
|
5481
|
+
const reserveCallData = encodeFunctionData14({
|
|
4053
5482
|
abi: POOL_ABI,
|
|
4054
5483
|
functionName: "getReserveData",
|
|
4055
5484
|
args: [asset]
|
|
@@ -4076,8 +5505,8 @@ var AaveV3Adapter = class {
|
|
|
4076
5505
|
const aTokenAddress = result[8];
|
|
4077
5506
|
const variableDebtTokenAddress = result[10];
|
|
4078
5507
|
const [supplyRaw, borrowRaw] = await multicallRead(this.rpcUrl, [
|
|
4079
|
-
[aTokenAddress,
|
|
4080
|
-
[variableDebtTokenAddress,
|
|
5508
|
+
[aTokenAddress, encodeFunctionData14({ abi: ERC20_ABI2, functionName: "totalSupply" })],
|
|
5509
|
+
[variableDebtTokenAddress, encodeFunctionData14({ abi: ERC20_ABI2, functionName: "totalSupply" })]
|
|
4081
5510
|
]);
|
|
4082
5511
|
const totalSupply = decodeU256(supplyRaw ?? null);
|
|
4083
5512
|
const totalBorrow = decodeU256(borrowRaw ?? null);
|
|
@@ -4088,24 +5517,24 @@ var AaveV3Adapter = class {
|
|
|
4088
5517
|
const borrowEmissions = [];
|
|
4089
5518
|
try {
|
|
4090
5519
|
const [controllerRaw] = await multicallRead(this.rpcUrl, [
|
|
4091
|
-
[aTokenAddress,
|
|
5520
|
+
[aTokenAddress, encodeFunctionData14({ abi: INCENTIVES_ABI, functionName: "getIncentivesController" })]
|
|
4092
5521
|
]);
|
|
4093
|
-
const controllerAddr =
|
|
4094
|
-
if (controllerAddr && controllerAddr !==
|
|
5522
|
+
const controllerAddr = decodeAddress4(controllerRaw ?? null);
|
|
5523
|
+
if (controllerAddr && controllerAddr !== zeroAddress8) {
|
|
4095
5524
|
const [supplyRewardsRaw, borrowRewardsRaw] = await multicallRead(this.rpcUrl, [
|
|
4096
|
-
[controllerAddr,
|
|
4097
|
-
[controllerAddr,
|
|
5525
|
+
[controllerAddr, encodeFunctionData14({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [aTokenAddress] })],
|
|
5526
|
+
[controllerAddr, encodeFunctionData14({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [variableDebtTokenAddress] })]
|
|
4098
5527
|
]);
|
|
4099
5528
|
const supplyRewards = decodeAddressArray(supplyRewardsRaw ?? null);
|
|
4100
5529
|
const borrowRewards = decodeAddressArray(borrowRewardsRaw ?? null);
|
|
4101
5530
|
const rewardsDataCalls = [
|
|
4102
5531
|
...supplyRewards.map((reward) => [
|
|
4103
5532
|
controllerAddr,
|
|
4104
|
-
|
|
5533
|
+
encodeFunctionData14({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [aTokenAddress, reward] })
|
|
4105
5534
|
]),
|
|
4106
5535
|
...borrowRewards.map((reward) => [
|
|
4107
5536
|
controllerAddr,
|
|
4108
|
-
|
|
5537
|
+
encodeFunctionData14({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [variableDebtTokenAddress, reward] })
|
|
4109
5538
|
])
|
|
4110
5539
|
];
|
|
4111
5540
|
if (rewardsDataCalls.length > 0) {
|
|
@@ -4137,19 +5566,19 @@ var AaveV3Adapter = class {
|
|
|
4137
5566
|
if ((hasSupplyRewards || hasBorrowRewards) && totalSupply > 0n) {
|
|
4138
5567
|
try {
|
|
4139
5568
|
const [providerRaw] = await multicallRead(this.rpcUrl, [
|
|
4140
|
-
[this.pool,
|
|
5569
|
+
[this.pool, encodeFunctionData14({ abi: POOL_PROVIDER_ABI, functionName: "ADDRESSES_PROVIDER" })]
|
|
4141
5570
|
]);
|
|
4142
|
-
const providerAddr =
|
|
5571
|
+
const providerAddr = decodeAddress4(providerRaw ?? null);
|
|
4143
5572
|
if (!providerAddr) throw new Error("No provider address");
|
|
4144
5573
|
const [oracleRaw] = await multicallRead(this.rpcUrl, [
|
|
4145
|
-
[providerAddr,
|
|
5574
|
+
[providerAddr, encodeFunctionData14({ abi: ADDRESSES_PROVIDER_ABI, functionName: "getPriceOracle" })]
|
|
4146
5575
|
]);
|
|
4147
|
-
const oracleAddr =
|
|
5576
|
+
const oracleAddr = decodeAddress4(oracleRaw ?? null);
|
|
4148
5577
|
if (!oracleAddr) throw new Error("No oracle address");
|
|
4149
5578
|
const [assetPriceRaw, baseCurrencyUnitRaw, assetDecimalsRaw] = await multicallRead(this.rpcUrl, [
|
|
4150
|
-
[oracleAddr,
|
|
4151
|
-
[oracleAddr,
|
|
4152
|
-
[asset,
|
|
5579
|
+
[oracleAddr, encodeFunctionData14({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [asset] })],
|
|
5580
|
+
[oracleAddr, encodeFunctionData14({ abi: ORACLE_ABI, functionName: "BASE_CURRENCY_UNIT" })],
|
|
5581
|
+
[asset, encodeFunctionData14({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
|
|
4153
5582
|
]);
|
|
4154
5583
|
const assetPrice = decodeU256(assetPriceRaw ?? null);
|
|
4155
5584
|
const baseCurrencyUnit = decodeU256(baseCurrencyUnitRaw ?? null);
|
|
@@ -4159,8 +5588,8 @@ var AaveV3Adapter = class {
|
|
|
4159
5588
|
const assetDecimalsDivisor = 10 ** assetDecimals;
|
|
4160
5589
|
const allRewardTokens = Array.from(/* @__PURE__ */ new Set([...supplyRewardTokens, ...borrowRewardTokens]));
|
|
4161
5590
|
const rewardPriceCalls = allRewardTokens.flatMap((token) => [
|
|
4162
|
-
[oracleAddr,
|
|
4163
|
-
[token,
|
|
5591
|
+
[oracleAddr, encodeFunctionData14({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [token] })],
|
|
5592
|
+
[token, encodeFunctionData14({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
|
|
4164
5593
|
]);
|
|
4165
5594
|
const rewardPriceResults = rewardPriceCalls.length > 0 ? await multicallRead(this.rpcUrl, rewardPriceCalls) : [];
|
|
4166
5595
|
const rewardPriceMap = /* @__PURE__ */ new Map();
|
|
@@ -4233,7 +5662,7 @@ var AaveV3Adapter = class {
|
|
|
4233
5662
|
}
|
|
4234
5663
|
async getUserPosition(user) {
|
|
4235
5664
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4236
|
-
const client =
|
|
5665
|
+
const client = createPublicClient10({ transport: http10(this.rpcUrl) });
|
|
4237
5666
|
const result = await client.readContract({
|
|
4238
5667
|
address: this.pool,
|
|
4239
5668
|
abi: POOL_ABI,
|
|
@@ -4248,8 +5677,8 @@ var AaveV3Adapter = class {
|
|
|
4248
5677
|
const collateralUsd = u256ToF64(totalCollateralBase) / 1e8;
|
|
4249
5678
|
const debtUsd = u256ToF64(totalDebtBase) / 1e8;
|
|
4250
5679
|
const ltvBps = u256ToF64(ltv);
|
|
4251
|
-
const supplies = collateralUsd > 0 ? [{ asset:
|
|
4252
|
-
const borrows = debtUsd > 0 ? [{ asset:
|
|
5680
|
+
const supplies = collateralUsd > 0 ? [{ asset: zeroAddress8, symbol: "Total Collateral", amount: totalCollateralBase, value_usd: collateralUsd }] : [];
|
|
5681
|
+
const borrows = debtUsd > 0 ? [{ asset: zeroAddress8, symbol: "Total Debt", amount: totalDebtBase, value_usd: debtUsd }] : [];
|
|
4253
5682
|
return {
|
|
4254
5683
|
protocol: this.protocolName,
|
|
4255
5684
|
user,
|
|
@@ -4260,7 +5689,7 @@ var AaveV3Adapter = class {
|
|
|
4260
5689
|
};
|
|
4261
5690
|
}
|
|
4262
5691
|
};
|
|
4263
|
-
var POOL_ABI2 =
|
|
5692
|
+
var POOL_ABI2 = parseAbi15([
|
|
4264
5693
|
"function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
|
|
4265
5694
|
"function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
|
|
4266
5695
|
"function repay(address asset, uint256 amount, uint256 rateMode, address onBehalfOf) external returns (uint256)",
|
|
@@ -4273,7 +5702,7 @@ var POOL_ABI2 = parseAbi12([
|
|
|
4273
5702
|
// [9]=variableDebtTokenAddress, [10]=interestRateStrategyAddress, [11]=id
|
|
4274
5703
|
"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)"
|
|
4275
5704
|
]);
|
|
4276
|
-
var ERC20_ABI22 =
|
|
5705
|
+
var ERC20_ABI22 = parseAbi15([
|
|
4277
5706
|
"function totalSupply() external view returns (uint256)"
|
|
4278
5707
|
]);
|
|
4279
5708
|
function u256ToF642(v) {
|
|
@@ -4296,7 +5725,7 @@ var AaveV2Adapter = class {
|
|
|
4296
5725
|
return this.protocolName;
|
|
4297
5726
|
}
|
|
4298
5727
|
async buildSupply(params) {
|
|
4299
|
-
const data =
|
|
5728
|
+
const data = encodeFunctionData15({
|
|
4300
5729
|
abi: POOL_ABI2,
|
|
4301
5730
|
functionName: "deposit",
|
|
4302
5731
|
args: [params.asset, params.amount, params.on_behalf_of, 0]
|
|
@@ -4312,7 +5741,7 @@ var AaveV2Adapter = class {
|
|
|
4312
5741
|
}
|
|
4313
5742
|
async buildBorrow(params) {
|
|
4314
5743
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
4315
|
-
const data =
|
|
5744
|
+
const data = encodeFunctionData15({
|
|
4316
5745
|
abi: POOL_ABI2,
|
|
4317
5746
|
functionName: "borrow",
|
|
4318
5747
|
args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
|
|
@@ -4327,7 +5756,7 @@ var AaveV2Adapter = class {
|
|
|
4327
5756
|
}
|
|
4328
5757
|
async buildRepay(params) {
|
|
4329
5758
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
4330
|
-
const data =
|
|
5759
|
+
const data = encodeFunctionData15({
|
|
4331
5760
|
abi: POOL_ABI2,
|
|
4332
5761
|
functionName: "repay",
|
|
4333
5762
|
args: [params.asset, params.amount, rateMode, params.on_behalf_of]
|
|
@@ -4342,7 +5771,7 @@ var AaveV2Adapter = class {
|
|
|
4342
5771
|
};
|
|
4343
5772
|
}
|
|
4344
5773
|
async buildWithdraw(params) {
|
|
4345
|
-
const data =
|
|
5774
|
+
const data = encodeFunctionData15({
|
|
4346
5775
|
abi: POOL_ABI2,
|
|
4347
5776
|
functionName: "withdraw",
|
|
4348
5777
|
args: [params.asset, params.amount, params.to]
|
|
@@ -4357,7 +5786,7 @@ var AaveV2Adapter = class {
|
|
|
4357
5786
|
}
|
|
4358
5787
|
async getRates(asset) {
|
|
4359
5788
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4360
|
-
const client =
|
|
5789
|
+
const client = createPublicClient11({ transport: http11(this.rpcUrl) });
|
|
4361
5790
|
const result = await client.readContract({
|
|
4362
5791
|
address: this.pool,
|
|
4363
5792
|
abi: POOL_ABI2,
|
|
@@ -4403,7 +5832,7 @@ var AaveV2Adapter = class {
|
|
|
4403
5832
|
}
|
|
4404
5833
|
async getUserPosition(user) {
|
|
4405
5834
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4406
|
-
const client =
|
|
5835
|
+
const client = createPublicClient11({ transport: http11(this.rpcUrl) });
|
|
4407
5836
|
const result = await client.readContract({
|
|
4408
5837
|
address: this.pool,
|
|
4409
5838
|
abi: POOL_ABI2,
|
|
@@ -4418,8 +5847,8 @@ var AaveV2Adapter = class {
|
|
|
4418
5847
|
const collateralUsd = u256ToF642(totalCollateralBase) / 1e18;
|
|
4419
5848
|
const debtUsd = u256ToF642(totalDebtBase) / 1e18;
|
|
4420
5849
|
const ltvBps = u256ToF642(ltv);
|
|
4421
|
-
const supplies = collateralUsd > 0 ? [{ asset:
|
|
4422
|
-
const borrows = debtUsd > 0 ? [{ asset:
|
|
5850
|
+
const supplies = collateralUsd > 0 ? [{ asset: zeroAddress9, symbol: "Total Collateral", amount: totalCollateralBase, value_usd: collateralUsd }] : [];
|
|
5851
|
+
const borrows = debtUsd > 0 ? [{ asset: zeroAddress9, symbol: "Total Debt", amount: totalDebtBase, value_usd: debtUsd }] : [];
|
|
4423
5852
|
return {
|
|
4424
5853
|
protocol: this.protocolName,
|
|
4425
5854
|
user,
|
|
@@ -4430,7 +5859,7 @@ var AaveV2Adapter = class {
|
|
|
4430
5859
|
};
|
|
4431
5860
|
}
|
|
4432
5861
|
};
|
|
4433
|
-
var ORACLE_ABI2 =
|
|
5862
|
+
var ORACLE_ABI2 = parseAbi16([
|
|
4434
5863
|
"function getAssetPrice(address asset) external view returns (uint256)",
|
|
4435
5864
|
"function getAssetsPrices(address[] calldata assets) external view returns (uint256[] memory)",
|
|
4436
5865
|
"function BASE_CURRENCY_UNIT() external view returns (uint256)"
|
|
@@ -4451,7 +5880,7 @@ var AaveOracleAdapter = class {
|
|
|
4451
5880
|
return this.protocolName;
|
|
4452
5881
|
}
|
|
4453
5882
|
async getPrice(asset) {
|
|
4454
|
-
const client =
|
|
5883
|
+
const client = createPublicClient12({ transport: http12(this.rpcUrl) });
|
|
4455
5884
|
const baseUnit = await client.readContract({
|
|
4456
5885
|
address: this.oracle,
|
|
4457
5886
|
abi: ORACLE_ABI2,
|
|
@@ -4478,7 +5907,7 @@ var AaveOracleAdapter = class {
|
|
|
4478
5907
|
};
|
|
4479
5908
|
}
|
|
4480
5909
|
async getPrices(assets) {
|
|
4481
|
-
const client =
|
|
5910
|
+
const client = createPublicClient12({ transport: http12(this.rpcUrl) });
|
|
4482
5911
|
const baseUnit = await client.readContract({
|
|
4483
5912
|
address: this.oracle,
|
|
4484
5913
|
abi: ORACLE_ABI2,
|
|
@@ -4507,7 +5936,7 @@ var AaveOracleAdapter = class {
|
|
|
4507
5936
|
});
|
|
4508
5937
|
}
|
|
4509
5938
|
};
|
|
4510
|
-
var CTOKEN_ABI =
|
|
5939
|
+
var CTOKEN_ABI = parseAbi17([
|
|
4511
5940
|
"function supplyRatePerBlock() external view returns (uint256)",
|
|
4512
5941
|
"function borrowRatePerBlock() external view returns (uint256)",
|
|
4513
5942
|
"function totalSupply() external view returns (uint256)",
|
|
@@ -4534,7 +5963,7 @@ var CompoundV2Adapter = class {
|
|
|
4534
5963
|
return this.protocolName;
|
|
4535
5964
|
}
|
|
4536
5965
|
async buildSupply(params) {
|
|
4537
|
-
const data =
|
|
5966
|
+
const data = encodeFunctionData16({
|
|
4538
5967
|
abi: CTOKEN_ABI,
|
|
4539
5968
|
functionName: "mint",
|
|
4540
5969
|
args: [params.amount]
|
|
@@ -4548,7 +5977,7 @@ var CompoundV2Adapter = class {
|
|
|
4548
5977
|
};
|
|
4549
5978
|
}
|
|
4550
5979
|
async buildBorrow(params) {
|
|
4551
|
-
const data =
|
|
5980
|
+
const data = encodeFunctionData16({
|
|
4552
5981
|
abi: CTOKEN_ABI,
|
|
4553
5982
|
functionName: "borrow",
|
|
4554
5983
|
args: [params.amount]
|
|
@@ -4562,7 +5991,7 @@ var CompoundV2Adapter = class {
|
|
|
4562
5991
|
};
|
|
4563
5992
|
}
|
|
4564
5993
|
async buildRepay(params) {
|
|
4565
|
-
const data =
|
|
5994
|
+
const data = encodeFunctionData16({
|
|
4566
5995
|
abi: CTOKEN_ABI,
|
|
4567
5996
|
functionName: "repayBorrow",
|
|
4568
5997
|
args: [params.amount]
|
|
@@ -4576,7 +6005,7 @@ var CompoundV2Adapter = class {
|
|
|
4576
6005
|
};
|
|
4577
6006
|
}
|
|
4578
6007
|
async buildWithdraw(params) {
|
|
4579
|
-
const data =
|
|
6008
|
+
const data = encodeFunctionData16({
|
|
4580
6009
|
abi: CTOKEN_ABI,
|
|
4581
6010
|
functionName: "redeem",
|
|
4582
6011
|
args: [params.amount]
|
|
@@ -4591,7 +6020,7 @@ var CompoundV2Adapter = class {
|
|
|
4591
6020
|
}
|
|
4592
6021
|
async getRates(asset) {
|
|
4593
6022
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4594
|
-
const client =
|
|
6023
|
+
const client = createPublicClient13({ transport: http13(this.rpcUrl) });
|
|
4595
6024
|
const [supplyRate, borrowRate, totalSupply, totalBorrows] = await Promise.all([
|
|
4596
6025
|
client.readContract({ address: this.defaultVtoken, abi: CTOKEN_ABI, functionName: "supplyRatePerBlock" }).catch((e) => {
|
|
4597
6026
|
throw DefiError.rpcError(`[${this.protocolName}] supplyRatePerBlock failed: ${e}`);
|
|
@@ -4625,7 +6054,7 @@ var CompoundV2Adapter = class {
|
|
|
4625
6054
|
);
|
|
4626
6055
|
}
|
|
4627
6056
|
};
|
|
4628
|
-
var COMET_ABI =
|
|
6057
|
+
var COMET_ABI = parseAbi18([
|
|
4629
6058
|
"function getUtilization() external view returns (uint256)",
|
|
4630
6059
|
"function getSupplyRate(uint256 utilization) external view returns (uint64)",
|
|
4631
6060
|
"function getBorrowRate(uint256 utilization) external view returns (uint64)",
|
|
@@ -4651,7 +6080,7 @@ var CompoundV3Adapter = class {
|
|
|
4651
6080
|
return this.protocolName;
|
|
4652
6081
|
}
|
|
4653
6082
|
async buildSupply(params) {
|
|
4654
|
-
const data =
|
|
6083
|
+
const data = encodeFunctionData17({
|
|
4655
6084
|
abi: COMET_ABI,
|
|
4656
6085
|
functionName: "supply",
|
|
4657
6086
|
args: [params.asset, params.amount]
|
|
@@ -4665,7 +6094,7 @@ var CompoundV3Adapter = class {
|
|
|
4665
6094
|
};
|
|
4666
6095
|
}
|
|
4667
6096
|
async buildBorrow(params) {
|
|
4668
|
-
const data =
|
|
6097
|
+
const data = encodeFunctionData17({
|
|
4669
6098
|
abi: COMET_ABI,
|
|
4670
6099
|
functionName: "withdraw",
|
|
4671
6100
|
args: [params.asset, params.amount]
|
|
@@ -4679,7 +6108,7 @@ var CompoundV3Adapter = class {
|
|
|
4679
6108
|
};
|
|
4680
6109
|
}
|
|
4681
6110
|
async buildRepay(params) {
|
|
4682
|
-
const data =
|
|
6111
|
+
const data = encodeFunctionData17({
|
|
4683
6112
|
abi: COMET_ABI,
|
|
4684
6113
|
functionName: "supply",
|
|
4685
6114
|
args: [params.asset, params.amount]
|
|
@@ -4693,7 +6122,7 @@ var CompoundV3Adapter = class {
|
|
|
4693
6122
|
};
|
|
4694
6123
|
}
|
|
4695
6124
|
async buildWithdraw(params) {
|
|
4696
|
-
const data =
|
|
6125
|
+
const data = encodeFunctionData17({
|
|
4697
6126
|
abi: COMET_ABI,
|
|
4698
6127
|
functionName: "withdraw",
|
|
4699
6128
|
args: [params.asset, params.amount]
|
|
@@ -4708,7 +6137,7 @@ var CompoundV3Adapter = class {
|
|
|
4708
6137
|
}
|
|
4709
6138
|
async getRates(asset) {
|
|
4710
6139
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4711
|
-
const client =
|
|
6140
|
+
const client = createPublicClient14({ transport: http14(this.rpcUrl) });
|
|
4712
6141
|
const utilization = await client.readContract({
|
|
4713
6142
|
address: this.comet,
|
|
4714
6143
|
abi: COMET_ABI,
|
|
@@ -4747,7 +6176,7 @@ var CompoundV3Adapter = class {
|
|
|
4747
6176
|
);
|
|
4748
6177
|
}
|
|
4749
6178
|
};
|
|
4750
|
-
var EULER_VAULT_ABI =
|
|
6179
|
+
var EULER_VAULT_ABI = parseAbi19([
|
|
4751
6180
|
"function deposit(uint256 amount, address receiver) external returns (uint256)",
|
|
4752
6181
|
"function withdraw(uint256 amount, address receiver, address owner) external returns (uint256)",
|
|
4753
6182
|
"function borrow(uint256 amount, address receiver) external returns (uint256)",
|
|
@@ -4773,7 +6202,7 @@ var EulerV2Adapter = class {
|
|
|
4773
6202
|
return this.protocolName;
|
|
4774
6203
|
}
|
|
4775
6204
|
async buildSupply(params) {
|
|
4776
|
-
const data =
|
|
6205
|
+
const data = encodeFunctionData18({
|
|
4777
6206
|
abi: EULER_VAULT_ABI,
|
|
4778
6207
|
functionName: "deposit",
|
|
4779
6208
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -4787,7 +6216,7 @@ var EulerV2Adapter = class {
|
|
|
4787
6216
|
};
|
|
4788
6217
|
}
|
|
4789
6218
|
async buildBorrow(params) {
|
|
4790
|
-
const data =
|
|
6219
|
+
const data = encodeFunctionData18({
|
|
4791
6220
|
abi: EULER_VAULT_ABI,
|
|
4792
6221
|
functionName: "borrow",
|
|
4793
6222
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -4801,7 +6230,7 @@ var EulerV2Adapter = class {
|
|
|
4801
6230
|
};
|
|
4802
6231
|
}
|
|
4803
6232
|
async buildRepay(params) {
|
|
4804
|
-
const data =
|
|
6233
|
+
const data = encodeFunctionData18({
|
|
4805
6234
|
abi: EULER_VAULT_ABI,
|
|
4806
6235
|
functionName: "repay",
|
|
4807
6236
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -4815,7 +6244,7 @@ var EulerV2Adapter = class {
|
|
|
4815
6244
|
};
|
|
4816
6245
|
}
|
|
4817
6246
|
async buildWithdraw(params) {
|
|
4818
|
-
const data =
|
|
6247
|
+
const data = encodeFunctionData18({
|
|
4819
6248
|
abi: EULER_VAULT_ABI,
|
|
4820
6249
|
functionName: "withdraw",
|
|
4821
6250
|
args: [params.amount, params.to, params.to]
|
|
@@ -4830,7 +6259,7 @@ var EulerV2Adapter = class {
|
|
|
4830
6259
|
}
|
|
4831
6260
|
async getRates(asset) {
|
|
4832
6261
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4833
|
-
const client =
|
|
6262
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4834
6263
|
const [totalSupply, totalBorrows, interestRate] = await Promise.all([
|
|
4835
6264
|
client.readContract({ address: this.euler, abi: EULER_VAULT_ABI, functionName: "totalSupply" }).catch((e) => {
|
|
4836
6265
|
throw DefiError.rpcError(`[${this.protocolName}] totalSupply failed: ${e}`);
|
|
@@ -4864,7 +6293,7 @@ var EulerV2Adapter = class {
|
|
|
4864
6293
|
);
|
|
4865
6294
|
}
|
|
4866
6295
|
};
|
|
4867
|
-
var MORPHO_ABI =
|
|
6296
|
+
var MORPHO_ABI = parseAbi20([
|
|
4868
6297
|
"function market(bytes32 id) external view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)",
|
|
4869
6298
|
"function idToMarketParams(bytes32 id) external view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)",
|
|
4870
6299
|
"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)",
|
|
@@ -4872,29 +6301,29 @@ var MORPHO_ABI = parseAbi17([
|
|
|
4872
6301
|
"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)",
|
|
4873
6302
|
"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)"
|
|
4874
6303
|
]);
|
|
4875
|
-
var META_MORPHO_ABI =
|
|
6304
|
+
var META_MORPHO_ABI = parseAbi20([
|
|
4876
6305
|
"function supplyQueueLength() external view returns (uint256)",
|
|
4877
6306
|
"function supplyQueue(uint256 index) external view returns (bytes32)",
|
|
4878
6307
|
"function totalAssets() external view returns (uint256)",
|
|
4879
6308
|
"function totalSupply() external view returns (uint256)"
|
|
4880
6309
|
]);
|
|
4881
|
-
var IRM_ABI =
|
|
6310
|
+
var IRM_ABI = parseAbi20([
|
|
4882
6311
|
"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)"
|
|
4883
6312
|
]);
|
|
4884
6313
|
var SECONDS_PER_YEAR3 = 365.25 * 24 * 3600;
|
|
4885
|
-
function defaultMarketParams(loanToken =
|
|
6314
|
+
function defaultMarketParams(loanToken = zeroAddress10) {
|
|
4886
6315
|
return {
|
|
4887
6316
|
loanToken,
|
|
4888
|
-
collateralToken:
|
|
4889
|
-
oracle:
|
|
4890
|
-
irm:
|
|
6317
|
+
collateralToken: zeroAddress10,
|
|
6318
|
+
oracle: zeroAddress10,
|
|
6319
|
+
irm: zeroAddress10,
|
|
4891
6320
|
lltv: 0n
|
|
4892
6321
|
};
|
|
4893
6322
|
}
|
|
4894
6323
|
function decodeMarket(data) {
|
|
4895
6324
|
if (!data) return null;
|
|
4896
6325
|
try {
|
|
4897
|
-
return
|
|
6326
|
+
return decodeFunctionResult7({
|
|
4898
6327
|
abi: MORPHO_ABI,
|
|
4899
6328
|
functionName: "market",
|
|
4900
6329
|
data
|
|
@@ -4906,7 +6335,7 @@ function decodeMarket(data) {
|
|
|
4906
6335
|
function decodeMarketParams(data) {
|
|
4907
6336
|
if (!data) return null;
|
|
4908
6337
|
try {
|
|
4909
|
-
return
|
|
6338
|
+
return decodeFunctionResult7({
|
|
4910
6339
|
abi: MORPHO_ABI,
|
|
4911
6340
|
functionName: "idToMarketParams",
|
|
4912
6341
|
data
|
|
@@ -4934,7 +6363,7 @@ var MorphoBlueAdapter = class {
|
|
|
4934
6363
|
}
|
|
4935
6364
|
async buildSupply(params) {
|
|
4936
6365
|
const market = defaultMarketParams(params.asset);
|
|
4937
|
-
const data =
|
|
6366
|
+
const data = encodeFunctionData19({
|
|
4938
6367
|
abi: MORPHO_ABI,
|
|
4939
6368
|
functionName: "supply",
|
|
4940
6369
|
args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
|
|
@@ -4949,7 +6378,7 @@ var MorphoBlueAdapter = class {
|
|
|
4949
6378
|
}
|
|
4950
6379
|
async buildBorrow(params) {
|
|
4951
6380
|
const market = defaultMarketParams(params.asset);
|
|
4952
|
-
const data =
|
|
6381
|
+
const data = encodeFunctionData19({
|
|
4953
6382
|
abi: MORPHO_ABI,
|
|
4954
6383
|
functionName: "borrow",
|
|
4955
6384
|
args: [market, params.amount, 0n, params.on_behalf_of, params.on_behalf_of]
|
|
@@ -4964,7 +6393,7 @@ var MorphoBlueAdapter = class {
|
|
|
4964
6393
|
}
|
|
4965
6394
|
async buildRepay(params) {
|
|
4966
6395
|
const market = defaultMarketParams(params.asset);
|
|
4967
|
-
const data =
|
|
6396
|
+
const data = encodeFunctionData19({
|
|
4968
6397
|
abi: MORPHO_ABI,
|
|
4969
6398
|
functionName: "repay",
|
|
4970
6399
|
args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
|
|
@@ -4979,7 +6408,7 @@ var MorphoBlueAdapter = class {
|
|
|
4979
6408
|
}
|
|
4980
6409
|
async buildWithdraw(params) {
|
|
4981
6410
|
const market = defaultMarketParams(params.asset);
|
|
4982
|
-
const data =
|
|
6411
|
+
const data = encodeFunctionData19({
|
|
4983
6412
|
abi: MORPHO_ABI,
|
|
4984
6413
|
functionName: "withdraw",
|
|
4985
6414
|
args: [market, params.amount, 0n, params.to, params.to]
|
|
@@ -4998,7 +6427,7 @@ var MorphoBlueAdapter = class {
|
|
|
4998
6427
|
throw DefiError.contractError(`[${this.protocolName}] No MetaMorpho vault configured for rate query`);
|
|
4999
6428
|
}
|
|
5000
6429
|
const [queueLenRaw] = await multicallRead(this.rpcUrl, [
|
|
5001
|
-
[this.defaultVault,
|
|
6430
|
+
[this.defaultVault, encodeFunctionData19({ abi: META_MORPHO_ABI, functionName: "supplyQueueLength" })]
|
|
5002
6431
|
]).catch((e) => {
|
|
5003
6432
|
throw DefiError.rpcError(`[${this.protocolName}] supplyQueueLength failed: ${e}`);
|
|
5004
6433
|
});
|
|
@@ -5015,7 +6444,7 @@ var MorphoBlueAdapter = class {
|
|
|
5015
6444
|
};
|
|
5016
6445
|
}
|
|
5017
6446
|
const [marketIdRaw] = await multicallRead(this.rpcUrl, [
|
|
5018
|
-
[this.defaultVault,
|
|
6447
|
+
[this.defaultVault, encodeFunctionData19({ abi: META_MORPHO_ABI, functionName: "supplyQueue", args: [0n] })]
|
|
5019
6448
|
]).catch((e) => {
|
|
5020
6449
|
throw DefiError.rpcError(`[${this.protocolName}] supplyQueue(0) failed: ${e}`);
|
|
5021
6450
|
});
|
|
@@ -5024,8 +6453,8 @@ var MorphoBlueAdapter = class {
|
|
|
5024
6453
|
}
|
|
5025
6454
|
const marketId = marketIdRaw.slice(0, 66);
|
|
5026
6455
|
const [marketRaw, paramsRaw] = await multicallRead(this.rpcUrl, [
|
|
5027
|
-
[this.morpho,
|
|
5028
|
-
[this.morpho,
|
|
6456
|
+
[this.morpho, encodeFunctionData19({ abi: MORPHO_ABI, functionName: "market", args: [marketId] })],
|
|
6457
|
+
[this.morpho, encodeFunctionData19({ abi: MORPHO_ABI, functionName: "idToMarketParams", args: [marketId] })]
|
|
5029
6458
|
]).catch((e) => {
|
|
5030
6459
|
throw DefiError.rpcError(`[${this.protocolName}] market/idToMarketParams failed: ${e}`);
|
|
5031
6460
|
});
|
|
@@ -5042,7 +6471,7 @@ var MorphoBlueAdapter = class {
|
|
|
5042
6471
|
const irmMarket = { totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee };
|
|
5043
6472
|
const borrowRatePerSec = await (async () => {
|
|
5044
6473
|
const [borrowRateRaw] = await multicallRead(this.rpcUrl, [
|
|
5045
|
-
[irm,
|
|
6474
|
+
[irm, encodeFunctionData19({ abi: IRM_ABI, functionName: "borrowRateView", args: [irmMarketParams, irmMarket] })]
|
|
5046
6475
|
]).catch((e) => {
|
|
5047
6476
|
throw DefiError.rpcError(`[${this.protocolName}] borrowRateView failed: ${e}`);
|
|
5048
6477
|
});
|
|
@@ -5068,18 +6497,18 @@ var MorphoBlueAdapter = class {
|
|
|
5068
6497
|
);
|
|
5069
6498
|
}
|
|
5070
6499
|
};
|
|
5071
|
-
var BORROWER_OPS_ABI =
|
|
6500
|
+
var BORROWER_OPS_ABI = parseAbi21([
|
|
5072
6501
|
"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)",
|
|
5073
6502
|
"function adjustTrove(uint256 _troveId, uint256 _collChange, bool _isCollIncrease, uint256 _debtChange, bool _isDebtIncrease, uint256 _upperHint, uint256 _lowerHint, uint256 _maxUpfrontFee) external",
|
|
5074
6503
|
"function closeTrove(uint256 _troveId) external"
|
|
5075
6504
|
]);
|
|
5076
|
-
var TROVE_MANAGER_ABI =
|
|
6505
|
+
var TROVE_MANAGER_ABI = parseAbi21([
|
|
5077
6506
|
"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)"
|
|
5078
6507
|
]);
|
|
5079
|
-
var HINT_HELPERS_ABI =
|
|
6508
|
+
var HINT_HELPERS_ABI = parseAbi21([
|
|
5080
6509
|
"function getApproxHint(uint256 _collIndex, uint256 _interestRate, uint256 _numTrials, uint256 _inputRandomSeed) external view returns (uint256 hintId, uint256 diff, uint256 latestRandomSeed)"
|
|
5081
6510
|
]);
|
|
5082
|
-
var SORTED_TROVES_ABI =
|
|
6511
|
+
var SORTED_TROVES_ABI = parseAbi21([
|
|
5083
6512
|
"function findInsertPosition(uint256 _annualInterestRate, uint256 _prevId, uint256 _nextId) external view returns (uint256 prevId, uint256 nextId)"
|
|
5084
6513
|
]);
|
|
5085
6514
|
var FelixCdpAdapter = class {
|
|
@@ -5107,7 +6536,7 @@ var FelixCdpAdapter = class {
|
|
|
5107
6536
|
if (!this.hintHelpers || !this.sortedTroves || !this.rpcUrl) {
|
|
5108
6537
|
return [0n, 0n];
|
|
5109
6538
|
}
|
|
5110
|
-
const client =
|
|
6539
|
+
const client = createPublicClient16({ transport: http16(this.rpcUrl) });
|
|
5111
6540
|
const approxResult = await client.readContract({
|
|
5112
6541
|
address: this.hintHelpers,
|
|
5113
6542
|
abi: HINT_HELPERS_ABI,
|
|
@@ -5130,7 +6559,7 @@ var FelixCdpAdapter = class {
|
|
|
5130
6559
|
const interestRate = 50000000000000000n;
|
|
5131
6560
|
const [upperHint, lowerHint] = await this.getHints(interestRate);
|
|
5132
6561
|
const hasHints = upperHint !== 0n || lowerHint !== 0n;
|
|
5133
|
-
const data =
|
|
6562
|
+
const data = encodeFunctionData20({
|
|
5134
6563
|
abi: BORROWER_OPS_ABI,
|
|
5135
6564
|
functionName: "openTrove",
|
|
5136
6565
|
args: [
|
|
@@ -5159,7 +6588,7 @@ var FelixCdpAdapter = class {
|
|
|
5159
6588
|
async buildAdjust(params) {
|
|
5160
6589
|
const collChange = params.collateral_delta ?? 0n;
|
|
5161
6590
|
const debtChange = params.debt_delta ?? 0n;
|
|
5162
|
-
const data =
|
|
6591
|
+
const data = encodeFunctionData20({
|
|
5163
6592
|
abi: BORROWER_OPS_ABI,
|
|
5164
6593
|
functionName: "adjustTrove",
|
|
5165
6594
|
args: [
|
|
@@ -5182,7 +6611,7 @@ var FelixCdpAdapter = class {
|
|
|
5182
6611
|
};
|
|
5183
6612
|
}
|
|
5184
6613
|
async buildClose(params) {
|
|
5185
|
-
const data =
|
|
6614
|
+
const data = encodeFunctionData20({
|
|
5186
6615
|
abi: BORROWER_OPS_ABI,
|
|
5187
6616
|
functionName: "closeTrove",
|
|
5188
6617
|
args: [params.cdp_id]
|
|
@@ -5198,7 +6627,7 @@ var FelixCdpAdapter = class {
|
|
|
5198
6627
|
async getCdpInfo(cdpId) {
|
|
5199
6628
|
if (!this.rpcUrl) throw DefiError.rpcError(`[${this.protocolName}] getCdpInfo requires RPC \u2014 set HYPEREVM_RPC_URL`);
|
|
5200
6629
|
if (!this.troveManager) throw DefiError.contractError(`[${this.protocolName}] trove_manager contract not configured`);
|
|
5201
|
-
const client =
|
|
6630
|
+
const client = createPublicClient16({ transport: http16(this.rpcUrl) });
|
|
5202
6631
|
const data = await client.readContract({
|
|
5203
6632
|
address: this.troveManager,
|
|
5204
6633
|
abi: TROVE_MANAGER_ABI,
|
|
@@ -5216,13 +6645,13 @@ var FelixCdpAdapter = class {
|
|
|
5216
6645
|
protocol: this.protocolName,
|
|
5217
6646
|
cdp_id: cdpId,
|
|
5218
6647
|
collateral: {
|
|
5219
|
-
token:
|
|
6648
|
+
token: zeroAddress11,
|
|
5220
6649
|
symbol: "WHYPE",
|
|
5221
6650
|
amount: entireColl,
|
|
5222
6651
|
decimals: 18
|
|
5223
6652
|
},
|
|
5224
6653
|
debt: {
|
|
5225
|
-
token:
|
|
6654
|
+
token: zeroAddress11,
|
|
5226
6655
|
symbol: "feUSD",
|
|
5227
6656
|
amount: entireDebt,
|
|
5228
6657
|
decimals: 18
|
|
@@ -5231,7 +6660,7 @@ var FelixCdpAdapter = class {
|
|
|
5231
6660
|
};
|
|
5232
6661
|
}
|
|
5233
6662
|
};
|
|
5234
|
-
var PRICE_FEED_ABI =
|
|
6663
|
+
var PRICE_FEED_ABI = parseAbi222([
|
|
5235
6664
|
"function fetchPrice() external view returns (uint256 price, bool isNewOracleFailureDetected)",
|
|
5236
6665
|
"function lastGoodPrice() external view returns (uint256)"
|
|
5237
6666
|
]);
|
|
@@ -5257,7 +6686,7 @@ var FelixOracleAdapter = class {
|
|
|
5257
6686
|
if (asset !== this.asset && this.asset !== "0x0000000000000000000000000000000000000000") {
|
|
5258
6687
|
throw DefiError.unsupported(`[${this.protocolName}] Felix PriceFeed only supports asset ${this.asset}`);
|
|
5259
6688
|
}
|
|
5260
|
-
const client =
|
|
6689
|
+
const client = createPublicClient17({ transport: http17(this.rpcUrl) });
|
|
5261
6690
|
let priceVal;
|
|
5262
6691
|
try {
|
|
5263
6692
|
const result = await client.readContract({
|
|
@@ -5296,7 +6725,7 @@ var FelixOracleAdapter = class {
|
|
|
5296
6725
|
return results;
|
|
5297
6726
|
}
|
|
5298
6727
|
};
|
|
5299
|
-
var ERC4626_ABI =
|
|
6728
|
+
var ERC4626_ABI = parseAbi23([
|
|
5300
6729
|
"function asset() external view returns (address)",
|
|
5301
6730
|
"function totalAssets() external view returns (uint256)",
|
|
5302
6731
|
"function totalSupply() external view returns (uint256)",
|
|
@@ -5320,7 +6749,7 @@ var ERC4626VaultAdapter = class {
|
|
|
5320
6749
|
return this.protocolName;
|
|
5321
6750
|
}
|
|
5322
6751
|
async buildDeposit(assets, receiver) {
|
|
5323
|
-
const data =
|
|
6752
|
+
const data = encodeFunctionData21({
|
|
5324
6753
|
abi: ERC4626_ABI,
|
|
5325
6754
|
functionName: "deposit",
|
|
5326
6755
|
args: [assets, receiver]
|
|
@@ -5334,7 +6763,7 @@ var ERC4626VaultAdapter = class {
|
|
|
5334
6763
|
};
|
|
5335
6764
|
}
|
|
5336
6765
|
async buildWithdraw(assets, receiver, owner) {
|
|
5337
|
-
const data =
|
|
6766
|
+
const data = encodeFunctionData21({
|
|
5338
6767
|
abi: ERC4626_ABI,
|
|
5339
6768
|
functionName: "withdraw",
|
|
5340
6769
|
args: [assets, receiver, owner]
|
|
@@ -5349,7 +6778,7 @@ var ERC4626VaultAdapter = class {
|
|
|
5349
6778
|
}
|
|
5350
6779
|
async totalAssets() {
|
|
5351
6780
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5352
|
-
const client =
|
|
6781
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
5353
6782
|
return client.readContract({
|
|
5354
6783
|
address: this.vaultAddress,
|
|
5355
6784
|
abi: ERC4626_ABI,
|
|
@@ -5360,7 +6789,7 @@ var ERC4626VaultAdapter = class {
|
|
|
5360
6789
|
}
|
|
5361
6790
|
async convertToShares(assets) {
|
|
5362
6791
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5363
|
-
const client =
|
|
6792
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
5364
6793
|
return client.readContract({
|
|
5365
6794
|
address: this.vaultAddress,
|
|
5366
6795
|
abi: ERC4626_ABI,
|
|
@@ -5372,7 +6801,7 @@ var ERC4626VaultAdapter = class {
|
|
|
5372
6801
|
}
|
|
5373
6802
|
async convertToAssets(shares) {
|
|
5374
6803
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5375
|
-
const client =
|
|
6804
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
5376
6805
|
return client.readContract({
|
|
5377
6806
|
address: this.vaultAddress,
|
|
5378
6807
|
abi: ERC4626_ABI,
|
|
@@ -5384,7 +6813,7 @@ var ERC4626VaultAdapter = class {
|
|
|
5384
6813
|
}
|
|
5385
6814
|
async getVaultInfo() {
|
|
5386
6815
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5387
|
-
const client =
|
|
6816
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
5388
6817
|
const [totalAssets, totalSupply, asset] = await Promise.all([
|
|
5389
6818
|
client.readContract({ address: this.vaultAddress, abi: ERC4626_ABI, functionName: "totalAssets" }).catch((e) => {
|
|
5390
6819
|
throw DefiError.rpcError(`[${this.protocolName}] totalAssets failed: ${e}`);
|
|
@@ -5405,7 +6834,7 @@ var ERC4626VaultAdapter = class {
|
|
|
5405
6834
|
};
|
|
5406
6835
|
}
|
|
5407
6836
|
};
|
|
5408
|
-
var GENERIC_LST_ABI =
|
|
6837
|
+
var GENERIC_LST_ABI = parseAbi24([
|
|
5409
6838
|
"function stake() external payable returns (uint256)",
|
|
5410
6839
|
"function unstake(uint256 amount) external returns (uint256)"
|
|
5411
6840
|
]);
|
|
@@ -5422,7 +6851,7 @@ var GenericLstAdapter = class {
|
|
|
5422
6851
|
return this.protocolName;
|
|
5423
6852
|
}
|
|
5424
6853
|
async buildStake(params) {
|
|
5425
|
-
const data =
|
|
6854
|
+
const data = encodeFunctionData222({ abi: GENERIC_LST_ABI, functionName: "stake" });
|
|
5426
6855
|
return {
|
|
5427
6856
|
description: `[${this.protocolName}] Stake ${params.amount} HYPE`,
|
|
5428
6857
|
to: this.staking,
|
|
@@ -5432,7 +6861,7 @@ var GenericLstAdapter = class {
|
|
|
5432
6861
|
};
|
|
5433
6862
|
}
|
|
5434
6863
|
async buildUnstake(params) {
|
|
5435
|
-
const data =
|
|
6864
|
+
const data = encodeFunctionData222({
|
|
5436
6865
|
abi: GENERIC_LST_ABI,
|
|
5437
6866
|
functionName: "unstake",
|
|
5438
6867
|
args: [params.amount]
|
|
@@ -5449,11 +6878,11 @@ var GenericLstAdapter = class {
|
|
|
5449
6878
|
throw DefiError.unsupported(`[${this.protocolName}] getInfo requires RPC`);
|
|
5450
6879
|
}
|
|
5451
6880
|
};
|
|
5452
|
-
var STHYPE_ABI =
|
|
6881
|
+
var STHYPE_ABI = parseAbi25([
|
|
5453
6882
|
"function submit(address referral) external payable returns (uint256)",
|
|
5454
6883
|
"function requestWithdrawals(uint256[] amounts, address owner) external returns (uint256[] requestIds)"
|
|
5455
6884
|
]);
|
|
5456
|
-
var ERC20_ABI3 =
|
|
6885
|
+
var ERC20_ABI3 = parseAbi25([
|
|
5457
6886
|
"function totalSupply() external view returns (uint256)"
|
|
5458
6887
|
]);
|
|
5459
6888
|
var StHypeAdapter = class {
|
|
@@ -5473,10 +6902,10 @@ var StHypeAdapter = class {
|
|
|
5473
6902
|
return this.protocolName;
|
|
5474
6903
|
}
|
|
5475
6904
|
async buildStake(params) {
|
|
5476
|
-
const data =
|
|
6905
|
+
const data = encodeFunctionData23({
|
|
5477
6906
|
abi: STHYPE_ABI,
|
|
5478
6907
|
functionName: "submit",
|
|
5479
|
-
args: [
|
|
6908
|
+
args: [zeroAddress12]
|
|
5480
6909
|
});
|
|
5481
6910
|
return {
|
|
5482
6911
|
description: `[${this.protocolName}] Stake ${params.amount} HYPE for stHYPE`,
|
|
@@ -5487,7 +6916,7 @@ var StHypeAdapter = class {
|
|
|
5487
6916
|
};
|
|
5488
6917
|
}
|
|
5489
6918
|
async buildUnstake(params) {
|
|
5490
|
-
const data =
|
|
6919
|
+
const data = encodeFunctionData23({
|
|
5491
6920
|
abi: STHYPE_ABI,
|
|
5492
6921
|
functionName: "requestWithdrawals",
|
|
5493
6922
|
args: [[params.amount], params.recipient]
|
|
@@ -5502,7 +6931,7 @@ var StHypeAdapter = class {
|
|
|
5502
6931
|
}
|
|
5503
6932
|
async getInfo() {
|
|
5504
6933
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5505
|
-
const client =
|
|
6934
|
+
const client = createPublicClient19({ transport: http19(this.rpcUrl) });
|
|
5506
6935
|
const tokenAddr = this.sthypeToken ?? this.staking;
|
|
5507
6936
|
const totalSupply = await client.readContract({
|
|
5508
6937
|
address: tokenAddr,
|
|
@@ -5513,19 +6942,19 @@ var StHypeAdapter = class {
|
|
|
5513
6942
|
});
|
|
5514
6943
|
return {
|
|
5515
6944
|
protocol: this.protocolName,
|
|
5516
|
-
staked_token:
|
|
6945
|
+
staked_token: zeroAddress12,
|
|
5517
6946
|
liquid_token: tokenAddr,
|
|
5518
6947
|
exchange_rate: 1,
|
|
5519
6948
|
total_staked: totalSupply
|
|
5520
6949
|
};
|
|
5521
6950
|
}
|
|
5522
6951
|
};
|
|
5523
|
-
var KINETIQ_ABI =
|
|
6952
|
+
var KINETIQ_ABI = parseAbi26([
|
|
5524
6953
|
"function stake() external payable returns (uint256)",
|
|
5525
6954
|
"function requestUnstake(uint256 amount) external returns (uint256)",
|
|
5526
6955
|
"function totalStaked() external view returns (uint256)"
|
|
5527
6956
|
]);
|
|
5528
|
-
var ORACLE_ABI3 =
|
|
6957
|
+
var ORACLE_ABI3 = parseAbi26([
|
|
5529
6958
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
5530
6959
|
]);
|
|
5531
6960
|
var WHYPE = "0x5555555555555555555555555555555555555555";
|
|
@@ -5547,7 +6976,7 @@ var KinetiqAdapter = class {
|
|
|
5547
6976
|
return this.protocolName;
|
|
5548
6977
|
}
|
|
5549
6978
|
async buildStake(params) {
|
|
5550
|
-
const data =
|
|
6979
|
+
const data = encodeFunctionData24({ abi: KINETIQ_ABI, functionName: "stake" });
|
|
5551
6980
|
return {
|
|
5552
6981
|
description: `[${this.protocolName}] Stake ${params.amount} HYPE for kHYPE`,
|
|
5553
6982
|
to: this.staking,
|
|
@@ -5557,7 +6986,7 @@ var KinetiqAdapter = class {
|
|
|
5557
6986
|
};
|
|
5558
6987
|
}
|
|
5559
6988
|
async buildUnstake(params) {
|
|
5560
|
-
const data =
|
|
6989
|
+
const data = encodeFunctionData24({
|
|
5561
6990
|
abi: KINETIQ_ABI,
|
|
5562
6991
|
functionName: "requestUnstake",
|
|
5563
6992
|
args: [params.amount]
|
|
@@ -5572,7 +7001,7 @@ var KinetiqAdapter = class {
|
|
|
5572
7001
|
}
|
|
5573
7002
|
async getInfo() {
|
|
5574
7003
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5575
|
-
const client =
|
|
7004
|
+
const client = createPublicClient20({ transport: http20(this.rpcUrl) });
|
|
5576
7005
|
const totalStaked = await client.readContract({
|
|
5577
7006
|
address: this.staking,
|
|
5578
7007
|
abi: KINETIQ_ABI,
|
|
@@ -5587,22 +7016,22 @@ var KinetiqAdapter = class {
|
|
|
5587
7016
|
const rateF64 = hypePrice > 0n && khypePrice > 0n ? Number(khypePrice * 10n ** 18n / hypePrice) / 1e18 : 1;
|
|
5588
7017
|
return {
|
|
5589
7018
|
protocol: this.protocolName,
|
|
5590
|
-
staked_token:
|
|
7019
|
+
staked_token: zeroAddress13,
|
|
5591
7020
|
liquid_token: this.liquidToken,
|
|
5592
7021
|
exchange_rate: rateF64,
|
|
5593
7022
|
total_staked: totalStaked
|
|
5594
7023
|
};
|
|
5595
7024
|
}
|
|
5596
7025
|
};
|
|
5597
|
-
var HLP_ABI =
|
|
7026
|
+
var HLP_ABI = parseAbi27([
|
|
5598
7027
|
"function deposit(uint256 amount) external returns (uint256)",
|
|
5599
7028
|
"function withdraw(uint256 shares) external returns (uint256)"
|
|
5600
7029
|
]);
|
|
5601
|
-
var RYSK_ABI =
|
|
7030
|
+
var RYSK_ABI = parseAbi28([
|
|
5602
7031
|
"function openOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 premium)",
|
|
5603
7032
|
"function closeOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 payout)"
|
|
5604
7033
|
]);
|
|
5605
|
-
var ERC721_ABI =
|
|
7034
|
+
var ERC721_ABI = parseAbi29([
|
|
5606
7035
|
"function name() returns (string)",
|
|
5607
7036
|
"function symbol() returns (string)",
|
|
5608
7037
|
"function totalSupply() returns (uint256)",
|
|
@@ -5622,7 +7051,7 @@ var ERC721Adapter = class {
|
|
|
5622
7051
|
}
|
|
5623
7052
|
async getCollectionInfo(collection) {
|
|
5624
7053
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5625
|
-
const client =
|
|
7054
|
+
const client = createPublicClient21({ transport: http21(this.rpcUrl) });
|
|
5626
7055
|
const [collectionName, symbol, totalSupply] = await Promise.all([
|
|
5627
7056
|
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "name" }).catch((e) => {
|
|
5628
7057
|
throw DefiError.rpcError(`[${this.protocolName}] name failed: ${e}`);
|
|
@@ -5641,7 +7070,7 @@ var ERC721Adapter = class {
|
|
|
5641
7070
|
}
|
|
5642
7071
|
async getTokenInfo(collection, tokenId) {
|
|
5643
7072
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5644
|
-
const client =
|
|
7073
|
+
const client = createPublicClient21({ transport: http21(this.rpcUrl) });
|
|
5645
7074
|
const [owner, tokenUri] = await Promise.all([
|
|
5646
7075
|
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "ownerOf", args: [tokenId] }).catch((e) => {
|
|
5647
7076
|
throw DefiError.rpcError(`[${this.protocolName}] ownerOf failed: ${e}`);
|
|
@@ -5657,7 +7086,7 @@ var ERC721Adapter = class {
|
|
|
5657
7086
|
}
|
|
5658
7087
|
async getBalance(owner, collection) {
|
|
5659
7088
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5660
|
-
const client =
|
|
7089
|
+
const client = createPublicClient21({ transport: http21(this.rpcUrl) });
|
|
5661
7090
|
return client.readContract({ address: collection, abi: ERC721_ABI, functionName: "balanceOf", args: [owner] }).catch((e) => {
|
|
5662
7091
|
throw DefiError.rpcError(`[${this.protocolName}] balanceOf failed: ${e}`);
|
|
5663
7092
|
});
|
|
@@ -5678,6 +7107,8 @@ function createDex(entry, rpcUrl) {
|
|
|
5678
7107
|
case "solidly_v2":
|
|
5679
7108
|
case "solidly_cl":
|
|
5680
7109
|
return new SolidlyAdapter(entry, rpcUrl);
|
|
7110
|
+
case "hybra":
|
|
7111
|
+
return new ThenaCLAdapter(entry, rpcUrl);
|
|
5681
7112
|
case "curve_stableswap":
|
|
5682
7113
|
return new CurveStableSwapAdapter(entry);
|
|
5683
7114
|
case "balancer_v3":
|
|
@@ -5738,11 +7169,13 @@ function createLiquidStaking(entry, rpcUrl) {
|
|
|
5738
7169
|
}
|
|
5739
7170
|
}
|
|
5740
7171
|
function createGauge(entry, rpcUrl) {
|
|
7172
|
+
if (entry.interface === "hybra" || entry.contracts?.["gauge_manager"]) {
|
|
7173
|
+
return new HybraGaugeAdapter(entry, rpcUrl);
|
|
7174
|
+
}
|
|
5741
7175
|
switch (entry.interface) {
|
|
5742
7176
|
case "solidly_v2":
|
|
5743
7177
|
case "solidly_cl":
|
|
5744
7178
|
case "algebra_v3":
|
|
5745
|
-
case "hybra":
|
|
5746
7179
|
return new SolidlyGaugeAdapter(entry, rpcUrl);
|
|
5747
7180
|
default:
|
|
5748
7181
|
throw DefiError.unsupported(`Gauge interface '${entry.interface}' not supported`);
|
|
@@ -5781,6 +7214,22 @@ function createOracleFromCdp(entry, _asset, rpcUrl) {
|
|
|
5781
7214
|
function createMerchantMoeLB(entry, rpcUrl) {
|
|
5782
7215
|
return new MerchantMoeLBAdapter(entry, rpcUrl);
|
|
5783
7216
|
}
|
|
7217
|
+
function createKittenSwapFarming(entry, rpcUrl) {
|
|
7218
|
+
const farmingCenter = entry.contracts?.["farming_center"];
|
|
7219
|
+
if (!farmingCenter) {
|
|
7220
|
+
throw new DefiError("CONTRACT_ERROR", `[${entry.name}] Missing 'farming_center' contract address`);
|
|
7221
|
+
}
|
|
7222
|
+
const eternalFarming = entry.contracts?.["eternal_farming"];
|
|
7223
|
+
if (!eternalFarming) {
|
|
7224
|
+
throw new DefiError("CONTRACT_ERROR", `[${entry.name}] Missing 'eternal_farming' contract address`);
|
|
7225
|
+
}
|
|
7226
|
+
const positionManager = entry.contracts?.["position_manager"];
|
|
7227
|
+
if (!positionManager) {
|
|
7228
|
+
throw new DefiError("CONTRACT_ERROR", `[${entry.name}] Missing 'position_manager' contract address`);
|
|
7229
|
+
}
|
|
7230
|
+
const factory = entry.contracts?.["factory"];
|
|
7231
|
+
return new KittenSwapFarmingAdapter(entry.name, farmingCenter, eternalFarming, positionManager, rpcUrl, factory);
|
|
7232
|
+
}
|
|
5784
7233
|
var DexSpotPrice = class {
|
|
5785
7234
|
/**
|
|
5786
7235
|
* Get the spot price for `token` denominated in `quoteToken` (e.g. USDC).
|
|
@@ -5853,7 +7302,7 @@ function registerDex(parent, getOpts, makeExecutor2) {
|
|
|
5853
7302
|
const result = await executor.execute(tx);
|
|
5854
7303
|
printOutput(result, getOpts());
|
|
5855
7304
|
});
|
|
5856
|
-
dex.command("lp-add").description("Add liquidity to a pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--token-a <token>", "First token symbol or address").requiredOption("--token-b <token>", "Second token symbol or address").requiredOption("--amount-a <amount>", "Amount of token A in wei").requiredOption("--amount-b <amount>", "Amount of token B in wei").option("--recipient <address>", "Recipient address").action(async (opts) => {
|
|
7305
|
+
dex.command("lp-add").description("Add liquidity to a pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--token-a <token>", "First token symbol or address").requiredOption("--token-b <token>", "Second token symbol or address").requiredOption("--amount-a <amount>", "Amount of token A in wei").requiredOption("--amount-b <amount>", "Amount of token B in wei").option("--recipient <address>", "Recipient address").option("--tick-lower <tick>", "Lower tick for concentrated LP (default: full range)").option("--tick-upper <tick>", "Upper tick for concentrated LP (default: full range)").option("--range <percent>", "\xB1N% concentrated range around current price (e.g. --range 2 for \xB12%)").option("--pool <name_or_address>", "Pool name (e.g. WHYPE/USDC) or address").action(async (opts) => {
|
|
5857
7306
|
const executor = makeExecutor2();
|
|
5858
7307
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
5859
7308
|
const registry = Registry.loadEmbedded();
|
|
@@ -5863,13 +7312,26 @@ function registerDex(parent, getOpts, makeExecutor2) {
|
|
|
5863
7312
|
const tokenA = opts.tokenA.startsWith("0x") ? opts.tokenA : registry.resolveToken(chainName, opts.tokenA).address;
|
|
5864
7313
|
const tokenB = opts.tokenB.startsWith("0x") ? opts.tokenB : registry.resolveToken(chainName, opts.tokenB).address;
|
|
5865
7314
|
const recipient = opts.recipient ?? process.env.DEFI_WALLET_ADDRESS ?? "0x0000000000000000000000000000000000000001";
|
|
7315
|
+
let poolAddr;
|
|
7316
|
+
if (opts.pool) {
|
|
7317
|
+
if (opts.pool.startsWith("0x")) {
|
|
7318
|
+
poolAddr = opts.pool;
|
|
7319
|
+
} else {
|
|
7320
|
+
const poolInfo = registry.resolvePool(opts.protocol, opts.pool);
|
|
7321
|
+
poolAddr = poolInfo.address;
|
|
7322
|
+
}
|
|
7323
|
+
}
|
|
5866
7324
|
const tx = await adapter.buildAddLiquidity({
|
|
5867
7325
|
protocol: protocol.name,
|
|
5868
7326
|
token_a: tokenA,
|
|
5869
7327
|
token_b: tokenB,
|
|
5870
7328
|
amount_a: BigInt(opts.amountA),
|
|
5871
7329
|
amount_b: BigInt(opts.amountB),
|
|
5872
|
-
recipient
|
|
7330
|
+
recipient,
|
|
7331
|
+
tick_lower: opts.tickLower !== void 0 ? parseInt(opts.tickLower) : void 0,
|
|
7332
|
+
tick_upper: opts.tickUpper !== void 0 ? parseInt(opts.tickUpper) : void 0,
|
|
7333
|
+
range_pct: opts.range !== void 0 ? parseFloat(opts.range) : void 0,
|
|
7334
|
+
pool: poolAddr
|
|
5873
7335
|
});
|
|
5874
7336
|
const result = await executor.execute(tx);
|
|
5875
7337
|
printOutput(result, getOpts());
|
|
@@ -5918,57 +7380,96 @@ function registerDex(parent, getOpts, makeExecutor2) {
|
|
|
5918
7380
|
|
|
5919
7381
|
// src/commands/gauge.ts
|
|
5920
7382
|
import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
7383
|
+
function resolveAccount() {
|
|
7384
|
+
const walletAddr = process.env["DEFI_WALLET_ADDRESS"];
|
|
7385
|
+
if (walletAddr) return walletAddr;
|
|
7386
|
+
const privateKey = process.env["DEFI_PRIVATE_KEY"];
|
|
7387
|
+
if (privateKey) return privateKeyToAccount2(privateKey).address;
|
|
7388
|
+
return void 0;
|
|
7389
|
+
}
|
|
5921
7390
|
function registerGauge(parent, getOpts, makeExecutor2) {
|
|
5922
|
-
const gauge = parent.command("gauge").description("Gauge operations: deposit, withdraw, claim,
|
|
5923
|
-
gauge.command("
|
|
5924
|
-
const
|
|
7391
|
+
const gauge = parent.command("gauge").description("Gauge operations: find, deposit, withdraw, claim, earned");
|
|
7392
|
+
gauge.command("discover").description("Find all pools with emission gauges (scans V2 + CL factories)").requiredOption("--protocol <protocol>", "Protocol slug").action(async (opts) => {
|
|
7393
|
+
const chainName = parent.opts().chain ?? "hyperevm";
|
|
5925
7394
|
const registry = Registry.loadEmbedded();
|
|
7395
|
+
const chain = registry.getChain(chainName);
|
|
5926
7396
|
const protocol = registry.getProtocol(opts.protocol);
|
|
5927
|
-
const adapter = createGauge(protocol);
|
|
5928
|
-
|
|
5929
|
-
const
|
|
5930
|
-
|
|
5931
|
-
printOutput(result, getOpts());
|
|
7397
|
+
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7398
|
+
if (!adapter.discoverGaugedPools) throw new Error(`${protocol.name} does not support gauge discovery`);
|
|
7399
|
+
const pools = await adapter.discoverGaugedPools();
|
|
7400
|
+
printOutput(pools, getOpts());
|
|
5932
7401
|
});
|
|
5933
|
-
gauge.command("
|
|
5934
|
-
const
|
|
7402
|
+
gauge.command("find").description("Find gauge address for a pool via voter contract").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "Pool address").action(async (opts) => {
|
|
7403
|
+
const chainName = parent.opts().chain ?? "hyperevm";
|
|
5935
7404
|
const registry = Registry.loadEmbedded();
|
|
7405
|
+
const chain = registry.getChain(chainName);
|
|
5936
7406
|
const protocol = registry.getProtocol(opts.protocol);
|
|
5937
|
-
const adapter = createGauge(protocol);
|
|
5938
|
-
|
|
5939
|
-
const
|
|
5940
|
-
printOutput(
|
|
7407
|
+
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7408
|
+
if (!adapter.resolveGauge) throw new Error(`${protocol.name} does not support gauge lookup`);
|
|
7409
|
+
const gaugeAddr = await adapter.resolveGauge(opts.pool);
|
|
7410
|
+
printOutput({ pool: opts.pool, gauge: gaugeAddr, protocol: protocol.name }, getOpts());
|
|
7411
|
+
});
|
|
7412
|
+
gauge.command("earned").description("Check pending rewards for a gauge").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--gauge <address>", "Gauge contract address").option("--token-id <id>", "NFT tokenId (for CL gauges like Hybra)").action(async (opts) => {
|
|
7413
|
+
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7414
|
+
const registry = Registry.loadEmbedded();
|
|
7415
|
+
const chain = registry.getChain(chainName);
|
|
7416
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
7417
|
+
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7418
|
+
if (opts.tokenId) {
|
|
7419
|
+
if (!adapter.getPendingRewardsByTokenId) throw new Error(`${protocol.name} does not support NFT rewards`);
|
|
7420
|
+
const earned = await adapter.getPendingRewardsByTokenId(opts.gauge, BigInt(opts.tokenId));
|
|
7421
|
+
printOutput({ gauge: opts.gauge, token_id: opts.tokenId, earned: earned.toString() }, getOpts());
|
|
7422
|
+
} else {
|
|
7423
|
+
const account = resolveAccount();
|
|
7424
|
+
if (!account) throw new Error("DEFI_WALLET_ADDRESS or DEFI_PRIVATE_KEY required");
|
|
7425
|
+
const rewards = await adapter.getPendingRewards(opts.gauge, account);
|
|
7426
|
+
printOutput(rewards.map((r) => ({ token: r.token, amount: r.amount.toString() })), getOpts());
|
|
7427
|
+
}
|
|
5941
7428
|
});
|
|
5942
|
-
gauge.command("
|
|
7429
|
+
gauge.command("deposit").description("Deposit LP tokens or NFT into a gauge").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--gauge <address>", "Gauge contract address").option("--amount <amount>", "LP token amount in wei (for V2 gauges)").option("--token-id <id>", "NFT tokenId (for CL gauges like Hybra)").action(async (opts) => {
|
|
5943
7430
|
const executor = makeExecutor2();
|
|
7431
|
+
const chainName = parent.opts().chain ?? "hyperevm";
|
|
5944
7432
|
const registry = Registry.loadEmbedded();
|
|
7433
|
+
const chain = registry.getChain(chainName);
|
|
5945
7434
|
const protocol = registry.getProtocol(opts.protocol);
|
|
5946
|
-
const adapter = createGauge(protocol,
|
|
5947
|
-
const
|
|
5948
|
-
const
|
|
5949
|
-
const tx = await adapter.
|
|
7435
|
+
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7436
|
+
const amount = opts.amount ? BigInt(opts.amount) : 0n;
|
|
7437
|
+
const tokenId = opts.tokenId ? BigInt(opts.tokenId) : void 0;
|
|
7438
|
+
const tx = await adapter.buildDeposit(opts.gauge, amount, tokenId);
|
|
5950
7439
|
const result = await executor.execute(tx);
|
|
5951
7440
|
printOutput(result, getOpts());
|
|
5952
7441
|
});
|
|
5953
|
-
gauge.command("
|
|
7442
|
+
gauge.command("withdraw").description("Withdraw LP tokens or NFT from a gauge").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--gauge <address>", "Gauge contract address").option("--amount <amount>", "LP token amount in wei (for V2 gauges)").option("--token-id <id>", "NFT tokenId (for CL gauges like Hybra)").action(async (opts) => {
|
|
5954
7443
|
const executor = makeExecutor2();
|
|
7444
|
+
const chainName = parent.opts().chain ?? "hyperevm";
|
|
5955
7445
|
const registry = Registry.loadEmbedded();
|
|
7446
|
+
const chain = registry.getChain(chainName);
|
|
5956
7447
|
const protocol = registry.getProtocol(opts.protocol);
|
|
5957
|
-
const adapter = createGauge(protocol);
|
|
5958
|
-
const
|
|
7448
|
+
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7449
|
+
const amount = opts.amount ? BigInt(opts.amount) : 0n;
|
|
7450
|
+
const tokenId = opts.tokenId ? BigInt(opts.tokenId) : void 0;
|
|
7451
|
+
const tx = await adapter.buildWithdraw(opts.gauge, amount, tokenId);
|
|
5959
7452
|
const result = await executor.execute(tx);
|
|
5960
7453
|
printOutput(result, getOpts());
|
|
5961
7454
|
});
|
|
5962
|
-
gauge.command("
|
|
7455
|
+
gauge.command("claim").description("Claim earned rewards from a gauge").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--gauge <address>", "Gauge contract address").option("--token-id <id>", "NFT tokenId (for CL gauges like Hybra)").action(async (opts) => {
|
|
5963
7456
|
const executor = makeExecutor2();
|
|
7457
|
+
const chainName = parent.opts().chain ?? "hyperevm";
|
|
5964
7458
|
const registry = Registry.loadEmbedded();
|
|
7459
|
+
const chain = registry.getChain(chainName);
|
|
5965
7460
|
const protocol = registry.getProtocol(opts.protocol);
|
|
5966
|
-
const adapter = createGauge(protocol);
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
7461
|
+
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7462
|
+
if (opts.tokenId) {
|
|
7463
|
+
if (!adapter.buildClaimRewardsByTokenId) throw new Error(`${protocol.name} does not support NFT claim`);
|
|
7464
|
+
const tx = await adapter.buildClaimRewardsByTokenId(opts.gauge, BigInt(opts.tokenId));
|
|
7465
|
+
const result = await executor.execute(tx);
|
|
7466
|
+
printOutput(result, getOpts());
|
|
7467
|
+
} else {
|
|
7468
|
+
const account = resolveAccount();
|
|
7469
|
+
const tx = await adapter.buildClaimRewards(opts.gauge, account);
|
|
7470
|
+
const result = await executor.execute(tx);
|
|
7471
|
+
printOutput(result, getOpts());
|
|
7472
|
+
}
|
|
5972
7473
|
});
|
|
5973
7474
|
}
|
|
5974
7475
|
|
|
@@ -6215,9 +7716,7 @@ function resolveAsset(registry, chain, asset) {
|
|
|
6215
7716
|
return registry.resolveToken(chain, asset).address;
|
|
6216
7717
|
}
|
|
6217
7718
|
async function collectLendingRates(registry, chainName, rpc, assetAddr) {
|
|
6218
|
-
const protos = registry.getProtocolsForChain(chainName).filter(
|
|
6219
|
-
(p) => p.category === ProtocolCategory.Lending && (p.interface === "aave_v3" || p.interface === "aave_v3_isolated")
|
|
6220
|
-
);
|
|
7719
|
+
const protos = registry.getProtocolsForChain(chainName).filter((p) => p.category === ProtocolCategory.Lending);
|
|
6221
7720
|
const results = [];
|
|
6222
7721
|
let first = true;
|
|
6223
7722
|
for (const proto of protos) {
|
|
@@ -6305,7 +7804,7 @@ async function runYieldScan(registry, asset, output) {
|
|
|
6305
7804
|
} catch {
|
|
6306
7805
|
return [];
|
|
6307
7806
|
}
|
|
6308
|
-
const protos = registry.getProtocolsForChain(chainName).filter((p) => p.category === ProtocolCategory.Lending
|
|
7807
|
+
const protos = registry.getProtocolsForChain(chainName).filter((p) => p.category === ProtocolCategory.Lending);
|
|
6309
7808
|
if (protos.length === 0) return [];
|
|
6310
7809
|
const rpc = chain.effectiveRpcUrl();
|
|
6311
7810
|
const rates = [];
|
|
@@ -6388,7 +7887,7 @@ async function scanRatesForExecute(registry, asset) {
|
|
|
6388
7887
|
} catch {
|
|
6389
7888
|
return [];
|
|
6390
7889
|
}
|
|
6391
|
-
const protos = registry.getProtocolsForChain(chainName).filter((p) => p.category === ProtocolCategory.Lending
|
|
7890
|
+
const protos = registry.getProtocolsForChain(chainName).filter((p) => p.category === ProtocolCategory.Lending);
|
|
6392
7891
|
if (protos.length === 0) return [];
|
|
6393
7892
|
const rpc = chain.effectiveRpcUrl();
|
|
6394
7893
|
const rates = [];
|
|
@@ -6420,7 +7919,26 @@ async function scanRatesForExecute(registry, asset) {
|
|
|
6420
7919
|
}
|
|
6421
7920
|
function registerYield(parent, getOpts, makeExecutor2) {
|
|
6422
7921
|
const yieldCmd = parent.command("yield").description("Yield operations: compare, scan, optimize, execute");
|
|
6423
|
-
yieldCmd.
|
|
7922
|
+
yieldCmd.option("--asset <token>", "Token symbol or address", "USDC").action(async (opts) => {
|
|
7923
|
+
try {
|
|
7924
|
+
const registry = Registry.loadEmbedded();
|
|
7925
|
+
const chainName = (parent.opts().chain ?? "hyperevm").toLowerCase();
|
|
7926
|
+
const chain = registry.getChain(chainName);
|
|
7927
|
+
const rpc = chain.effectiveRpcUrl();
|
|
7928
|
+
const assetAddr = resolveAsset(registry, chainName, opts.asset);
|
|
7929
|
+
const results = await collectLendingRates(registry, chainName, rpc, assetAddr);
|
|
7930
|
+
results.sort((a, b) => b.supply_apy - a.supply_apy);
|
|
7931
|
+
const bestSupply = results[0]?.protocol ?? null;
|
|
7932
|
+
const bestBorrow = results.reduce((best, r) => {
|
|
7933
|
+
if (!best || r.borrow_variable_apy < best.borrow_variable_apy) return r;
|
|
7934
|
+
return best;
|
|
7935
|
+
}, null)?.protocol ?? null;
|
|
7936
|
+
printOutput({ asset: opts.asset, chain: chainName, rates: results, best_supply: bestSupply, best_borrow: bestBorrow }, getOpts());
|
|
7937
|
+
} catch (err) {
|
|
7938
|
+
printOutput({ error: String(err) }, getOpts());
|
|
7939
|
+
}
|
|
7940
|
+
});
|
|
7941
|
+
yieldCmd.command("compare").description("Compare lending rates across protocols for an asset").option("--asset <token>", "Token symbol or address", "USDC").action(async (opts) => {
|
|
6424
7942
|
try {
|
|
6425
7943
|
const registry = Registry.loadEmbedded();
|
|
6426
7944
|
const chainName = (parent.opts().chain ?? "hyperevm").toLowerCase();
|
|
@@ -6596,7 +8114,7 @@ function registerYield(parent, getOpts, makeExecutor2) {
|
|
|
6596
8114
|
return;
|
|
6597
8115
|
}
|
|
6598
8116
|
} else {
|
|
6599
|
-
const candidates = registry.getProtocolsForChain(chainName).filter((p) => p.category === ProtocolCategory.Lending
|
|
8117
|
+
const candidates = registry.getProtocolsForChain(chainName).filter((p) => p.category === ProtocolCategory.Lending);
|
|
6600
8118
|
if (candidates.length === 0) {
|
|
6601
8119
|
printOutput({ error: `No aave_v3 lending protocol found on ${chainName}` }, getOpts());
|
|
6602
8120
|
process.exit(1);
|
|
@@ -6788,20 +8306,20 @@ function registerYield(parent, getOpts, makeExecutor2) {
|
|
|
6788
8306
|
}
|
|
6789
8307
|
|
|
6790
8308
|
// src/commands/portfolio.ts
|
|
6791
|
-
import { encodeFunctionData as
|
|
8309
|
+
import { encodeFunctionData as encodeFunctionData28, parseAbi as parseAbi31 } from "viem";
|
|
6792
8310
|
|
|
6793
8311
|
// src/portfolio-tracker.ts
|
|
6794
8312
|
import { mkdirSync, writeFileSync, readdirSync as readdirSync2, readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
6795
8313
|
import { homedir } from "os";
|
|
6796
8314
|
import { resolve as resolve2 } from "path";
|
|
6797
|
-
import { encodeFunctionData as
|
|
6798
|
-
var ERC20_ABI4 =
|
|
8315
|
+
import { encodeFunctionData as encodeFunctionData27, parseAbi as parseAbi30 } from "viem";
|
|
8316
|
+
var ERC20_ABI4 = parseAbi30([
|
|
6799
8317
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
6800
8318
|
]);
|
|
6801
|
-
var ORACLE_ABI4 =
|
|
8319
|
+
var ORACLE_ABI4 = parseAbi30([
|
|
6802
8320
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
6803
8321
|
]);
|
|
6804
|
-
var POOL_ABI3 =
|
|
8322
|
+
var POOL_ABI3 = parseAbi30([
|
|
6805
8323
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
6806
8324
|
]);
|
|
6807
8325
|
function decodeU256Word(data, wordOffset = 0) {
|
|
@@ -6830,7 +8348,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
6830
8348
|
tokenEntries.push({ symbol: t.symbol, address: entry.address, decimals: entry.decimals });
|
|
6831
8349
|
calls.push([
|
|
6832
8350
|
entry.address,
|
|
6833
|
-
|
|
8351
|
+
encodeFunctionData27({ abi: ERC20_ABI4, functionName: "balanceOf", args: [user] })
|
|
6834
8352
|
]);
|
|
6835
8353
|
callLabels.push(`balance:${t.symbol}`);
|
|
6836
8354
|
}
|
|
@@ -6838,7 +8356,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
6838
8356
|
for (const p of lendingProtocols) {
|
|
6839
8357
|
calls.push([
|
|
6840
8358
|
p.contracts["pool"],
|
|
6841
|
-
|
|
8359
|
+
encodeFunctionData27({ abi: POOL_ABI3, functionName: "getUserAccountData", args: [user] })
|
|
6842
8360
|
]);
|
|
6843
8361
|
callLabels.push(`lending:${p.name}`);
|
|
6844
8362
|
}
|
|
@@ -6848,7 +8366,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
6848
8366
|
if (oracleAddr) {
|
|
6849
8367
|
calls.push([
|
|
6850
8368
|
oracleAddr,
|
|
6851
|
-
|
|
8369
|
+
encodeFunctionData27({ abi: ORACLE_ABI4, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
6852
8370
|
]);
|
|
6853
8371
|
callLabels.push("price:native");
|
|
6854
8372
|
}
|
|
@@ -6986,13 +8504,13 @@ function calculatePnL(current, previous) {
|
|
|
6986
8504
|
}
|
|
6987
8505
|
|
|
6988
8506
|
// src/commands/portfolio.ts
|
|
6989
|
-
var ERC20_ABI5 =
|
|
8507
|
+
var ERC20_ABI5 = parseAbi31([
|
|
6990
8508
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
6991
8509
|
]);
|
|
6992
|
-
var POOL_ABI4 =
|
|
8510
|
+
var POOL_ABI4 = parseAbi31([
|
|
6993
8511
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
6994
8512
|
]);
|
|
6995
|
-
var ORACLE_ABI5 =
|
|
8513
|
+
var ORACLE_ABI5 = parseAbi31([
|
|
6996
8514
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
6997
8515
|
]);
|
|
6998
8516
|
function decodeU2562(data, wordOffset = 0) {
|
|
@@ -7032,7 +8550,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
7032
8550
|
if (entry.address === "0x0000000000000000000000000000000000000000") continue;
|
|
7033
8551
|
calls.push([
|
|
7034
8552
|
entry.address,
|
|
7035
|
-
|
|
8553
|
+
encodeFunctionData28({ abi: ERC20_ABI5, functionName: "balanceOf", args: [user] })
|
|
7036
8554
|
]);
|
|
7037
8555
|
callLabels.push(`balance:${symbol}`);
|
|
7038
8556
|
}
|
|
@@ -7040,7 +8558,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
7040
8558
|
for (const p of lendingProtocols) {
|
|
7041
8559
|
calls.push([
|
|
7042
8560
|
p.contracts["pool"],
|
|
7043
|
-
|
|
8561
|
+
encodeFunctionData28({ abi: POOL_ABI4, functionName: "getUserAccountData", args: [user] })
|
|
7044
8562
|
]);
|
|
7045
8563
|
callLabels.push(`lending:${p.name}`);
|
|
7046
8564
|
}
|
|
@@ -7050,7 +8568,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
7050
8568
|
if (oracleAddr) {
|
|
7051
8569
|
calls.push([
|
|
7052
8570
|
oracleAddr,
|
|
7053
|
-
|
|
8571
|
+
encodeFunctionData28({ abi: ORACLE_ABI5, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
7054
8572
|
]);
|
|
7055
8573
|
callLabels.push("price:native");
|
|
7056
8574
|
}
|
|
@@ -7412,14 +8930,14 @@ function registerAlert(parent, getOpts) {
|
|
|
7412
8930
|
}
|
|
7413
8931
|
|
|
7414
8932
|
// src/commands/scan.ts
|
|
7415
|
-
import { encodeFunctionData as
|
|
7416
|
-
var AAVE_ORACLE_ABI =
|
|
8933
|
+
import { encodeFunctionData as encodeFunctionData29, parseAbi as parseAbi33 } from "viem";
|
|
8934
|
+
var AAVE_ORACLE_ABI = parseAbi33([
|
|
7417
8935
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
7418
8936
|
]);
|
|
7419
|
-
var UNIV2_ROUTER_ABI =
|
|
8937
|
+
var UNIV2_ROUTER_ABI = parseAbi33([
|
|
7420
8938
|
"function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory)"
|
|
7421
8939
|
]);
|
|
7422
|
-
var VTOKEN_ABI =
|
|
8940
|
+
var VTOKEN_ABI = parseAbi33([
|
|
7423
8941
|
"function exchangeRateStored() external view returns (uint256)"
|
|
7424
8942
|
]);
|
|
7425
8943
|
var STABLECOINS = /* @__PURE__ */ new Set(["USDC", "USDT", "DAI", "USDT0"]);
|
|
@@ -7529,7 +9047,7 @@ function registerScan(parent, getOpts) {
|
|
|
7529
9047
|
callTypes.push({ kind: "oracle", oracle: oracle.name, token: token.symbol, oracleDecimals: oracle.decimals });
|
|
7530
9048
|
calls.push([
|
|
7531
9049
|
oracle.addr,
|
|
7532
|
-
|
|
9050
|
+
encodeFunctionData29({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })
|
|
7533
9051
|
]);
|
|
7534
9052
|
}
|
|
7535
9053
|
}
|
|
@@ -7540,7 +9058,7 @@ function registerScan(parent, getOpts) {
|
|
|
7540
9058
|
callTypes.push({ kind: "dex", token: token.symbol, outDecimals: quoteStable.decimals });
|
|
7541
9059
|
calls.push([
|
|
7542
9060
|
dexRouter,
|
|
7543
|
-
|
|
9061
|
+
encodeFunctionData29({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [amountIn, path] })
|
|
7544
9062
|
]);
|
|
7545
9063
|
}
|
|
7546
9064
|
}
|
|
@@ -7549,7 +9067,7 @@ function registerScan(parent, getOpts) {
|
|
|
7549
9067
|
callTypes.push({ kind: "stable", from: "USDC", to: "USDT", outDecimals: usdt.decimals });
|
|
7550
9068
|
calls.push([
|
|
7551
9069
|
dexRouter,
|
|
7552
|
-
|
|
9070
|
+
encodeFunctionData29({
|
|
7553
9071
|
abi: UNIV2_ROUTER_ABI,
|
|
7554
9072
|
functionName: "getAmountsOut",
|
|
7555
9073
|
args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]]
|
|
@@ -7558,7 +9076,7 @@ function registerScan(parent, getOpts) {
|
|
|
7558
9076
|
callTypes.push({ kind: "stable", from: "USDT", to: "USDC", outDecimals: usdc.decimals });
|
|
7559
9077
|
calls.push([
|
|
7560
9078
|
dexRouter,
|
|
7561
|
-
|
|
9079
|
+
encodeFunctionData29({
|
|
7562
9080
|
abi: UNIV2_ROUTER_ABI,
|
|
7563
9081
|
functionName: "getAmountsOut",
|
|
7564
9082
|
args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]]
|
|
@@ -7569,7 +9087,7 @@ function registerScan(parent, getOpts) {
|
|
|
7569
9087
|
for (const fork of compoundForks) {
|
|
7570
9088
|
for (const { key, addr } of fork.vtokens) {
|
|
7571
9089
|
callTypes.push({ kind: "exchangeRate", protocol: fork.name, vtoken: key });
|
|
7572
|
-
calls.push([addr,
|
|
9090
|
+
calls.push([addr, encodeFunctionData29({ abi: VTOKEN_ABI, functionName: "exchangeRateStored", args: [] })]);
|
|
7573
9091
|
}
|
|
7574
9092
|
}
|
|
7575
9093
|
}
|
|
@@ -7787,22 +9305,22 @@ async function runAllChains(registry, patterns, oracleThreshold, stableThreshold
|
|
|
7787
9305
|
for (const oracle of oracles) {
|
|
7788
9306
|
for (const token of scanTokens) {
|
|
7789
9307
|
cts.push({ kind: "oracle", oracle: oracle.name, token: token.symbol, dec: oracle.decimals });
|
|
7790
|
-
calls.push([oracle.addr,
|
|
9308
|
+
calls.push([oracle.addr, encodeFunctionData29({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })]);
|
|
7791
9309
|
}
|
|
7792
9310
|
}
|
|
7793
9311
|
if (dexRouter) {
|
|
7794
9312
|
for (const token of scanTokens) {
|
|
7795
9313
|
const path = wrappedNative && token.address.toLowerCase() === wrappedNative.toLowerCase() ? [token.address, quoteStable.address] : wrappedNative ? [token.address, wrappedNative, quoteStable.address] : [token.address, quoteStable.address];
|
|
7796
9314
|
cts.push({ kind: "dex", token: token.symbol, dec: quoteStable.decimals });
|
|
7797
|
-
calls.push([dexRouter,
|
|
9315
|
+
calls.push([dexRouter, encodeFunctionData29({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(token.decimals), path] })]);
|
|
7798
9316
|
}
|
|
7799
9317
|
}
|
|
7800
9318
|
}
|
|
7801
9319
|
if (doStable && usdc && usdt && dexRouter) {
|
|
7802
9320
|
cts.push({ kind: "stable", from: "USDC", to: "USDT", dec: usdt.decimals });
|
|
7803
|
-
calls.push([dexRouter,
|
|
9321
|
+
calls.push([dexRouter, encodeFunctionData29({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]] })]);
|
|
7804
9322
|
cts.push({ kind: "stable", from: "USDT", to: "USDC", dec: usdc.decimals });
|
|
7805
|
-
calls.push([dexRouter,
|
|
9323
|
+
calls.push([dexRouter, encodeFunctionData29({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]] })]);
|
|
7806
9324
|
}
|
|
7807
9325
|
if (calls.length === 0) return null;
|
|
7808
9326
|
const ct0 = Date.now();
|
|
@@ -7930,14 +9448,14 @@ function registerArb(parent, getOpts, makeExecutor2) {
|
|
|
7930
9448
|
}
|
|
7931
9449
|
|
|
7932
9450
|
// src/commands/positions.ts
|
|
7933
|
-
import { encodeFunctionData as
|
|
7934
|
-
var ERC20_ABI6 =
|
|
9451
|
+
import { encodeFunctionData as encodeFunctionData30, parseAbi as parseAbi34 } from "viem";
|
|
9452
|
+
var ERC20_ABI6 = parseAbi34([
|
|
7935
9453
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
7936
9454
|
]);
|
|
7937
|
-
var POOL_ABI5 =
|
|
9455
|
+
var POOL_ABI5 = parseAbi34([
|
|
7938
9456
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
7939
9457
|
]);
|
|
7940
|
-
var ORACLE_ABI6 =
|
|
9458
|
+
var ORACLE_ABI6 = parseAbi34([
|
|
7941
9459
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
7942
9460
|
]);
|
|
7943
9461
|
function round22(x) {
|
|
@@ -7966,7 +9484,7 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7966
9484
|
callTypes.push({ kind: "token", symbol: token.symbol, decimals: token.decimals });
|
|
7967
9485
|
calls.push([
|
|
7968
9486
|
token.address,
|
|
7969
|
-
|
|
9487
|
+
encodeFunctionData30({ abi: ERC20_ABI6, functionName: "balanceOf", args: [user] })
|
|
7970
9488
|
]);
|
|
7971
9489
|
}
|
|
7972
9490
|
}
|
|
@@ -7974,14 +9492,14 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7974
9492
|
callTypes.push({ kind: "lending", protocol: name, iface });
|
|
7975
9493
|
calls.push([
|
|
7976
9494
|
pool,
|
|
7977
|
-
|
|
9495
|
+
encodeFunctionData30({ abi: POOL_ABI5, functionName: "getUserAccountData", args: [user] })
|
|
7978
9496
|
]);
|
|
7979
9497
|
}
|
|
7980
9498
|
if (oracleAddr) {
|
|
7981
9499
|
callTypes.push({ kind: "native_price" });
|
|
7982
9500
|
calls.push([
|
|
7983
9501
|
oracleAddr,
|
|
7984
|
-
|
|
9502
|
+
encodeFunctionData30({ abi: ORACLE_ABI6, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
7985
9503
|
]);
|
|
7986
9504
|
}
|
|
7987
9505
|
if (calls.length === 0) return null;
|
|
@@ -8274,14 +9792,14 @@ function registerPrice(parent, getOpts) {
|
|
|
8274
9792
|
}
|
|
8275
9793
|
|
|
8276
9794
|
// src/commands/wallet.ts
|
|
8277
|
-
import { createPublicClient as
|
|
9795
|
+
import { createPublicClient as createPublicClient23, http as http23, formatEther } from "viem";
|
|
8278
9796
|
function registerWallet(parent, getOpts) {
|
|
8279
9797
|
const wallet = parent.command("wallet").description("Wallet management");
|
|
8280
9798
|
wallet.command("balance").description("Show native token balance").requiredOption("--address <address>", "Wallet address to query").action(async (opts) => {
|
|
8281
9799
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
8282
9800
|
const registry = Registry.loadEmbedded();
|
|
8283
9801
|
const chain = registry.getChain(chainName);
|
|
8284
|
-
const client =
|
|
9802
|
+
const client = createPublicClient23({ transport: http23(chain.effectiveRpcUrl()) });
|
|
8285
9803
|
const balance = await client.getBalance({ address: opts.address });
|
|
8286
9804
|
printOutput({
|
|
8287
9805
|
chain: chain.name,
|
|
@@ -8298,14 +9816,14 @@ function registerWallet(parent, getOpts) {
|
|
|
8298
9816
|
}
|
|
8299
9817
|
|
|
8300
9818
|
// src/commands/token.ts
|
|
8301
|
-
import { createPublicClient as
|
|
9819
|
+
import { createPublicClient as createPublicClient24, http as http24, maxUint256 } from "viem";
|
|
8302
9820
|
function registerToken(parent, getOpts, makeExecutor2) {
|
|
8303
9821
|
const token = parent.command("token").description("Token operations: approve, allowance, transfer, balance");
|
|
8304
9822
|
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) => {
|
|
8305
9823
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
8306
9824
|
const registry = Registry.loadEmbedded();
|
|
8307
9825
|
const chain = registry.getChain(chainName);
|
|
8308
|
-
const client =
|
|
9826
|
+
const client = createPublicClient24({ transport: http24(chain.effectiveRpcUrl()) });
|
|
8309
9827
|
const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
|
|
8310
9828
|
const [balance, symbol, decimals] = await Promise.all([
|
|
8311
9829
|
client.readContract({ address: tokenAddr, abi: erc20Abi, functionName: "balanceOf", args: [opts.owner] }),
|
|
@@ -8334,7 +9852,7 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
8334
9852
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
8335
9853
|
const registry = Registry.loadEmbedded();
|
|
8336
9854
|
const chain = registry.getChain(chainName);
|
|
8337
|
-
const client =
|
|
9855
|
+
const client = createPublicClient24({ transport: http24(chain.effectiveRpcUrl()) });
|
|
8338
9856
|
const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
|
|
8339
9857
|
const allowance = await client.readContract({
|
|
8340
9858
|
address: tokenAddr,
|
|
@@ -8356,8 +9874,8 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
8356
9874
|
}
|
|
8357
9875
|
|
|
8358
9876
|
// src/commands/whales.ts
|
|
8359
|
-
import { encodeFunctionData as
|
|
8360
|
-
var POOL_ABI6 =
|
|
9877
|
+
import { encodeFunctionData as encodeFunctionData31, parseAbi as parseAbi35 } from "viem";
|
|
9878
|
+
var POOL_ABI6 = parseAbi35([
|
|
8361
9879
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
8362
9880
|
]);
|
|
8363
9881
|
function round24(x) {
|
|
@@ -8468,7 +9986,7 @@ function registerWhales(parent, getOpts) {
|
|
|
8468
9986
|
for (const { pool } of lendingPools) {
|
|
8469
9987
|
calls.push([
|
|
8470
9988
|
pool,
|
|
8471
|
-
|
|
9989
|
+
encodeFunctionData31({ abi: POOL_ABI6, functionName: "getUserAccountData", args: [whale.address] })
|
|
8472
9990
|
]);
|
|
8473
9991
|
}
|
|
8474
9992
|
}
|
|
@@ -8896,11 +10414,11 @@ function registerBridge(parent, getOpts) {
|
|
|
8896
10414
|
const amountUsdc = Number(BigInt(opts.amount)) / 1e6;
|
|
8897
10415
|
const { fee, maxFeeSubunits } = await getCctpFeeEstimate(srcDomain, dstDomain, amountUsdc);
|
|
8898
10416
|
const recipientPadded = `0x${"0".repeat(24)}${recipient.replace("0x", "").toLowerCase()}`;
|
|
8899
|
-
const { encodeFunctionData:
|
|
8900
|
-
const tokenMessengerAbi =
|
|
10417
|
+
const { encodeFunctionData: encodeFunctionData34, parseAbi: parseAbi37 } = await import("viem");
|
|
10418
|
+
const tokenMessengerAbi = parseAbi37([
|
|
8901
10419
|
"function depositForBurn(uint256 amount, uint32 destinationDomain, bytes32 mintRecipient, address burnToken, bytes32 destinationCaller, uint256 maxFee, uint32 minFinalityThreshold) external returns (uint64 nonce)"
|
|
8902
10420
|
]);
|
|
8903
|
-
const data =
|
|
10421
|
+
const data = encodeFunctionData34({
|
|
8904
10422
|
abi: tokenMessengerAbi,
|
|
8905
10423
|
functionName: "depositForBurn",
|
|
8906
10424
|
args: [
|
|
@@ -9093,6 +10611,124 @@ function registerFarm(parent, getOpts, makeExecutor2) {
|
|
|
9093
10611
|
});
|
|
9094
10612
|
}
|
|
9095
10613
|
|
|
10614
|
+
// src/commands/farming.ts
|
|
10615
|
+
import { privateKeyToAccount as privateKeyToAccount3 } from "viem/accounts";
|
|
10616
|
+
function registerFarming(parent, getOpts, makeExecutor2) {
|
|
10617
|
+
const farming = parent.command("farming").description("Algebra eternal farming operations (KittenSwap): enter, exit, collect rewards, claim, discover");
|
|
10618
|
+
farming.command("enter").description("Enter farming: stake an NFT position to start earning rewards").requiredOption("--protocol <protocol>", "Protocol slug (e.g. kittenswap)").requiredOption("--pool <address>", "Pool address").requiredOption("--token-id <id>", "NFT position token ID").option("--owner <address>", "Owner address to receive claimed rewards (defaults to DEFI_WALLET_ADDRESS or private key address)").action(async (opts) => {
|
|
10619
|
+
const executor = makeExecutor2();
|
|
10620
|
+
const registry = Registry.loadEmbedded();
|
|
10621
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
10622
|
+
const chainName = parent.opts().chain;
|
|
10623
|
+
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10624
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
10625
|
+
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10626
|
+
const owner = resolveOwner(opts.owner);
|
|
10627
|
+
const tx = await adapter.buildEnterFarming(
|
|
10628
|
+
BigInt(opts.tokenId),
|
|
10629
|
+
opts.pool,
|
|
10630
|
+
owner
|
|
10631
|
+
);
|
|
10632
|
+
const result = await executor.execute(tx);
|
|
10633
|
+
printOutput(result, getOpts());
|
|
10634
|
+
});
|
|
10635
|
+
farming.command("exit").description("Exit farming: unstake an NFT position").requiredOption("--protocol <protocol>", "Protocol slug (e.g. kittenswap)").requiredOption("--pool <address>", "Pool address").requiredOption("--token-id <id>", "NFT position token ID").action(async (opts) => {
|
|
10636
|
+
const executor = makeExecutor2();
|
|
10637
|
+
const registry = Registry.loadEmbedded();
|
|
10638
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
10639
|
+
const chainName = parent.opts().chain;
|
|
10640
|
+
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10641
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
10642
|
+
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10643
|
+
const tx = await adapter.buildExitFarming(
|
|
10644
|
+
BigInt(opts.tokenId),
|
|
10645
|
+
opts.pool
|
|
10646
|
+
);
|
|
10647
|
+
const result = await executor.execute(tx);
|
|
10648
|
+
printOutput(result, getOpts());
|
|
10649
|
+
});
|
|
10650
|
+
farming.command("rewards").description("Collect + claim farming rewards for a staked position (collectRewards + claimReward multicall)").requiredOption("--protocol <protocol>", "Protocol slug (e.g. kittenswap)").requiredOption("--pool <address>", "Pool address").requiredOption("--token-id <id>", "NFT position token ID").option("--owner <address>", "Owner address to receive claimed rewards (defaults to DEFI_WALLET_ADDRESS or private key address)").action(async (opts) => {
|
|
10651
|
+
const executor = makeExecutor2();
|
|
10652
|
+
const registry = Registry.loadEmbedded();
|
|
10653
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
10654
|
+
const chainName = parent.opts().chain;
|
|
10655
|
+
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10656
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
10657
|
+
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10658
|
+
const owner = resolveOwner(opts.owner);
|
|
10659
|
+
const tx = await adapter.buildCollectRewards(
|
|
10660
|
+
BigInt(opts.tokenId),
|
|
10661
|
+
opts.pool,
|
|
10662
|
+
owner
|
|
10663
|
+
);
|
|
10664
|
+
const result = await executor.execute(tx);
|
|
10665
|
+
printOutput(result, getOpts());
|
|
10666
|
+
});
|
|
10667
|
+
farming.command("claim").description("Claim accumulated farming rewards (KITTEN + WHYPE) without changing position").requiredOption("--protocol <protocol>", "Protocol slug (e.g. kittenswap)").option("--owner <address>", "Owner address to receive rewards (defaults to DEFI_WALLET_ADDRESS or private key address)").action(async (opts) => {
|
|
10668
|
+
const executor = makeExecutor2();
|
|
10669
|
+
const registry = Registry.loadEmbedded();
|
|
10670
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
10671
|
+
const chainName = parent.opts().chain;
|
|
10672
|
+
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10673
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
10674
|
+
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10675
|
+
const owner = resolveOwner(opts.owner);
|
|
10676
|
+
const tx = await adapter.buildClaimReward(owner);
|
|
10677
|
+
const result = await executor.execute(tx);
|
|
10678
|
+
printOutput(result, getOpts());
|
|
10679
|
+
});
|
|
10680
|
+
farming.command("pending").description("Query pending farming rewards for a position (read-only)").requiredOption("--protocol <protocol>", "Protocol slug (e.g. kittenswap)").requiredOption("--pool <address>", "Pool address").requiredOption("--token-id <id>", "NFT position token ID").action(async (opts) => {
|
|
10681
|
+
const registry = Registry.loadEmbedded();
|
|
10682
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
10683
|
+
const chainName = parent.opts().chain;
|
|
10684
|
+
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10685
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
10686
|
+
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10687
|
+
const rewards = await adapter.getPendingRewards(
|
|
10688
|
+
BigInt(opts.tokenId),
|
|
10689
|
+
opts.pool
|
|
10690
|
+
);
|
|
10691
|
+
printOutput(
|
|
10692
|
+
{
|
|
10693
|
+
tokenId: opts.tokenId,
|
|
10694
|
+
pool: opts.pool,
|
|
10695
|
+
reward_kitten: rewards.reward.toString(),
|
|
10696
|
+
bonus_reward_whype: rewards.bonusReward.toString()
|
|
10697
|
+
},
|
|
10698
|
+
getOpts()
|
|
10699
|
+
);
|
|
10700
|
+
});
|
|
10701
|
+
farming.command("discover").description("Discover all pools with active KittenSwap farming incentives").requiredOption("--protocol <protocol>", "Protocol slug (e.g. kittenswap)").action(async (opts) => {
|
|
10702
|
+
const registry = Registry.loadEmbedded();
|
|
10703
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
10704
|
+
const chainName = parent.opts().chain;
|
|
10705
|
+
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10706
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
10707
|
+
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10708
|
+
const pools = await adapter.discoverFarmingPools();
|
|
10709
|
+
const output = pools.map((p) => ({
|
|
10710
|
+
pool: p.pool,
|
|
10711
|
+
nonce: p.key.nonce.toString(),
|
|
10712
|
+
total_reward: p.totalReward.toString(),
|
|
10713
|
+
bonus_reward: p.bonusReward.toString(),
|
|
10714
|
+
active: p.active
|
|
10715
|
+
}));
|
|
10716
|
+
printOutput(output, getOpts());
|
|
10717
|
+
});
|
|
10718
|
+
}
|
|
10719
|
+
function resolveOwner(optOwner) {
|
|
10720
|
+
if (optOwner) return optOwner;
|
|
10721
|
+
const walletAddr = process.env["DEFI_WALLET_ADDRESS"];
|
|
10722
|
+
if (walletAddr) return walletAddr;
|
|
10723
|
+
const privateKey = process.env["DEFI_PRIVATE_KEY"];
|
|
10724
|
+
if (privateKey) {
|
|
10725
|
+
return privateKeyToAccount3(privateKey).address;
|
|
10726
|
+
}
|
|
10727
|
+
throw new Error(
|
|
10728
|
+
"--owner, DEFI_WALLET_ADDRESS, or DEFI_PRIVATE_KEY is required to resolve reward recipient"
|
|
10729
|
+
);
|
|
10730
|
+
}
|
|
10731
|
+
|
|
9096
10732
|
// src/commands/setup.ts
|
|
9097
10733
|
import pc2 from "picocolors";
|
|
9098
10734
|
import { createInterface } from "readline";
|
|
@@ -9141,8 +10777,8 @@ function isValidPrivateKey(s) {
|
|
|
9141
10777
|
}
|
|
9142
10778
|
async function deriveAddress(privateKey) {
|
|
9143
10779
|
try {
|
|
9144
|
-
const { privateKeyToAccount:
|
|
9145
|
-
const account =
|
|
10780
|
+
const { privateKeyToAccount: privateKeyToAccount4 } = await import("viem/accounts");
|
|
10781
|
+
const account = privateKeyToAccount4(privateKey);
|
|
9146
10782
|
return account.address;
|
|
9147
10783
|
} catch {
|
|
9148
10784
|
return null;
|
|
@@ -9349,7 +10985,7 @@ var BANNER = `
|
|
|
9349
10985
|
\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
|
|
9350
10986
|
\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
|
|
9351
10987
|
|
|
9352
|
-
2 chains \xB7
|
|
10988
|
+
2 chains \xB7 23 protocols \xB7 by HypurrQuant
|
|
9353
10989
|
|
|
9354
10990
|
Scan exploits, swap tokens, bridge assets, track whales,
|
|
9355
10991
|
compare yields \u2014 all from your terminal.
|
|
@@ -9389,6 +11025,7 @@ registerSwap(program, getOutputMode, makeExecutor);
|
|
|
9389
11025
|
registerBridge(program, getOutputMode);
|
|
9390
11026
|
registerNft(program, getOutputMode);
|
|
9391
11027
|
registerFarm(program, getOutputMode, makeExecutor);
|
|
11028
|
+
registerFarming(program, getOutputMode, makeExecutor);
|
|
9392
11029
|
registerLB(program, getOutputMode, makeExecutor);
|
|
9393
11030
|
registerSetup(program);
|
|
9394
11031
|
program.command("agent").description("Agent mode: read JSON commands from stdin (for AI agents)").action(async () => {
|
|
@@ -9400,13 +11037,13 @@ program.command("agent").description("Agent mode: read JSON commands from stdin
|
|
|
9400
11037
|
|
|
9401
11038
|
// src/landing.ts
|
|
9402
11039
|
import pc3 from "picocolors";
|
|
9403
|
-
import { encodeFunctionData as
|
|
11040
|
+
import { encodeFunctionData as encodeFunctionData33, parseAbi as parseAbi36, formatUnits } from "viem";
|
|
9404
11041
|
var HYPEREVM_DISPLAY = ["HYPE", "WHYPE", "USDC", "USDT0", "USDe", "kHYPE", "wstHYPE"];
|
|
9405
11042
|
var MANTLE_DISPLAY = ["MNT", "WMNT", "USDC", "USDT", "WETH", "mETH"];
|
|
9406
|
-
var balanceOfAbi =
|
|
11043
|
+
var balanceOfAbi = parseAbi36([
|
|
9407
11044
|
"function balanceOf(address account) view returns (uint256)"
|
|
9408
11045
|
]);
|
|
9409
|
-
var getEthBalanceAbi =
|
|
11046
|
+
var getEthBalanceAbi = parseAbi36([
|
|
9410
11047
|
"function getEthBalance(address addr) view returns (uint256)"
|
|
9411
11048
|
]);
|
|
9412
11049
|
async function fetchBalances(rpcUrl, wallet, tokens) {
|
|
@@ -9415,7 +11052,7 @@ async function fetchBalances(rpcUrl, wallet, tokens) {
|
|
|
9415
11052
|
if (isNative) {
|
|
9416
11053
|
return [
|
|
9417
11054
|
MULTICALL3_ADDRESS,
|
|
9418
|
-
|
|
11055
|
+
encodeFunctionData33({
|
|
9419
11056
|
abi: getEthBalanceAbi,
|
|
9420
11057
|
functionName: "getEthBalance",
|
|
9421
11058
|
args: [wallet]
|
|
@@ -9424,7 +11061,7 @@ async function fetchBalances(rpcUrl, wallet, tokens) {
|
|
|
9424
11061
|
}
|
|
9425
11062
|
return [
|
|
9426
11063
|
t.address,
|
|
9427
|
-
|
|
11064
|
+
encodeFunctionData33({
|
|
9428
11065
|
abi: balanceOfAbi,
|
|
9429
11066
|
functionName: "balanceOf",
|
|
9430
11067
|
args: [wallet]
|
|
@@ -9598,6 +11235,7 @@ async function main() {
|
|
|
9598
11235
|
"bridge",
|
|
9599
11236
|
"nft",
|
|
9600
11237
|
"farm",
|
|
11238
|
+
"farming",
|
|
9601
11239
|
"lb",
|
|
9602
11240
|
"agent",
|
|
9603
11241
|
"setup",
|