@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/index.js
CHANGED
|
@@ -1019,6 +1019,24 @@ var Registry = class _Registry {
|
|
|
1019
1019
|
if (!token) throw new Error(`Token not found: ${symbol}`);
|
|
1020
1020
|
return token;
|
|
1021
1021
|
}
|
|
1022
|
+
/**
|
|
1023
|
+
* Resolve a pool by name (e.g. "WHYPE/USDC") from a protocol's pool list.
|
|
1024
|
+
* Returns the pool info or throws if not found.
|
|
1025
|
+
*/
|
|
1026
|
+
resolvePool(protocolSlug, poolName) {
|
|
1027
|
+
const protocol = this.getProtocol(protocolSlug);
|
|
1028
|
+
if (!protocol.pools || protocol.pools.length === 0) {
|
|
1029
|
+
throw new Error(`Protocol ${protocol.name} has no pools configured`);
|
|
1030
|
+
}
|
|
1031
|
+
const pool = protocol.pools.find(
|
|
1032
|
+
(p) => p.name.toLowerCase() === poolName.toLowerCase()
|
|
1033
|
+
);
|
|
1034
|
+
if (!pool) {
|
|
1035
|
+
const available = protocol.pools.map((p) => p.name).join(", ");
|
|
1036
|
+
throw new Error(`Pool '${poolName}' not found in ${protocol.name}. Available: ${available}`);
|
|
1037
|
+
}
|
|
1038
|
+
return pool;
|
|
1039
|
+
}
|
|
1022
1040
|
};
|
|
1023
1041
|
|
|
1024
1042
|
// src/executor.ts
|
|
@@ -1129,8 +1147,11 @@ var Executor = class _Executor {
|
|
|
1129
1147
|
return buffered > MAX_GAS_LIMIT ? MAX_GAS_LIMIT : buffered;
|
|
1130
1148
|
}
|
|
1131
1149
|
} catch {
|
|
1150
|
+
if (tx.gas_estimate) {
|
|
1151
|
+
return _Executor.applyGasBuffer(BigInt(tx.gas_estimate));
|
|
1152
|
+
}
|
|
1132
1153
|
}
|
|
1133
|
-
return
|
|
1154
|
+
return 0n;
|
|
1134
1155
|
}
|
|
1135
1156
|
/** Simulate a transaction via eth_call + eth_estimateGas */
|
|
1136
1157
|
async simulate(tx) {
|
|
@@ -1253,6 +1274,31 @@ var Executor = class _Executor {
|
|
|
1253
1274
|
}
|
|
1254
1275
|
const publicClient = createPublicClient2({ transport: http2(rpcUrl) });
|
|
1255
1276
|
const walletClient = createWalletClient({ account, transport: http2(rpcUrl) });
|
|
1277
|
+
if (tx.pre_txs && tx.pre_txs.length > 0) {
|
|
1278
|
+
for (const preTx of tx.pre_txs) {
|
|
1279
|
+
process.stderr.write(` Pre-tx: ${preTx.description}...
|
|
1280
|
+
`);
|
|
1281
|
+
const preGas = await this.estimateGasWithBuffer(rpcUrl, preTx, account.address);
|
|
1282
|
+
const preTxHash = await walletClient.sendTransaction({
|
|
1283
|
+
chain: null,
|
|
1284
|
+
to: preTx.to,
|
|
1285
|
+
data: preTx.data,
|
|
1286
|
+
value: preTx.value,
|
|
1287
|
+
gas: preGas > 0n ? preGas : void 0
|
|
1288
|
+
});
|
|
1289
|
+
const preTxUrl = this.explorerUrl ? `${this.explorerUrl}/tx/${preTxHash}` : void 0;
|
|
1290
|
+
process.stderr.write(` Pre-tx sent: ${preTxHash}
|
|
1291
|
+
`);
|
|
1292
|
+
if (preTxUrl) process.stderr.write(` Explorer: ${preTxUrl}
|
|
1293
|
+
`);
|
|
1294
|
+
const preReceipt = await publicClient.waitForTransactionReceipt({ hash: preTxHash });
|
|
1295
|
+
if (preReceipt.status !== "success") {
|
|
1296
|
+
throw new DefiError("TX_FAILED", `Pre-transaction failed: ${preTx.description}`);
|
|
1297
|
+
}
|
|
1298
|
+
process.stderr.write(` Pre-tx confirmed
|
|
1299
|
+
`);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1256
1302
|
if (tx.approvals && tx.approvals.length > 0) {
|
|
1257
1303
|
for (const approval of tx.approvals) {
|
|
1258
1304
|
await this.checkAndApprove(
|
|
@@ -1290,20 +1336,37 @@ var Executor = class _Executor {
|
|
|
1290
1336
|
process.stderr.write("Waiting for confirmation...\n");
|
|
1291
1337
|
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
1292
1338
|
const status = receipt.status === "success" ? "confirmed" : "failed";
|
|
1339
|
+
let mintedTokenId;
|
|
1340
|
+
if (receipt.status === "success" && receipt.logs) {
|
|
1341
|
+
const TRANSFER_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
|
|
1342
|
+
const ZERO_TOPIC = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
1343
|
+
for (const log of receipt.logs) {
|
|
1344
|
+
if (log.topics.length >= 4 && log.topics[0] === TRANSFER_TOPIC && log.topics[1] === ZERO_TOPIC) {
|
|
1345
|
+
mintedTokenId = BigInt(log.topics[3]).toString();
|
|
1346
|
+
break;
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
const details = {
|
|
1351
|
+
to: tx.to,
|
|
1352
|
+
from: account.address,
|
|
1353
|
+
block_number: receipt.blockNumber?.toString(),
|
|
1354
|
+
gas_limit: gasLimit.toString(),
|
|
1355
|
+
gas_used: receipt.gasUsed?.toString(),
|
|
1356
|
+
explorer_url: txUrl,
|
|
1357
|
+
mode: "broadcast"
|
|
1358
|
+
};
|
|
1359
|
+
if (mintedTokenId) {
|
|
1360
|
+
details.minted_token_id = mintedTokenId;
|
|
1361
|
+
process.stderr.write(` Minted NFT tokenId: ${mintedTokenId}
|
|
1362
|
+
`);
|
|
1363
|
+
}
|
|
1293
1364
|
return {
|
|
1294
1365
|
tx_hash: txHash,
|
|
1295
1366
|
status,
|
|
1296
1367
|
gas_used: receipt.gasUsed ? Number(receipt.gasUsed) : void 0,
|
|
1297
1368
|
description: tx.description,
|
|
1298
|
-
details
|
|
1299
|
-
to: tx.to,
|
|
1300
|
-
from: account.address,
|
|
1301
|
-
block_number: receipt.blockNumber?.toString(),
|
|
1302
|
-
gas_limit: gasLimit.toString(),
|
|
1303
|
-
gas_used: receipt.gasUsed?.toString(),
|
|
1304
|
-
explorer_url: txUrl,
|
|
1305
|
-
mode: "broadcast"
|
|
1306
|
-
}
|
|
1369
|
+
details
|
|
1307
1370
|
};
|
|
1308
1371
|
}
|
|
1309
1372
|
};
|
|
@@ -1847,32 +1910,45 @@ import { encodeFunctionData as encodeFunctionData32, parseAbi as parseAbi32, cre
|
|
|
1847
1910
|
import { encodeFunctionData as encodeFunctionData42, parseAbi as parseAbi42, zeroAddress as zeroAddress2 } from "viem";
|
|
1848
1911
|
import { encodeFunctionData as encodeFunctionData5, parseAbi as parseAbi5 } from "viem";
|
|
1849
1912
|
import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6, decodeAbiParameters as decodeAbiParameters4 } from "viem";
|
|
1850
|
-
import { encodeFunctionData as encodeFunctionData7, parseAbi as parseAbi7, zeroAddress as zeroAddress3 } from "viem";
|
|
1851
|
-
import { createPublicClient as
|
|
1852
|
-
import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9,
|
|
1913
|
+
import { encodeFunctionData as encodeFunctionData7, parseAbi as parseAbi7, createPublicClient as createPublicClient42, http as http42, zeroAddress as zeroAddress3 } from "viem";
|
|
1914
|
+
import { createPublicClient as createPublicClient5, decodeFunctionResult as decodeFunctionResult22, encodeFunctionData as encodeFunctionData8, http as http5, parseAbi as parseAbi8, zeroAddress as zeroAddress4 } from "viem";
|
|
1915
|
+
import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9, zeroAddress as zeroAddress5 } from "viem";
|
|
1916
|
+
import { createPublicClient as createPublicClient6, decodeFunctionResult as decodeFunctionResult3, encodeFunctionData as encodeFunctionData10, http as http6, parseAbi as parseAbi10, zeroAddress as zeroAddress6 } from "viem";
|
|
1917
|
+
import { encodeFunctionData as encodeFunctionData11, parseAbi as parseAbi11, createPublicClient as createPublicClient7, http as http7 } from "viem";
|
|
1853
1918
|
import {
|
|
1854
|
-
encodeFunctionData as
|
|
1855
|
-
decodeFunctionResult as
|
|
1856
|
-
parseAbi as
|
|
1857
|
-
createPublicClient as
|
|
1858
|
-
http as
|
|
1919
|
+
encodeFunctionData as encodeFunctionData12,
|
|
1920
|
+
decodeFunctionResult as decodeFunctionResult4,
|
|
1921
|
+
parseAbi as parseAbi12,
|
|
1922
|
+
createPublicClient as createPublicClient8,
|
|
1923
|
+
http as http8
|
|
1859
1924
|
} from "viem";
|
|
1860
|
-
import {
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
import { createPublicClient as
|
|
1872
|
-
import { createPublicClient as
|
|
1925
|
+
import {
|
|
1926
|
+
decodeAbiParameters as decodeAbiParameters5,
|
|
1927
|
+
encodeFunctionData as encodeFunctionData13,
|
|
1928
|
+
encodeAbiParameters,
|
|
1929
|
+
http as http9,
|
|
1930
|
+
createPublicClient as createPublicClient9,
|
|
1931
|
+
keccak256,
|
|
1932
|
+
parseAbi as parseAbi13,
|
|
1933
|
+
decodeFunctionResult as decodeFunctionResult5,
|
|
1934
|
+
zeroAddress as zeroAddress7
|
|
1935
|
+
} from "viem";
|
|
1936
|
+
import { createPublicClient as createPublicClient10, http as http10, parseAbi as parseAbi14, encodeFunctionData as encodeFunctionData14, decodeFunctionResult as decodeFunctionResult6, zeroAddress as zeroAddress8 } from "viem";
|
|
1937
|
+
import { createPublicClient as createPublicClient11, http as http11, parseAbi as parseAbi15, encodeFunctionData as encodeFunctionData15, zeroAddress as zeroAddress9 } from "viem";
|
|
1938
|
+
import { createPublicClient as createPublicClient12, http as http12, parseAbi as parseAbi16 } from "viem";
|
|
1939
|
+
import { createPublicClient as createPublicClient13, http as http13, parseAbi as parseAbi17, encodeFunctionData as encodeFunctionData16 } from "viem";
|
|
1940
|
+
import { createPublicClient as createPublicClient14, http as http14, parseAbi as parseAbi18, encodeFunctionData as encodeFunctionData17 } from "viem";
|
|
1941
|
+
import { createPublicClient as createPublicClient15, http as http15, parseAbi as parseAbi19, encodeFunctionData as encodeFunctionData18 } from "viem";
|
|
1942
|
+
import { parseAbi as parseAbi20, encodeFunctionData as encodeFunctionData19, decodeFunctionResult as decodeFunctionResult7, zeroAddress as zeroAddress10 } from "viem";
|
|
1943
|
+
import { createPublicClient as createPublicClient16, http as http16, parseAbi as parseAbi21, encodeFunctionData as encodeFunctionData20, zeroAddress as zeroAddress11 } from "viem";
|
|
1944
|
+
import { createPublicClient as createPublicClient17, http as http17, parseAbi as parseAbi222 } from "viem";
|
|
1945
|
+
import { createPublicClient as createPublicClient18, http as http18, parseAbi as parseAbi23, encodeFunctionData as encodeFunctionData21 } from "viem";
|
|
1873
1946
|
import { parseAbi as parseAbi24, encodeFunctionData as encodeFunctionData222 } from "viem";
|
|
1874
|
-
import { parseAbi as parseAbi25, encodeFunctionData as encodeFunctionData23 } from "viem";
|
|
1875
|
-
import { createPublicClient as
|
|
1947
|
+
import { createPublicClient as createPublicClient19, http as http19, parseAbi as parseAbi25, encodeFunctionData as encodeFunctionData23, zeroAddress as zeroAddress12 } from "viem";
|
|
1948
|
+
import { createPublicClient as createPublicClient20, http as http20, parseAbi as parseAbi26, encodeFunctionData as encodeFunctionData24, zeroAddress as zeroAddress13 } from "viem";
|
|
1949
|
+
import { parseAbi as parseAbi27, encodeFunctionData as encodeFunctionData25 } from "viem";
|
|
1950
|
+
import { parseAbi as parseAbi28, encodeFunctionData as encodeFunctionData26 } from "viem";
|
|
1951
|
+
import { createPublicClient as createPublicClient21, http as http21, parseAbi as parseAbi29 } from "viem";
|
|
1876
1952
|
var DEFAULT_FEE = 3e3;
|
|
1877
1953
|
var swapRouterAbi = parseAbi4([
|
|
1878
1954
|
"struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; }",
|
|
@@ -2324,6 +2400,22 @@ var UniswapV2Adapter = class {
|
|
|
2324
2400
|
};
|
|
2325
2401
|
}
|
|
2326
2402
|
};
|
|
2403
|
+
function pctToTickDelta(pct) {
|
|
2404
|
+
return Math.round(Math.log(1 + pct / 100) / Math.log(1.0001));
|
|
2405
|
+
}
|
|
2406
|
+
function alignTickDown(tick, tickSpacing) {
|
|
2407
|
+
return Math.floor(tick / tickSpacing) * tickSpacing;
|
|
2408
|
+
}
|
|
2409
|
+
function alignTickUp(tick, tickSpacing) {
|
|
2410
|
+
return Math.ceil(tick / tickSpacing) * tickSpacing;
|
|
2411
|
+
}
|
|
2412
|
+
function rangeToTicks(currentTick, rangePct, tickSpacing) {
|
|
2413
|
+
const delta = pctToTickDelta(rangePct);
|
|
2414
|
+
return {
|
|
2415
|
+
tickLower: alignTickDown(currentTick - delta, tickSpacing),
|
|
2416
|
+
tickUpper: alignTickUp(currentTick + delta, tickSpacing)
|
|
2417
|
+
};
|
|
2418
|
+
}
|
|
2327
2419
|
var abi2 = parseAbi32([
|
|
2328
2420
|
"struct ExactInputSingleParams { address tokenIn; address tokenOut; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 limitSqrtPrice; }",
|
|
2329
2421
|
"function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut)"
|
|
@@ -2334,7 +2426,11 @@ var algebraQuoterAbi = parseAbi32([
|
|
|
2334
2426
|
var algebraSingleQuoterAbi = parseAbi32([
|
|
2335
2427
|
"function quoteExactInputSingle((address tokenIn, address tokenOut, uint256 amountIn, uint160 limitSqrtPrice) params) external returns (uint256 amountOut, uint256 amountIn, uint160 sqrtPriceX96After)"
|
|
2336
2428
|
]);
|
|
2337
|
-
var
|
|
2429
|
+
var algebraIntegralPmAbi = parseAbi32([
|
|
2430
|
+
"struct MintParams { address token0; address token1; address deployer; int24 tickLower; int24 tickUpper; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; address recipient; uint256 deadline; }",
|
|
2431
|
+
"function mint(MintParams calldata params) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1)"
|
|
2432
|
+
]);
|
|
2433
|
+
var algebraV2PmAbi = parseAbi32([
|
|
2338
2434
|
"struct MintParams { address token0; address token1; int24 tickLower; int24 tickUpper; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; address recipient; uint256 deadline; }",
|
|
2339
2435
|
"function mint(MintParams calldata params) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1)"
|
|
2340
2436
|
]);
|
|
@@ -2479,36 +2575,58 @@ var AlgebraV3Adapter = class {
|
|
|
2479
2575
|
throw new DefiError("CONTRACT_ERROR", "Position manager address not configured");
|
|
2480
2576
|
}
|
|
2481
2577
|
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];
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
const
|
|
2485
|
-
|
|
2578
|
+
let tickLower = params.tick_lower ?? -887220;
|
|
2579
|
+
let tickUpper = params.tick_upper ?? 887220;
|
|
2580
|
+
const isSingleSide = rawAmount0 === 0n || rawAmount1 === 0n;
|
|
2581
|
+
const needsAutoTick = params.range_pct !== void 0 || isSingleSide && !params.tick_lower && !params.tick_upper;
|
|
2582
|
+
if (needsAutoTick) {
|
|
2583
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC URL required for auto tick detection");
|
|
2584
|
+
const poolAddr = params.pool;
|
|
2585
|
+
if (!poolAddr) throw new DefiError("CONTRACT_ERROR", "Pool address required (use --pool)");
|
|
2586
|
+
const client = createPublicClient32({ transport: http32(this.rpcUrl) });
|
|
2587
|
+
const algebraPoolAbi = parseAbi32([
|
|
2588
|
+
"function globalState() view returns (uint160 price, int24 tick, uint16 lastFee, uint8 pluginConfig, uint16 communityFee, bool unlocked)",
|
|
2589
|
+
"function tickSpacing() view returns (int24)"
|
|
2590
|
+
]);
|
|
2591
|
+
const [globalState, spacing] = await Promise.all([
|
|
2592
|
+
client.readContract({ address: poolAddr, abi: algebraPoolAbi, functionName: "globalState" }),
|
|
2593
|
+
client.readContract({ address: poolAddr, abi: algebraPoolAbi, functionName: "tickSpacing" })
|
|
2594
|
+
]);
|
|
2595
|
+
const currentTick = Number(globalState[1]);
|
|
2596
|
+
const tickSpace = Number(spacing);
|
|
2597
|
+
if (params.range_pct !== void 0) {
|
|
2598
|
+
const range = rangeToTicks(currentTick, params.range_pct, tickSpace);
|
|
2599
|
+
tickLower = range.tickLower;
|
|
2600
|
+
tickUpper = range.tickUpper;
|
|
2601
|
+
} else if (rawAmount0 > 0n && rawAmount1 === 0n) {
|
|
2602
|
+
tickLower = alignTickUp(currentTick + tickSpace, tickSpace);
|
|
2603
|
+
tickUpper = 887220;
|
|
2604
|
+
} else {
|
|
2605
|
+
tickLower = -887220;
|
|
2606
|
+
tickUpper = alignTickDown(currentTick - tickSpace, tickSpace);
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
const amount0 = rawAmount0;
|
|
2610
|
+
const amount1 = rawAmount1;
|
|
2611
|
+
const data = this.useSingleQuoter ? encodeFunctionData32({
|
|
2612
|
+
abi: algebraV2PmAbi,
|
|
2486
2613
|
functionName: "mint",
|
|
2487
|
-
args: [
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
tickUpper: 887220,
|
|
2493
|
-
amount0Desired: amount0,
|
|
2494
|
-
amount1Desired: amount1,
|
|
2495
|
-
amount0Min: 0n,
|
|
2496
|
-
amount1Min: 0n,
|
|
2497
|
-
recipient: params.recipient,
|
|
2498
|
-
deadline: BigInt("18446744073709551615")
|
|
2499
|
-
}
|
|
2500
|
-
]
|
|
2614
|
+
args: [{ token0, token1, tickLower, tickUpper, amount0Desired: amount0, amount1Desired: amount1, amount0Min: 0n, amount1Min: 0n, recipient: params.recipient, deadline: BigInt("18446744073709551615") }]
|
|
2615
|
+
}) : encodeFunctionData32({
|
|
2616
|
+
abi: algebraIntegralPmAbi,
|
|
2617
|
+
functionName: "mint",
|
|
2618
|
+
args: [{ token0, token1, deployer: zeroAddress, tickLower, tickUpper, amount0Desired: amount0, amount1Desired: amount1, amount0Min: 0n, amount1Min: 0n, recipient: params.recipient, deadline: BigInt("18446744073709551615") }]
|
|
2501
2619
|
});
|
|
2620
|
+
const approvals = [];
|
|
2621
|
+
if (amount0 > 0n) approvals.push({ token: token0, spender: pm, amount: amount0 });
|
|
2622
|
+
if (amount1 > 0n) approvals.push({ token: token1, spender: pm, amount: amount1 });
|
|
2502
2623
|
return {
|
|
2503
|
-
description: `[${this.protocolName}] Add liquidity`,
|
|
2624
|
+
description: `[${this.protocolName}] Add liquidity [${tickLower}, ${tickUpper}]`,
|
|
2504
2625
|
to: pm,
|
|
2505
2626
|
data,
|
|
2506
2627
|
value: 0n,
|
|
2507
2628
|
gas_estimate: 5e5,
|
|
2508
|
-
approvals
|
|
2509
|
-
{ token: token0, spender: pm, amount: amount0 },
|
|
2510
|
-
{ token: token1, spender: pm, amount: amount1 }
|
|
2511
|
-
]
|
|
2629
|
+
approvals
|
|
2512
2630
|
};
|
|
2513
2631
|
}
|
|
2514
2632
|
async buildRemoveLiquidity(_params) {
|
|
@@ -2800,228 +2918,1105 @@ var SolidlyAdapter = class {
|
|
|
2800
2918
|
};
|
|
2801
2919
|
}
|
|
2802
2920
|
};
|
|
2803
|
-
var
|
|
2804
|
-
"
|
|
2921
|
+
var thenaPmAbi = parseAbi7([
|
|
2922
|
+
"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; }",
|
|
2923
|
+
"function mint(MintParams calldata params) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1)"
|
|
2805
2924
|
]);
|
|
2806
|
-
var
|
|
2925
|
+
var thenaRouterAbi = parseAbi7([
|
|
2926
|
+
"struct ExactInputSingleParams { address tokenIn; address tokenOut; int24 tickSpacing; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; }",
|
|
2927
|
+
"function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut)"
|
|
2928
|
+
]);
|
|
2929
|
+
var thenaPoolAbi = parseAbi7([
|
|
2930
|
+
"function slot0() view returns (uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, bool unlocked)",
|
|
2931
|
+
"function tickSpacing() view returns (int24)",
|
|
2932
|
+
"function token0() view returns (address)",
|
|
2933
|
+
"function token1() view returns (address)"
|
|
2934
|
+
]);
|
|
2935
|
+
var thenaFactoryAbi = parseAbi7([
|
|
2936
|
+
"function getPool(address tokenA, address tokenB, int24 tickSpacing) view returns (address)"
|
|
2937
|
+
]);
|
|
2938
|
+
var ThenaCLAdapter = class {
|
|
2807
2939
|
protocolName;
|
|
2808
2940
|
router;
|
|
2809
|
-
|
|
2941
|
+
positionManager;
|
|
2942
|
+
factory;
|
|
2943
|
+
rpcUrl;
|
|
2944
|
+
defaultTickSpacing;
|
|
2945
|
+
constructor(entry, rpcUrl) {
|
|
2810
2946
|
this.protocolName = entry.name;
|
|
2811
2947
|
const router = entry.contracts?.["router"];
|
|
2812
|
-
if (!router)
|
|
2813
|
-
throw new DefiError("CONTRACT_ERROR", "Missing 'router' contract");
|
|
2814
|
-
}
|
|
2948
|
+
if (!router) throw new DefiError("CONTRACT_ERROR", "Missing 'router' contract address");
|
|
2815
2949
|
this.router = router;
|
|
2950
|
+
this.positionManager = entry.contracts?.["position_manager"];
|
|
2951
|
+
this.factory = entry.contracts?.["pool_factory"];
|
|
2952
|
+
this.rpcUrl = rpcUrl;
|
|
2953
|
+
this.defaultTickSpacing = 50;
|
|
2816
2954
|
}
|
|
2817
2955
|
name() {
|
|
2818
2956
|
return this.protocolName;
|
|
2819
2957
|
}
|
|
2820
2958
|
async buildSwap(params) {
|
|
2821
|
-
const minToAmount = 0n;
|
|
2822
2959
|
const data = encodeFunctionData7({
|
|
2823
|
-
abi:
|
|
2824
|
-
functionName: "
|
|
2825
|
-
args: [
|
|
2826
|
-
params.token_in,
|
|
2827
|
-
params.token_out,
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
params.
|
|
2831
|
-
|
|
2832
|
-
|
|
2960
|
+
abi: thenaRouterAbi,
|
|
2961
|
+
functionName: "exactInputSingle",
|
|
2962
|
+
args: [{
|
|
2963
|
+
tokenIn: params.token_in,
|
|
2964
|
+
tokenOut: params.token_out,
|
|
2965
|
+
tickSpacing: this.defaultTickSpacing,
|
|
2966
|
+
recipient: params.recipient,
|
|
2967
|
+
deadline: BigInt(params.deadline ?? 18446744073709551615n),
|
|
2968
|
+
amountIn: params.amount_in,
|
|
2969
|
+
amountOutMinimum: 0n,
|
|
2970
|
+
sqrtPriceLimitX96: 0n
|
|
2971
|
+
}]
|
|
2833
2972
|
});
|
|
2834
2973
|
return {
|
|
2835
|
-
description: `[${this.protocolName}] Swap
|
|
2974
|
+
description: `[${this.protocolName}] Swap`,
|
|
2836
2975
|
to: this.router,
|
|
2837
2976
|
data,
|
|
2838
2977
|
value: 0n,
|
|
2839
|
-
gas_estimate:
|
|
2978
|
+
gas_estimate: 3e5,
|
|
2979
|
+
approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
|
|
2840
2980
|
};
|
|
2841
2981
|
}
|
|
2842
2982
|
async quote(_params) {
|
|
2843
|
-
throw DefiError.unsupported(`[${this.protocolName}] quote
|
|
2983
|
+
throw DefiError.unsupported(`[${this.protocolName}] quote not yet implemented \u2014 use swap router`);
|
|
2844
2984
|
}
|
|
2845
|
-
async buildAddLiquidity(
|
|
2846
|
-
|
|
2985
|
+
async buildAddLiquidity(params) {
|
|
2986
|
+
const pm = this.positionManager;
|
|
2987
|
+
if (!pm) throw new DefiError("CONTRACT_ERROR", "Position manager not configured");
|
|
2988
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC URL required");
|
|
2989
|
+
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];
|
|
2990
|
+
const client = createPublicClient42({ transport: http42(this.rpcUrl) });
|
|
2991
|
+
const poolAddr = params.pool;
|
|
2992
|
+
let tickSpacing = this.defaultTickSpacing;
|
|
2993
|
+
let tickLower = params.tick_lower ?? 0;
|
|
2994
|
+
let tickUpper = params.tick_upper ?? 0;
|
|
2995
|
+
if (poolAddr || !params.tick_lower || !params.tick_upper) {
|
|
2996
|
+
let pool = poolAddr;
|
|
2997
|
+
if (!pool && this.factory) {
|
|
2998
|
+
pool = await client.readContract({
|
|
2999
|
+
address: this.factory,
|
|
3000
|
+
abi: thenaFactoryAbi,
|
|
3001
|
+
functionName: "getPool",
|
|
3002
|
+
args: [token0, token1, tickSpacing]
|
|
3003
|
+
});
|
|
3004
|
+
if (pool === zeroAddress3) throw new DefiError("CONTRACT_ERROR", "Pool not found");
|
|
3005
|
+
}
|
|
3006
|
+
if (pool) {
|
|
3007
|
+
const [slot0, ts] = await Promise.all([
|
|
3008
|
+
client.readContract({ address: pool, abi: thenaPoolAbi, functionName: "slot0" }),
|
|
3009
|
+
client.readContract({ address: pool, abi: thenaPoolAbi, functionName: "tickSpacing" })
|
|
3010
|
+
]);
|
|
3011
|
+
const currentTick = Number(slot0[1]);
|
|
3012
|
+
tickSpacing = Number(ts);
|
|
3013
|
+
if (params.range_pct !== void 0) {
|
|
3014
|
+
const range = rangeToTicks(currentTick, params.range_pct, tickSpacing);
|
|
3015
|
+
tickLower = range.tickLower;
|
|
3016
|
+
tickUpper = range.tickUpper;
|
|
3017
|
+
} else if (!params.tick_lower && !params.tick_upper) {
|
|
3018
|
+
const isSingleSide = rawAmount0 === 0n || rawAmount1 === 0n;
|
|
3019
|
+
if (isSingleSide) {
|
|
3020
|
+
if (rawAmount0 > 0n) {
|
|
3021
|
+
tickLower = alignTickUp(currentTick + tickSpacing, tickSpacing);
|
|
3022
|
+
tickUpper = Math.floor(887272 / tickSpacing) * tickSpacing;
|
|
3023
|
+
} else {
|
|
3024
|
+
tickLower = Math.ceil(-887272 / tickSpacing) * tickSpacing;
|
|
3025
|
+
tickUpper = alignTickDown(currentTick - tickSpacing, tickSpacing);
|
|
3026
|
+
}
|
|
3027
|
+
} else {
|
|
3028
|
+
tickLower = Math.ceil(-887272 / tickSpacing) * tickSpacing;
|
|
3029
|
+
tickUpper = Math.floor(887272 / tickSpacing) * tickSpacing;
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
}
|
|
3033
|
+
}
|
|
3034
|
+
if (params.tick_lower !== void 0) tickLower = params.tick_lower;
|
|
3035
|
+
if (params.tick_upper !== void 0) tickUpper = params.tick_upper;
|
|
3036
|
+
const data = encodeFunctionData7({
|
|
3037
|
+
abi: thenaPmAbi,
|
|
3038
|
+
functionName: "mint",
|
|
3039
|
+
args: [{
|
|
3040
|
+
token0,
|
|
3041
|
+
token1,
|
|
3042
|
+
tickSpacing,
|
|
3043
|
+
tickLower,
|
|
3044
|
+
tickUpper,
|
|
3045
|
+
amount0Desired: rawAmount0,
|
|
3046
|
+
amount1Desired: rawAmount1,
|
|
3047
|
+
amount0Min: 0n,
|
|
3048
|
+
amount1Min: 0n,
|
|
3049
|
+
recipient: params.recipient,
|
|
3050
|
+
deadline: BigInt("18446744073709551615"),
|
|
3051
|
+
sqrtPriceX96: 0n
|
|
3052
|
+
}]
|
|
3053
|
+
});
|
|
3054
|
+
const approvals = [];
|
|
3055
|
+
if (rawAmount0 > 0n) approvals.push({ token: token0, spender: pm, amount: rawAmount0 });
|
|
3056
|
+
if (rawAmount1 > 0n) approvals.push({ token: token1, spender: pm, amount: rawAmount1 });
|
|
3057
|
+
return {
|
|
3058
|
+
description: `[${this.protocolName}] Add liquidity [${tickLower}, ${tickUpper}]`,
|
|
3059
|
+
to: pm,
|
|
3060
|
+
data,
|
|
3061
|
+
value: 0n,
|
|
3062
|
+
gas_estimate: 7e5,
|
|
3063
|
+
approvals
|
|
3064
|
+
};
|
|
2847
3065
|
}
|
|
2848
3066
|
async buildRemoveLiquidity(_params) {
|
|
2849
|
-
throw DefiError.unsupported(`[${this.protocolName}]
|
|
3067
|
+
throw DefiError.unsupported(`[${this.protocolName}] remove_liquidity requires tokenId`);
|
|
2850
3068
|
}
|
|
2851
3069
|
};
|
|
2852
|
-
var
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
3070
|
+
var _addressDecodeAbi = parseAbi8(["function f() external view returns (address)"]);
|
|
3071
|
+
function decodeAddress(data) {
|
|
3072
|
+
if (!data) return null;
|
|
3073
|
+
try {
|
|
3074
|
+
return decodeFunctionResult22({ abi: _addressDecodeAbi, functionName: "f", data });
|
|
3075
|
+
} catch {
|
|
3076
|
+
return null;
|
|
3077
|
+
}
|
|
3078
|
+
}
|
|
3079
|
+
var _symbolDecodeAbi = parseAbi8(["function symbol() external view returns (string)"]);
|
|
3080
|
+
function decodeSymbol(data) {
|
|
3081
|
+
if (!data) return "?";
|
|
3082
|
+
try {
|
|
3083
|
+
return decodeFunctionResult22({ abi: _symbolDecodeAbi, functionName: "symbol", data });
|
|
3084
|
+
} catch {
|
|
3085
|
+
return "?";
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
var gaugeManagerAbi = parseAbi8([
|
|
3089
|
+
"function gauges(address pool) view returns (address gauge)",
|
|
3090
|
+
"function isGauge(address gauge) view returns (bool)",
|
|
3091
|
+
"function isAlive(address gauge) view returns (bool)",
|
|
3092
|
+
"function claimRewards(address gauge, uint256[] tokenIds, uint8 redeemType) external"
|
|
3093
|
+
]);
|
|
3094
|
+
var gaugeCLAbi = parseAbi8([
|
|
3095
|
+
"function deposit(uint256 tokenId) external",
|
|
3096
|
+
"function withdraw(uint256 tokenId, uint8 redeemType) external",
|
|
3097
|
+
"function earned(uint256 tokenId) view returns (uint256)",
|
|
3098
|
+
"function balanceOf(uint256 tokenId) view returns (uint256)",
|
|
3099
|
+
"function rewardToken() view returns (address)"
|
|
3100
|
+
]);
|
|
3101
|
+
var nfpmAbi = parseAbi8([
|
|
3102
|
+
"function approve(address to, uint256 tokenId) external",
|
|
3103
|
+
"function getApproved(uint256 tokenId) view returns (address)"
|
|
2864
3104
|
]);
|
|
2865
3105
|
var veAbi = parseAbi8([
|
|
2866
3106
|
"function create_lock(uint256 value, uint256 lock_duration) external returns (uint256)",
|
|
2867
3107
|
"function increase_amount(uint256 tokenId, uint256 value) external",
|
|
2868
3108
|
"function increase_unlock_time(uint256 tokenId, uint256 lock_duration) external",
|
|
2869
|
-
"function withdraw(uint256 tokenId) external"
|
|
2870
|
-
"function balanceOfNFT(uint256 tokenId) external view returns (uint256)",
|
|
2871
|
-
"function locked(uint256 tokenId) external view returns (uint256 amount, uint256 end)"
|
|
3109
|
+
"function withdraw(uint256 tokenId) external"
|
|
2872
3110
|
]);
|
|
2873
3111
|
var voterAbi = parseAbi8([
|
|
2874
|
-
"function vote(uint256 tokenId, address[]
|
|
2875
|
-
"function claimBribes(address[]
|
|
2876
|
-
"function claimFees(address[]
|
|
2877
|
-
"function gauges(address pool) external view returns (address)"
|
|
3112
|
+
"function vote(uint256 tokenId, address[] pools, uint256[] weights) external",
|
|
3113
|
+
"function claimBribes(address[] bribes, address[][] tokens, uint256 tokenId) external",
|
|
3114
|
+
"function claimFees(address[] fees, address[][] tokens, uint256 tokenId) external"
|
|
2878
3115
|
]);
|
|
2879
|
-
var
|
|
3116
|
+
var HybraGaugeAdapter = class {
|
|
2880
3117
|
protocolName;
|
|
2881
|
-
|
|
3118
|
+
gaugeManager;
|
|
2882
3119
|
veToken;
|
|
3120
|
+
voter;
|
|
3121
|
+
positionManager;
|
|
3122
|
+
poolFactory;
|
|
2883
3123
|
rpcUrl;
|
|
2884
3124
|
constructor(entry, rpcUrl) {
|
|
2885
3125
|
this.protocolName = entry.name;
|
|
2886
|
-
const
|
|
2887
|
-
if (!
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
this.
|
|
2895
|
-
this.veToken = veToken;
|
|
3126
|
+
const gm = entry.contracts?.["gauge_manager"];
|
|
3127
|
+
if (!gm) throw new DefiError("CONTRACT_ERROR", "Missing 'gauge_manager' contract");
|
|
3128
|
+
this.gaugeManager = gm;
|
|
3129
|
+
const ve = entry.contracts?.["ve_token"];
|
|
3130
|
+
if (!ve) throw new DefiError("CONTRACT_ERROR", "Missing 've_token' contract");
|
|
3131
|
+
this.veToken = ve;
|
|
3132
|
+
this.voter = entry.contracts?.["voter"] ?? zeroAddress4;
|
|
3133
|
+
this.positionManager = entry.contracts?.["position_manager"] ?? zeroAddress4;
|
|
3134
|
+
this.poolFactory = entry.contracts?.["pool_factory"];
|
|
2896
3135
|
this.rpcUrl = rpcUrl;
|
|
2897
3136
|
}
|
|
2898
3137
|
name() {
|
|
2899
3138
|
return this.protocolName;
|
|
2900
3139
|
}
|
|
2901
|
-
//
|
|
2902
|
-
async
|
|
2903
|
-
if (
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
3140
|
+
// ─── Gauge Discovery ──────────────────────────────────────
|
|
3141
|
+
async discoverGaugedPools() {
|
|
3142
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC URL required for gauge discovery");
|
|
3143
|
+
if (!this.poolFactory) throw new DefiError("CONTRACT_ERROR", "Missing 'pool_factory' contract");
|
|
3144
|
+
const factoryAbi = parseAbi8([
|
|
3145
|
+
"function allPoolsLength() external view returns (uint256)",
|
|
3146
|
+
"function allPools(uint256) external view returns (address)"
|
|
3147
|
+
]);
|
|
3148
|
+
const poolAbi2 = parseAbi8([
|
|
3149
|
+
"function token0() external view returns (address)",
|
|
3150
|
+
"function token1() external view returns (address)"
|
|
3151
|
+
]);
|
|
3152
|
+
const erc20SymbolAbi = parseAbi8(["function symbol() external view returns (string)"]);
|
|
3153
|
+
const gaugesAbi = parseAbi8(["function gauges(address pool) view returns (address gauge)"]);
|
|
3154
|
+
const client = createPublicClient5({ transport: http5(this.rpcUrl) });
|
|
3155
|
+
let poolCount;
|
|
3156
|
+
try {
|
|
3157
|
+
poolCount = await client.readContract({
|
|
3158
|
+
address: this.poolFactory,
|
|
3159
|
+
abi: factoryAbi,
|
|
3160
|
+
functionName: "allPoolsLength"
|
|
2908
3161
|
});
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
to: gauge,
|
|
2912
|
-
data: data2,
|
|
2913
|
-
value: 0n,
|
|
2914
|
-
gas_estimate: 2e5,
|
|
2915
|
-
approvals: lpToken ? [{ token: lpToken, spender: gauge, amount }] : void 0
|
|
2916
|
-
};
|
|
3162
|
+
} catch {
|
|
3163
|
+
return [];
|
|
2917
3164
|
}
|
|
2918
|
-
const
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
3165
|
+
const count = Number(poolCount);
|
|
3166
|
+
if (count === 0) return [];
|
|
3167
|
+
const poolAddressCalls = [];
|
|
3168
|
+
for (let i = 0; i < count; i++) {
|
|
3169
|
+
poolAddressCalls.push([
|
|
3170
|
+
this.poolFactory,
|
|
3171
|
+
encodeFunctionData8({ abi: factoryAbi, functionName: "allPools", args: [BigInt(i)] })
|
|
3172
|
+
]);
|
|
3173
|
+
}
|
|
3174
|
+
const poolAddressResults = await multicallRead(this.rpcUrl, poolAddressCalls);
|
|
3175
|
+
const pools = poolAddressResults.map((r) => decodeAddress(r)).filter((a) => a !== null && a !== zeroAddress4);
|
|
3176
|
+
if (pools.length === 0) return [];
|
|
3177
|
+
const gaugeCalls = pools.map((pool) => [
|
|
3178
|
+
this.gaugeManager,
|
|
3179
|
+
encodeFunctionData8({ abi: gaugesAbi, functionName: "gauges", args: [pool] })
|
|
3180
|
+
]);
|
|
3181
|
+
const gaugeResults = await multicallRead(this.rpcUrl, gaugeCalls);
|
|
3182
|
+
const gaugedPools = [];
|
|
3183
|
+
for (let i = 0; i < pools.length; i++) {
|
|
3184
|
+
const gauge = decodeAddress(gaugeResults[i] ?? null);
|
|
3185
|
+
if (gauge && gauge !== zeroAddress4) {
|
|
3186
|
+
gaugedPools.push({ pool: pools[i], gauge });
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
3189
|
+
if (gaugedPools.length === 0) return [];
|
|
3190
|
+
const tokenCalls = [];
|
|
3191
|
+
for (const { pool } of gaugedPools) {
|
|
3192
|
+
tokenCalls.push([pool, encodeFunctionData8({ abi: poolAbi2, functionName: "token0" })]);
|
|
3193
|
+
tokenCalls.push([pool, encodeFunctionData8({ abi: poolAbi2, functionName: "token1" })]);
|
|
3194
|
+
}
|
|
3195
|
+
const tokenResults = await multicallRead(this.rpcUrl, tokenCalls);
|
|
3196
|
+
const tokenAddrs = /* @__PURE__ */ new Set();
|
|
3197
|
+
for (let i = 0; i < gaugedPools.length; i++) {
|
|
3198
|
+
const t0 = decodeAddress(tokenResults[i * 2] ?? null);
|
|
3199
|
+
const t1 = decodeAddress(tokenResults[i * 2 + 1] ?? null);
|
|
3200
|
+
if (t0 && t0 !== zeroAddress4) tokenAddrs.add(t0);
|
|
3201
|
+
if (t1 && t1 !== zeroAddress4) tokenAddrs.add(t1);
|
|
3202
|
+
}
|
|
3203
|
+
const uniqueTokens = Array.from(tokenAddrs);
|
|
3204
|
+
const symbolCalls = uniqueTokens.map((t) => [
|
|
3205
|
+
t,
|
|
3206
|
+
encodeFunctionData8({ abi: erc20SymbolAbi, functionName: "symbol" })
|
|
3207
|
+
]);
|
|
3208
|
+
const symbolResults = await multicallRead(this.rpcUrl, symbolCalls);
|
|
3209
|
+
const symbolMap = /* @__PURE__ */ new Map();
|
|
3210
|
+
for (let i = 0; i < uniqueTokens.length; i++) {
|
|
3211
|
+
symbolMap.set(uniqueTokens[i], decodeSymbol(symbolResults[i] ?? null));
|
|
3212
|
+
}
|
|
3213
|
+
const out = [];
|
|
3214
|
+
for (let i = 0; i < gaugedPools.length; i++) {
|
|
3215
|
+
const { pool, gauge } = gaugedPools[i];
|
|
3216
|
+
const t0 = decodeAddress(tokenResults[i * 2] ?? null);
|
|
3217
|
+
const t1 = decodeAddress(tokenResults[i * 2 + 1] ?? null);
|
|
3218
|
+
out.push({
|
|
3219
|
+
pool,
|
|
3220
|
+
gauge,
|
|
3221
|
+
token0: t0 ? symbolMap.get(t0) ?? t0.slice(0, 10) : "?",
|
|
3222
|
+
token1: t1 ? symbolMap.get(t1) ?? t1.slice(0, 10) : "?",
|
|
3223
|
+
type: "CL"
|
|
3224
|
+
});
|
|
3225
|
+
}
|
|
3226
|
+
return out;
|
|
3227
|
+
}
|
|
3228
|
+
// ─── Gauge Lookup ──────────────────────────────────────────
|
|
3229
|
+
async resolveGauge(pool) {
|
|
3230
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC required");
|
|
3231
|
+
const client = createPublicClient5({ transport: http5(this.rpcUrl) });
|
|
3232
|
+
const gauge = await client.readContract({
|
|
3233
|
+
address: this.gaugeManager,
|
|
3234
|
+
abi: gaugeManagerAbi,
|
|
3235
|
+
functionName: "gauges",
|
|
3236
|
+
args: [pool]
|
|
3237
|
+
});
|
|
3238
|
+
if (gauge === zeroAddress4) throw new DefiError("CONTRACT_ERROR", `No gauge for pool ${pool}`);
|
|
3239
|
+
return gauge;
|
|
3240
|
+
}
|
|
3241
|
+
// ─── CL Gauge: NFT Deposit/Withdraw ──────────────────────────
|
|
3242
|
+
async buildDeposit(gauge, _amount, tokenId) {
|
|
3243
|
+
if (tokenId === void 0) throw new DefiError("CONTRACT_ERROR", "tokenId required for CL gauge deposit");
|
|
3244
|
+
const approveTx = {
|
|
3245
|
+
description: `[${this.protocolName}] Approve NFT #${tokenId} to gauge`,
|
|
3246
|
+
to: this.positionManager,
|
|
3247
|
+
data: encodeFunctionData8({ abi: nfpmAbi, functionName: "approve", args: [gauge, tokenId] }),
|
|
3248
|
+
value: 0n,
|
|
3249
|
+
gas_estimate: 8e4
|
|
3250
|
+
};
|
|
2923
3251
|
return {
|
|
2924
|
-
description: `[${this.protocolName}] Deposit
|
|
3252
|
+
description: `[${this.protocolName}] Deposit NFT #${tokenId} to gauge`,
|
|
2925
3253
|
to: gauge,
|
|
2926
|
-
data,
|
|
3254
|
+
data: encodeFunctionData8({ abi: gaugeCLAbi, functionName: "deposit", args: [tokenId] }),
|
|
2927
3255
|
value: 0n,
|
|
2928
|
-
gas_estimate:
|
|
2929
|
-
|
|
3256
|
+
gas_estimate: 5e5,
|
|
3257
|
+
pre_txs: [approveTx]
|
|
2930
3258
|
};
|
|
2931
3259
|
}
|
|
2932
|
-
async buildWithdraw(gauge,
|
|
2933
|
-
|
|
2934
|
-
abi: gaugeAbi,
|
|
2935
|
-
functionName: "withdraw",
|
|
2936
|
-
args: [amount]
|
|
2937
|
-
});
|
|
3260
|
+
async buildWithdraw(gauge, _amount, tokenId) {
|
|
3261
|
+
if (tokenId === void 0) throw new DefiError("CONTRACT_ERROR", "tokenId required for CL gauge withdraw");
|
|
2938
3262
|
return {
|
|
2939
|
-
description: `[${this.protocolName}] Withdraw
|
|
3263
|
+
description: `[${this.protocolName}] Withdraw NFT #${tokenId} from gauge`,
|
|
2940
3264
|
to: gauge,
|
|
2941
|
-
data,
|
|
3265
|
+
data: encodeFunctionData8({ abi: gaugeCLAbi, functionName: "withdraw", args: [tokenId, 1] }),
|
|
2942
3266
|
value: 0n,
|
|
2943
|
-
gas_estimate:
|
|
3267
|
+
gas_estimate: 1e6
|
|
2944
3268
|
};
|
|
2945
3269
|
}
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
address: gauge,
|
|
2952
|
-
abi: gaugeAbi,
|
|
2953
|
-
functionName: "rewardsListLength"
|
|
2954
|
-
});
|
|
2955
|
-
if (listLen > 0n) {
|
|
2956
|
-
const data2 = encodeFunctionData8({
|
|
2957
|
-
abi: gaugeAbi,
|
|
2958
|
-
functionName: "getReward",
|
|
2959
|
-
args: [account, []]
|
|
2960
|
-
});
|
|
2961
|
-
return {
|
|
2962
|
-
description: `[${this.protocolName}] Claim gauge rewards`,
|
|
2963
|
-
to: gauge,
|
|
2964
|
-
data: data2,
|
|
2965
|
-
value: 0n,
|
|
2966
|
-
gas_estimate: 3e5
|
|
2967
|
-
};
|
|
2968
|
-
}
|
|
2969
|
-
} catch {
|
|
2970
|
-
}
|
|
2971
|
-
}
|
|
2972
|
-
const data = encodeFunctionData8({
|
|
2973
|
-
abi: gaugeAbi,
|
|
2974
|
-
functionName: "getReward",
|
|
2975
|
-
args: [account ?? zeroAddress4]
|
|
2976
|
-
});
|
|
3270
|
+
// ─── Claim: via GaugeManager ──────────────────────────────────
|
|
3271
|
+
async buildClaimRewards(gauge, _account) {
|
|
3272
|
+
throw DefiError.unsupported(`[${this.protocolName}] Use buildClaimRewardsByTokenId for CL gauges`);
|
|
3273
|
+
}
|
|
3274
|
+
async buildClaimRewardsByTokenId(gauge, tokenId) {
|
|
2977
3275
|
return {
|
|
2978
|
-
description: `[${this.protocolName}] Claim
|
|
2979
|
-
to:
|
|
2980
|
-
data
|
|
3276
|
+
description: `[${this.protocolName}] Claim rewards for NFT #${tokenId}`,
|
|
3277
|
+
to: this.gaugeManager,
|
|
3278
|
+
data: encodeFunctionData8({
|
|
3279
|
+
abi: gaugeManagerAbi,
|
|
3280
|
+
functionName: "claimRewards",
|
|
3281
|
+
args: [gauge, [tokenId], 1]
|
|
3282
|
+
// redeemType=1
|
|
3283
|
+
}),
|
|
2981
3284
|
value: 0n,
|
|
2982
|
-
gas_estimate:
|
|
3285
|
+
gas_estimate: 1e6
|
|
2983
3286
|
};
|
|
2984
3287
|
}
|
|
2985
|
-
|
|
2986
|
-
|
|
3288
|
+
// ─── Pending Rewards ──────────────────────────────────────────
|
|
3289
|
+
async getPendingRewards(gauge, _user) {
|
|
3290
|
+
throw DefiError.unsupported(`[${this.protocolName}] Use getPendingRewardsByTokenId for CL gauges`);
|
|
2987
3291
|
}
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
const
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
3292
|
+
async getPendingRewardsByTokenId(gauge, tokenId) {
|
|
3293
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC required");
|
|
3294
|
+
const client = createPublicClient5({ transport: http5(this.rpcUrl) });
|
|
3295
|
+
return await client.readContract({
|
|
3296
|
+
address: gauge,
|
|
3297
|
+
abi: gaugeCLAbi,
|
|
3298
|
+
functionName: "earned",
|
|
3299
|
+
args: [tokenId]
|
|
2994
3300
|
});
|
|
3301
|
+
}
|
|
3302
|
+
// ─── VoteEscrow ──────────────────────────────────────────────
|
|
3303
|
+
async buildCreateLock(amount, lockDuration) {
|
|
2995
3304
|
return {
|
|
2996
|
-
description: `[${this.protocolName}] Create veNFT lock
|
|
3305
|
+
description: `[${this.protocolName}] Create veNFT lock`,
|
|
2997
3306
|
to: this.veToken,
|
|
2998
|
-
data,
|
|
3307
|
+
data: encodeFunctionData8({ abi: veAbi, functionName: "create_lock", args: [amount, BigInt(lockDuration)] }),
|
|
2999
3308
|
value: 0n,
|
|
3000
3309
|
gas_estimate: 3e5
|
|
3001
3310
|
};
|
|
3002
3311
|
}
|
|
3003
3312
|
async buildIncreaseAmount(tokenId, amount) {
|
|
3004
|
-
const data = encodeFunctionData8({
|
|
3005
|
-
abi: veAbi,
|
|
3006
|
-
functionName: "increase_amount",
|
|
3007
|
-
args: [tokenId, amount]
|
|
3008
|
-
});
|
|
3009
3313
|
return {
|
|
3010
|
-
description: `[${this.protocolName}] Increase veNFT #${tokenId}
|
|
3314
|
+
description: `[${this.protocolName}] Increase veNFT #${tokenId}`,
|
|
3011
3315
|
to: this.veToken,
|
|
3012
|
-
data,
|
|
3316
|
+
data: encodeFunctionData8({ abi: veAbi, functionName: "increase_amount", args: [tokenId, amount] }),
|
|
3013
3317
|
value: 0n,
|
|
3014
3318
|
gas_estimate: 2e5
|
|
3015
3319
|
};
|
|
3016
3320
|
}
|
|
3017
3321
|
async buildIncreaseUnlockTime(tokenId, lockDuration) {
|
|
3018
|
-
const data = encodeFunctionData8({
|
|
3019
|
-
abi: veAbi,
|
|
3020
|
-
functionName: "increase_unlock_time",
|
|
3021
|
-
args: [tokenId, BigInt(lockDuration)]
|
|
3022
|
-
});
|
|
3023
3322
|
return {
|
|
3024
|
-
description: `[${this.protocolName}] Extend veNFT #${tokenId} lock
|
|
3323
|
+
description: `[${this.protocolName}] Extend veNFT #${tokenId} lock`,
|
|
3324
|
+
to: this.veToken,
|
|
3325
|
+
data: encodeFunctionData8({ abi: veAbi, functionName: "increase_unlock_time", args: [tokenId, BigInt(lockDuration)] }),
|
|
3326
|
+
value: 0n,
|
|
3327
|
+
gas_estimate: 2e5
|
|
3328
|
+
};
|
|
3329
|
+
}
|
|
3330
|
+
async buildWithdrawExpired(tokenId) {
|
|
3331
|
+
return {
|
|
3332
|
+
description: `[${this.protocolName}] Withdraw expired veNFT #${tokenId}`,
|
|
3333
|
+
to: this.veToken,
|
|
3334
|
+
data: encodeFunctionData8({ abi: veAbi, functionName: "withdraw", args: [tokenId] }),
|
|
3335
|
+
value: 0n,
|
|
3336
|
+
gas_estimate: 2e5
|
|
3337
|
+
};
|
|
3338
|
+
}
|
|
3339
|
+
// ─── Voter ──────────────────────────────────────────────────
|
|
3340
|
+
async buildVote(tokenId, pools, weights) {
|
|
3341
|
+
return {
|
|
3342
|
+
description: `[${this.protocolName}] Vote with veNFT #${tokenId}`,
|
|
3343
|
+
to: this.voter,
|
|
3344
|
+
data: encodeFunctionData8({ abi: voterAbi, functionName: "vote", args: [tokenId, pools, weights] }),
|
|
3345
|
+
value: 0n,
|
|
3346
|
+
gas_estimate: 5e5
|
|
3347
|
+
};
|
|
3348
|
+
}
|
|
3349
|
+
async buildClaimBribes(bribes, tokenId) {
|
|
3350
|
+
const tokensPerBribe = bribes.map(() => []);
|
|
3351
|
+
return {
|
|
3352
|
+
description: `[${this.protocolName}] Claim bribes for veNFT #${tokenId}`,
|
|
3353
|
+
to: this.voter,
|
|
3354
|
+
data: encodeFunctionData8({ abi: voterAbi, functionName: "claimBribes", args: [bribes, tokensPerBribe, tokenId] }),
|
|
3355
|
+
value: 0n,
|
|
3356
|
+
gas_estimate: 3e5
|
|
3357
|
+
};
|
|
3358
|
+
}
|
|
3359
|
+
async buildClaimFees(fees, tokenId) {
|
|
3360
|
+
const tokensPerFee = fees.map(() => []);
|
|
3361
|
+
return {
|
|
3362
|
+
description: `[${this.protocolName}] Claim fees for veNFT #${tokenId}`,
|
|
3363
|
+
to: this.voter,
|
|
3364
|
+
data: encodeFunctionData8({ abi: voterAbi, functionName: "claimFees", args: [fees, tokensPerFee, tokenId] }),
|
|
3365
|
+
value: 0n,
|
|
3366
|
+
gas_estimate: 3e5
|
|
3367
|
+
};
|
|
3368
|
+
}
|
|
3369
|
+
};
|
|
3370
|
+
var abi5 = parseAbi9([
|
|
3371
|
+
"function swap(address fromToken, address toToken, uint256 fromAmount, uint256 minToAmount, address to, address rebateTo) external payable returns (uint256 realToAmount)"
|
|
3372
|
+
]);
|
|
3373
|
+
var WooFiAdapter = class {
|
|
3374
|
+
protocolName;
|
|
3375
|
+
router;
|
|
3376
|
+
constructor(entry, _rpcUrl) {
|
|
3377
|
+
this.protocolName = entry.name;
|
|
3378
|
+
const router = entry.contracts?.["router"];
|
|
3379
|
+
if (!router) {
|
|
3380
|
+
throw new DefiError("CONTRACT_ERROR", "Missing 'router' contract");
|
|
3381
|
+
}
|
|
3382
|
+
this.router = router;
|
|
3383
|
+
}
|
|
3384
|
+
name() {
|
|
3385
|
+
return this.protocolName;
|
|
3386
|
+
}
|
|
3387
|
+
async buildSwap(params) {
|
|
3388
|
+
const minToAmount = 0n;
|
|
3389
|
+
const data = encodeFunctionData9({
|
|
3390
|
+
abi: abi5,
|
|
3391
|
+
functionName: "swap",
|
|
3392
|
+
args: [
|
|
3393
|
+
params.token_in,
|
|
3394
|
+
params.token_out,
|
|
3395
|
+
params.amount_in,
|
|
3396
|
+
minToAmount,
|
|
3397
|
+
params.recipient,
|
|
3398
|
+
zeroAddress5
|
|
3399
|
+
]
|
|
3400
|
+
});
|
|
3401
|
+
return {
|
|
3402
|
+
description: `[${this.protocolName}] Swap ${params.amount_in} via WOOFi`,
|
|
3403
|
+
to: this.router,
|
|
3404
|
+
data,
|
|
3405
|
+
value: 0n,
|
|
3406
|
+
gas_estimate: 2e5
|
|
3407
|
+
};
|
|
3408
|
+
}
|
|
3409
|
+
async quote(_params) {
|
|
3410
|
+
throw DefiError.unsupported(`[${this.protocolName}] quote requires RPC`);
|
|
3411
|
+
}
|
|
3412
|
+
async buildAddLiquidity(_params) {
|
|
3413
|
+
throw DefiError.unsupported(`[${this.protocolName}] WOOFi does not support LP positions via router`);
|
|
3414
|
+
}
|
|
3415
|
+
async buildRemoveLiquidity(_params) {
|
|
3416
|
+
throw DefiError.unsupported(`[${this.protocolName}] WOOFi does not support LP positions via router`);
|
|
3417
|
+
}
|
|
3418
|
+
};
|
|
3419
|
+
var gaugeAbi = parseAbi10([
|
|
3420
|
+
"function deposit(uint256 amount) external",
|
|
3421
|
+
"function depositFor(uint256 amount, uint256 tokenId) external",
|
|
3422
|
+
"function withdraw(uint256 amount) external",
|
|
3423
|
+
"function getReward() external",
|
|
3424
|
+
"function getReward(address account) external",
|
|
3425
|
+
"function getReward(address account, address[] tokens) external",
|
|
3426
|
+
"function getReward(uint256 tokenId) external",
|
|
3427
|
+
"function earned(address account) external view returns (uint256)",
|
|
3428
|
+
"function earned(address token, address account) external view returns (uint256)",
|
|
3429
|
+
"function earned(uint256 tokenId) external view returns (uint256)",
|
|
3430
|
+
"function rewardRate() external view returns (uint256)",
|
|
3431
|
+
"function rewardToken() external view returns (address)",
|
|
3432
|
+
"function totalSupply() external view returns (uint256)",
|
|
3433
|
+
"function rewardsListLength() external view returns (uint256)",
|
|
3434
|
+
"function rewardData(address token) external view returns (uint256 periodFinish, uint256 rewardRate, uint256 lastUpdateTime, uint256 rewardPerTokenStored)",
|
|
3435
|
+
"function nonfungiblePositionManager() external view returns (address)"
|
|
3436
|
+
]);
|
|
3437
|
+
var veAbi2 = parseAbi10([
|
|
3438
|
+
"function create_lock(uint256 value, uint256 lock_duration) external returns (uint256)",
|
|
3439
|
+
"function increase_amount(uint256 tokenId, uint256 value) external",
|
|
3440
|
+
"function increase_unlock_time(uint256 tokenId, uint256 lock_duration) external",
|
|
3441
|
+
"function withdraw(uint256 tokenId) external",
|
|
3442
|
+
"function balanceOfNFT(uint256 tokenId) external view returns (uint256)",
|
|
3443
|
+
"function locked(uint256 tokenId) external view returns (uint256 amount, uint256 end)"
|
|
3444
|
+
]);
|
|
3445
|
+
var voterAbi2 = parseAbi10([
|
|
3446
|
+
"function vote(uint256 tokenId, address[] calldata pools, uint256[] calldata weights) external",
|
|
3447
|
+
"function claimBribes(address[] calldata bribes, address[][] calldata tokens, uint256 tokenId) external",
|
|
3448
|
+
"function claimFees(address[] calldata fees, address[][] calldata tokens, uint256 tokenId) external",
|
|
3449
|
+
"function gauges(address pool) external view returns (address)",
|
|
3450
|
+
"function gaugeForPool(address pool) external view returns (address)",
|
|
3451
|
+
"function poolToGauge(address pool) external view returns (address)"
|
|
3452
|
+
]);
|
|
3453
|
+
var _addressDecodeAbi2 = parseAbi10(["function f() external view returns (address)"]);
|
|
3454
|
+
function decodeAddress2(data) {
|
|
3455
|
+
if (!data) return null;
|
|
3456
|
+
try {
|
|
3457
|
+
return decodeFunctionResult3({ abi: _addressDecodeAbi2, functionName: "f", data });
|
|
3458
|
+
} catch {
|
|
3459
|
+
return null;
|
|
3460
|
+
}
|
|
3461
|
+
}
|
|
3462
|
+
var _symbolDecodeAbi2 = parseAbi10(["function symbol() external view returns (string)"]);
|
|
3463
|
+
function decodeSymbol2(data) {
|
|
3464
|
+
if (!data) return "?";
|
|
3465
|
+
try {
|
|
3466
|
+
return decodeFunctionResult3({ abi: _symbolDecodeAbi2, functionName: "symbol", data });
|
|
3467
|
+
} catch {
|
|
3468
|
+
return "?";
|
|
3469
|
+
}
|
|
3470
|
+
}
|
|
3471
|
+
var _boolDecodeAbi = parseAbi10(["function f() external view returns (bool)"]);
|
|
3472
|
+
function decodeBoolean(data) {
|
|
3473
|
+
try {
|
|
3474
|
+
return decodeFunctionResult3({ abi: _boolDecodeAbi, functionName: "f", data });
|
|
3475
|
+
} catch {
|
|
3476
|
+
return false;
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
var HYPEREVM_TOKENS = {
|
|
3480
|
+
WHYPE: "0x5555555555555555555555555555555555555555",
|
|
3481
|
+
USDC: "0xb88339CB7199b77E23DB6E890353E22632Ba630f",
|
|
3482
|
+
USDT0: "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
|
|
3483
|
+
UETH: "0xBe6727B535545C67d5cAa73dEa54865B92CF7907",
|
|
3484
|
+
UBTC: "0x9FDBdA0A5e284c32744D2f17Ee5c74B284993463",
|
|
3485
|
+
USDH: "0x111111a1a0667d36bD57c0A9f569b98057111111",
|
|
3486
|
+
USDe: "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34",
|
|
3487
|
+
sUSDe: "0x211Cc4DD073734dA055fbF44a2b4667d5E5fE5d2",
|
|
3488
|
+
XAUt0: "0xf4D9235269a96aaDaFc9aDAe454a0618eBE37949",
|
|
3489
|
+
kHYPE: "0xfD739d4e423301CE9385c1fb8850539D657C296D",
|
|
3490
|
+
RAM: "0x555570a286F15EbDFE42B66eDE2f724Aa1AB5555",
|
|
3491
|
+
hyperRAM: "0xAAAE8378809bb8815c08D3C59Eb0c7D1529aD769"
|
|
3492
|
+
};
|
|
3493
|
+
var CL_TICK_SPACINGS = [1, 5, 10, 50, 100, 200];
|
|
3494
|
+
var SolidlyGaugeAdapter = class {
|
|
3495
|
+
protocolName;
|
|
3496
|
+
voter;
|
|
3497
|
+
veToken;
|
|
3498
|
+
rpcUrl;
|
|
3499
|
+
clFactory;
|
|
3500
|
+
v2Factory;
|
|
3501
|
+
constructor(entry, rpcUrl) {
|
|
3502
|
+
this.protocolName = entry.name;
|
|
3503
|
+
const voter = entry.contracts?.["voter"];
|
|
3504
|
+
if (!voter) {
|
|
3505
|
+
throw new DefiError("CONTRACT_ERROR", "Missing 'voter' contract");
|
|
3506
|
+
}
|
|
3507
|
+
const veToken = entry.contracts?.["ve_token"];
|
|
3508
|
+
if (!veToken) {
|
|
3509
|
+
throw new DefiError("CONTRACT_ERROR", "Missing 've_token' contract");
|
|
3510
|
+
}
|
|
3511
|
+
this.voter = voter;
|
|
3512
|
+
this.veToken = veToken;
|
|
3513
|
+
this.rpcUrl = rpcUrl;
|
|
3514
|
+
this.clFactory = entry.contracts?.["cl_factory"] ?? entry.contracts?.["factory"];
|
|
3515
|
+
this.v2Factory = entry.contracts?.["pair_factory"] ?? entry.contracts?.["factory"];
|
|
3516
|
+
}
|
|
3517
|
+
name() {
|
|
3518
|
+
return this.protocolName;
|
|
3519
|
+
}
|
|
3520
|
+
/** Scan V2 and CL factories for pools that have active emission gauges. */
|
|
3521
|
+
async discoverGaugedPools() {
|
|
3522
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC URL required for gauge discovery");
|
|
3523
|
+
const results = [];
|
|
3524
|
+
await Promise.all([
|
|
3525
|
+
this._discoverV2GaugedPools(results),
|
|
3526
|
+
this._discoverCLGaugedPools(results)
|
|
3527
|
+
]);
|
|
3528
|
+
return results;
|
|
3529
|
+
}
|
|
3530
|
+
async _discoverV2GaugedPools(out) {
|
|
3531
|
+
if (!this.rpcUrl || !this.v2Factory) return;
|
|
3532
|
+
const v2FactoryAbi = parseAbi10([
|
|
3533
|
+
"function allPairsLength() external view returns (uint256)",
|
|
3534
|
+
"function allPairs(uint256) external view returns (address)"
|
|
3535
|
+
]);
|
|
3536
|
+
const pairAbi = parseAbi10([
|
|
3537
|
+
"function token0() external view returns (address)",
|
|
3538
|
+
"function token1() external view returns (address)",
|
|
3539
|
+
"function stable() external view returns (bool)"
|
|
3540
|
+
]);
|
|
3541
|
+
const erc20SymbolAbi = parseAbi10(["function symbol() external view returns (string)"]);
|
|
3542
|
+
const client = createPublicClient6({ transport: http6(this.rpcUrl) });
|
|
3543
|
+
let pairCount;
|
|
3544
|
+
try {
|
|
3545
|
+
pairCount = await client.readContract({
|
|
3546
|
+
address: this.v2Factory,
|
|
3547
|
+
abi: v2FactoryAbi,
|
|
3548
|
+
functionName: "allPairsLength"
|
|
3549
|
+
});
|
|
3550
|
+
} catch {
|
|
3551
|
+
return;
|
|
3552
|
+
}
|
|
3553
|
+
const count = Number(pairCount);
|
|
3554
|
+
if (count === 0) return;
|
|
3555
|
+
const pairAddressCalls = [];
|
|
3556
|
+
for (let i = 0; i < count; i++) {
|
|
3557
|
+
pairAddressCalls.push([
|
|
3558
|
+
this.v2Factory,
|
|
3559
|
+
encodeFunctionData10({ abi: v2FactoryAbi, functionName: "allPairs", args: [BigInt(i)] })
|
|
3560
|
+
]);
|
|
3561
|
+
}
|
|
3562
|
+
const pairAddressResults = await multicallRead(this.rpcUrl, pairAddressCalls);
|
|
3563
|
+
const pairs = pairAddressResults.map((r) => decodeAddress2(r)).filter((a) => a !== null && a !== zeroAddress6);
|
|
3564
|
+
if (pairs.length === 0) return;
|
|
3565
|
+
const gaugeForPoolAbi = parseAbi10(["function gaugeForPool(address) external view returns (address)"]);
|
|
3566
|
+
const poolToGaugeAbi = parseAbi10(["function poolToGauge(address) external view returns (address)"]);
|
|
3567
|
+
const gaugeCalls = pairs.map((pair) => [
|
|
3568
|
+
this.voter,
|
|
3569
|
+
encodeFunctionData10({ abi: gaugeForPoolAbi, functionName: "gaugeForPool", args: [pair] })
|
|
3570
|
+
]);
|
|
3571
|
+
let gaugeResults = await multicallRead(this.rpcUrl, gaugeCalls);
|
|
3572
|
+
const allNullV2 = gaugeResults.every((r) => !r || decodeAddress2(r) === zeroAddress6 || decodeAddress2(r) === null);
|
|
3573
|
+
if (allNullV2) {
|
|
3574
|
+
const fallbackCalls = pairs.map((pair) => [
|
|
3575
|
+
this.voter,
|
|
3576
|
+
encodeFunctionData10({ abi: poolToGaugeAbi, functionName: "poolToGauge", args: [pair] })
|
|
3577
|
+
]);
|
|
3578
|
+
gaugeResults = await multicallRead(this.rpcUrl, fallbackCalls);
|
|
3579
|
+
}
|
|
3580
|
+
const gaugedPairs = [];
|
|
3581
|
+
for (let i = 0; i < pairs.length; i++) {
|
|
3582
|
+
const gauge = decodeAddress2(gaugeResults[i] ?? null);
|
|
3583
|
+
if (gauge && gauge !== zeroAddress6) {
|
|
3584
|
+
gaugedPairs.push({ pair: pairs[i], gauge });
|
|
3585
|
+
}
|
|
3586
|
+
}
|
|
3587
|
+
if (gaugedPairs.length === 0) return;
|
|
3588
|
+
const metaCalls = [];
|
|
3589
|
+
for (const { pair } of gaugedPairs) {
|
|
3590
|
+
metaCalls.push([pair, encodeFunctionData10({ abi: pairAbi, functionName: "token0" })]);
|
|
3591
|
+
metaCalls.push([pair, encodeFunctionData10({ abi: pairAbi, functionName: "token1" })]);
|
|
3592
|
+
metaCalls.push([pair, encodeFunctionData10({ abi: pairAbi, functionName: "stable" })]);
|
|
3593
|
+
}
|
|
3594
|
+
const metaResults = await multicallRead(this.rpcUrl, metaCalls);
|
|
3595
|
+
const tokenAddrs = /* @__PURE__ */ new Set();
|
|
3596
|
+
for (let i = 0; i < gaugedPairs.length; i++) {
|
|
3597
|
+
const t0 = decodeAddress2(metaResults[i * 3] ?? null);
|
|
3598
|
+
const t1 = decodeAddress2(metaResults[i * 3 + 1] ?? null);
|
|
3599
|
+
if (t0 && t0 !== zeroAddress6) tokenAddrs.add(t0);
|
|
3600
|
+
if (t1 && t1 !== zeroAddress6) tokenAddrs.add(t1);
|
|
3601
|
+
}
|
|
3602
|
+
const uniqueTokens = Array.from(tokenAddrs);
|
|
3603
|
+
const symbolCalls = uniqueTokens.map((t) => [
|
|
3604
|
+
t,
|
|
3605
|
+
encodeFunctionData10({ abi: erc20SymbolAbi, functionName: "symbol" })
|
|
3606
|
+
]);
|
|
3607
|
+
const symbolResults = await multicallRead(this.rpcUrl, symbolCalls);
|
|
3608
|
+
const symbolMap = /* @__PURE__ */ new Map();
|
|
3609
|
+
for (let i = 0; i < uniqueTokens.length; i++) {
|
|
3610
|
+
symbolMap.set(uniqueTokens[i], decodeSymbol2(symbolResults[i] ?? null));
|
|
3611
|
+
}
|
|
3612
|
+
for (let i = 0; i < gaugedPairs.length; i++) {
|
|
3613
|
+
const { pair, gauge } = gaugedPairs[i];
|
|
3614
|
+
const t0 = decodeAddress2(metaResults[i * 3] ?? null);
|
|
3615
|
+
const t1 = decodeAddress2(metaResults[i * 3 + 1] ?? null);
|
|
3616
|
+
const stableRaw = metaResults[i * 3 + 2];
|
|
3617
|
+
const stable = stableRaw ? decodeBoolean(stableRaw) : false;
|
|
3618
|
+
out.push({
|
|
3619
|
+
pool: pair,
|
|
3620
|
+
gauge,
|
|
3621
|
+
token0: t0 ? symbolMap.get(t0) ?? t0.slice(0, 10) : "?",
|
|
3622
|
+
token1: t1 ? symbolMap.get(t1) ?? t1.slice(0, 10) : "?",
|
|
3623
|
+
type: "V2",
|
|
3624
|
+
stable
|
|
3625
|
+
});
|
|
3626
|
+
}
|
|
3627
|
+
}
|
|
3628
|
+
async _discoverCLGaugedPools(out) {
|
|
3629
|
+
if (!this.rpcUrl || !this.clFactory) return;
|
|
3630
|
+
const clFactoryAbi = parseAbi10([
|
|
3631
|
+
"function getPool(address tokenA, address tokenB, int24 tickSpacing) external view returns (address pool)"
|
|
3632
|
+
]);
|
|
3633
|
+
const algebraFactoryAbi2 = parseAbi10([
|
|
3634
|
+
"function poolByPair(address tokenA, address tokenB) external view returns (address pool)"
|
|
3635
|
+
]);
|
|
3636
|
+
const poolAbi2 = parseAbi10([
|
|
3637
|
+
"function token0() external view returns (address)",
|
|
3638
|
+
"function token1() external view returns (address)"
|
|
3639
|
+
]);
|
|
3640
|
+
const erc20SymbolAbi = parseAbi10(["function symbol() external view returns (string)"]);
|
|
3641
|
+
const gaugeForPoolAbi = parseAbi10(["function gaugeForPool(address) external view returns (address)"]);
|
|
3642
|
+
const poolToGaugeAbi = parseAbi10(["function poolToGauge(address) external view returns (address)"]);
|
|
3643
|
+
const tokenEntries = Object.entries(HYPEREVM_TOKENS);
|
|
3644
|
+
const tokenAddresses = tokenEntries.map(([, addr]) => addr);
|
|
3645
|
+
const pairs = [];
|
|
3646
|
+
for (let i = 0; i < tokenAddresses.length; i++) {
|
|
3647
|
+
for (let j = i + 1; j < tokenAddresses.length; j++) {
|
|
3648
|
+
pairs.push([tokenAddresses[i], tokenAddresses[j]]);
|
|
3649
|
+
}
|
|
3650
|
+
}
|
|
3651
|
+
const isAlgebra = await (async () => {
|
|
3652
|
+
try {
|
|
3653
|
+
const [result] = await multicallRead(this.rpcUrl, [[
|
|
3654
|
+
this.clFactory,
|
|
3655
|
+
encodeFunctionData10({ abi: algebraFactoryAbi2, functionName: "poolByPair", args: [tokenAddresses[0], tokenAddresses[1]] })
|
|
3656
|
+
]]);
|
|
3657
|
+
return result !== null && result.length >= 66;
|
|
3658
|
+
} catch {
|
|
3659
|
+
return false;
|
|
3660
|
+
}
|
|
3661
|
+
})();
|
|
3662
|
+
const getPoolCalls = [];
|
|
3663
|
+
const callMeta = [];
|
|
3664
|
+
if (isAlgebra) {
|
|
3665
|
+
for (let p = 0; p < pairs.length; p++) {
|
|
3666
|
+
const [tokenA, tokenB] = pairs[p];
|
|
3667
|
+
getPoolCalls.push([
|
|
3668
|
+
this.clFactory,
|
|
3669
|
+
encodeFunctionData10({ abi: algebraFactoryAbi2, functionName: "poolByPair", args: [tokenA, tokenB] })
|
|
3670
|
+
]);
|
|
3671
|
+
callMeta.push({ pairIdx: p, tickSpacing: 0 });
|
|
3672
|
+
}
|
|
3673
|
+
} else {
|
|
3674
|
+
for (let p = 0; p < pairs.length; p++) {
|
|
3675
|
+
const [tokenA, tokenB] = pairs[p];
|
|
3676
|
+
for (const ts of CL_TICK_SPACINGS) {
|
|
3677
|
+
getPoolCalls.push([
|
|
3678
|
+
this.clFactory,
|
|
3679
|
+
encodeFunctionData10({ abi: clFactoryAbi, functionName: "getPool", args: [tokenA, tokenB, ts] })
|
|
3680
|
+
]);
|
|
3681
|
+
callMeta.push({ pairIdx: p, tickSpacing: ts });
|
|
3682
|
+
}
|
|
3683
|
+
}
|
|
3684
|
+
}
|
|
3685
|
+
const getPoolResults = await multicallRead(this.rpcUrl, getPoolCalls);
|
|
3686
|
+
const candidatePools = [];
|
|
3687
|
+
for (let i = 0; i < getPoolCalls.length; i++) {
|
|
3688
|
+
const pool = decodeAddress2(getPoolResults[i] ?? null);
|
|
3689
|
+
if (pool && pool !== zeroAddress6) {
|
|
3690
|
+
const { pairIdx, tickSpacing } = callMeta[i];
|
|
3691
|
+
const [tokenA, tokenB] = pairs[pairIdx];
|
|
3692
|
+
candidatePools.push({ pool, tokenA, tokenB, tickSpacing });
|
|
3693
|
+
}
|
|
3694
|
+
}
|
|
3695
|
+
if (candidatePools.length === 0) return;
|
|
3696
|
+
const gaugeCalls = candidatePools.map(({ pool }) => [
|
|
3697
|
+
this.voter,
|
|
3698
|
+
encodeFunctionData10({ abi: gaugeForPoolAbi, functionName: "gaugeForPool", args: [pool] })
|
|
3699
|
+
]);
|
|
3700
|
+
let gaugeResults = await multicallRead(this.rpcUrl, gaugeCalls);
|
|
3701
|
+
const allNull = gaugeResults.every((r) => !r || decodeAddress2(r) === zeroAddress6 || decodeAddress2(r) === null);
|
|
3702
|
+
if (allNull) {
|
|
3703
|
+
const fallbackCalls = candidatePools.map(({ pool }) => [
|
|
3704
|
+
this.voter,
|
|
3705
|
+
encodeFunctionData10({ abi: poolToGaugeAbi, functionName: "poolToGauge", args: [pool] })
|
|
3706
|
+
]);
|
|
3707
|
+
gaugeResults = await multicallRead(this.rpcUrl, fallbackCalls);
|
|
3708
|
+
}
|
|
3709
|
+
const gaugedCL = [];
|
|
3710
|
+
for (let i = 0; i < candidatePools.length; i++) {
|
|
3711
|
+
const gauge = decodeAddress2(gaugeResults[i] ?? null);
|
|
3712
|
+
if (gauge && gauge !== zeroAddress6) {
|
|
3713
|
+
gaugedCL.push({ ...candidatePools[i], gauge });
|
|
3714
|
+
}
|
|
3715
|
+
}
|
|
3716
|
+
if (gaugedCL.length === 0) return;
|
|
3717
|
+
const tokenAddrsInPools = /* @__PURE__ */ new Set();
|
|
3718
|
+
for (const { tokenA, tokenB } of gaugedCL) {
|
|
3719
|
+
tokenAddrsInPools.add(tokenA);
|
|
3720
|
+
tokenAddrsInPools.add(tokenB);
|
|
3721
|
+
}
|
|
3722
|
+
const uniqueTokens = Array.from(tokenAddrsInPools);
|
|
3723
|
+
const symbolCalls = uniqueTokens.map((t) => [
|
|
3724
|
+
t,
|
|
3725
|
+
encodeFunctionData10({ abi: erc20SymbolAbi, functionName: "symbol" })
|
|
3726
|
+
]);
|
|
3727
|
+
const symbolResults = await multicallRead(this.rpcUrl, symbolCalls);
|
|
3728
|
+
const symbolMap = /* @__PURE__ */ new Map();
|
|
3729
|
+
for (let i = 0; i < uniqueTokens.length; i++) {
|
|
3730
|
+
symbolMap.set(uniqueTokens[i], decodeSymbol2(symbolResults[i] ?? null));
|
|
3731
|
+
}
|
|
3732
|
+
const poolTokenCalls = [];
|
|
3733
|
+
for (const { pool } of gaugedCL) {
|
|
3734
|
+
poolTokenCalls.push([pool, encodeFunctionData10({ abi: poolAbi2, functionName: "token0" })]);
|
|
3735
|
+
poolTokenCalls.push([pool, encodeFunctionData10({ abi: poolAbi2, functionName: "token1" })]);
|
|
3736
|
+
}
|
|
3737
|
+
const poolTokenResults = await multicallRead(this.rpcUrl, poolTokenCalls);
|
|
3738
|
+
for (let i = 0; i < gaugedCL.length; i++) {
|
|
3739
|
+
const { pool, gauge, tokenA, tokenB, tickSpacing } = gaugedCL[i];
|
|
3740
|
+
const rawT0 = decodeAddress2(poolTokenResults[i * 2] ?? null);
|
|
3741
|
+
const rawT1 = decodeAddress2(poolTokenResults[i * 2 + 1] ?? null);
|
|
3742
|
+
const t0 = rawT0 && rawT0 !== zeroAddress6 ? rawT0 : tokenA;
|
|
3743
|
+
const t1 = rawT1 && rawT1 !== zeroAddress6 ? rawT1 : tokenB;
|
|
3744
|
+
out.push({
|
|
3745
|
+
pool,
|
|
3746
|
+
gauge,
|
|
3747
|
+
token0: symbolMap.get(t0) ?? t0.slice(0, 10),
|
|
3748
|
+
token1: symbolMap.get(t1) ?? t1.slice(0, 10),
|
|
3749
|
+
type: "CL",
|
|
3750
|
+
tickSpacing
|
|
3751
|
+
});
|
|
3752
|
+
}
|
|
3753
|
+
}
|
|
3754
|
+
// IGauge
|
|
3755
|
+
async buildDeposit(gauge, amount, tokenId, lpToken) {
|
|
3756
|
+
if (tokenId !== void 0) {
|
|
3757
|
+
const data2 = encodeFunctionData10({
|
|
3758
|
+
abi: gaugeAbi,
|
|
3759
|
+
functionName: "depositFor",
|
|
3760
|
+
args: [amount, tokenId]
|
|
3761
|
+
});
|
|
3762
|
+
return {
|
|
3763
|
+
description: `[${this.protocolName}] Deposit ${amount} LP to gauge (boost veNFT #${tokenId})`,
|
|
3764
|
+
to: gauge,
|
|
3765
|
+
data: data2,
|
|
3766
|
+
value: 0n,
|
|
3767
|
+
gas_estimate: 2e5,
|
|
3768
|
+
approvals: lpToken ? [{ token: lpToken, spender: gauge, amount }] : void 0
|
|
3769
|
+
};
|
|
3770
|
+
}
|
|
3771
|
+
const data = encodeFunctionData10({
|
|
3772
|
+
abi: gaugeAbi,
|
|
3773
|
+
functionName: "deposit",
|
|
3774
|
+
args: [amount]
|
|
3775
|
+
});
|
|
3776
|
+
return {
|
|
3777
|
+
description: `[${this.protocolName}] Deposit ${amount} LP to gauge`,
|
|
3778
|
+
to: gauge,
|
|
3779
|
+
data,
|
|
3780
|
+
value: 0n,
|
|
3781
|
+
gas_estimate: 2e5,
|
|
3782
|
+
approvals: lpToken ? [{ token: lpToken, spender: gauge, amount }] : void 0
|
|
3783
|
+
};
|
|
3784
|
+
}
|
|
3785
|
+
async buildWithdraw(gauge, amount) {
|
|
3786
|
+
const data = encodeFunctionData10({
|
|
3787
|
+
abi: gaugeAbi,
|
|
3788
|
+
functionName: "withdraw",
|
|
3789
|
+
args: [amount]
|
|
3790
|
+
});
|
|
3791
|
+
return {
|
|
3792
|
+
description: `[${this.protocolName}] Withdraw ${amount} LP from gauge`,
|
|
3793
|
+
to: gauge,
|
|
3794
|
+
data,
|
|
3795
|
+
value: 0n,
|
|
3796
|
+
gas_estimate: 2e5
|
|
3797
|
+
};
|
|
3798
|
+
}
|
|
3799
|
+
/**
|
|
3800
|
+
* Resolve gauge address from a pool address via voter contract.
|
|
3801
|
+
* Tries gaugeForPool (Ramses), poolToGauge (NEST), gauges (classic Solidly).
|
|
3802
|
+
*/
|
|
3803
|
+
async resolveGauge(pool) {
|
|
3804
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC URL required for gauge lookup");
|
|
3805
|
+
const client = createPublicClient6({ transport: http6(this.rpcUrl) });
|
|
3806
|
+
for (const fn of ["gaugeForPool", "poolToGauge", "gauges"]) {
|
|
3807
|
+
try {
|
|
3808
|
+
const gauge = await client.readContract({
|
|
3809
|
+
address: this.voter,
|
|
3810
|
+
abi: voterAbi2,
|
|
3811
|
+
functionName: fn,
|
|
3812
|
+
args: [pool]
|
|
3813
|
+
});
|
|
3814
|
+
if (gauge !== zeroAddress6) return gauge;
|
|
3815
|
+
} catch {
|
|
3816
|
+
}
|
|
3817
|
+
}
|
|
3818
|
+
throw new DefiError("CONTRACT_ERROR", `[${this.protocolName}] No gauge found for pool ${pool}`);
|
|
3819
|
+
}
|
|
3820
|
+
/**
|
|
3821
|
+
* Discover reward tokens for a gauge.
|
|
3822
|
+
* Returns { tokens, multiToken } where multiToken indicates getReward(account, tokens[]) support.
|
|
3823
|
+
*/
|
|
3824
|
+
async discoverRewardTokens(gauge) {
|
|
3825
|
+
if (!this.rpcUrl) return { tokens: [], multiToken: false };
|
|
3826
|
+
const client = createPublicClient6({ transport: http6(this.rpcUrl) });
|
|
3827
|
+
try {
|
|
3828
|
+
const len = await client.readContract({
|
|
3829
|
+
address: gauge,
|
|
3830
|
+
abi: gaugeAbi,
|
|
3831
|
+
functionName: "rewardsListLength"
|
|
3832
|
+
});
|
|
3833
|
+
if (Number(len) > 0) {
|
|
3834
|
+
const candidates = [
|
|
3835
|
+
"0x5555555555555555555555555555555555555555",
|
|
3836
|
+
// WHYPE
|
|
3837
|
+
"0x555570a286F15EbDFE42B66eDE2f724Aa1AB5555",
|
|
3838
|
+
// xRAM
|
|
3839
|
+
"0x067b0C72aa4C6Bd3BFEFfF443c536DCd6a25a9C8",
|
|
3840
|
+
// HYBR
|
|
3841
|
+
"0x07c57E32a3C29D5659bda1d3EFC2E7BF004E3035"
|
|
3842
|
+
// NEST token
|
|
3843
|
+
];
|
|
3844
|
+
const found = [];
|
|
3845
|
+
for (const token of candidates) {
|
|
3846
|
+
try {
|
|
3847
|
+
const rd = await client.readContract({
|
|
3848
|
+
address: gauge,
|
|
3849
|
+
abi: gaugeAbi,
|
|
3850
|
+
functionName: "rewardData",
|
|
3851
|
+
args: [token]
|
|
3852
|
+
});
|
|
3853
|
+
if (rd[0] > 0n || rd[1] > 0n) found.push(token);
|
|
3854
|
+
} catch {
|
|
3855
|
+
}
|
|
3856
|
+
}
|
|
3857
|
+
if (found.length > 0) return { tokens: found, multiToken: true };
|
|
3858
|
+
return { tokens: [], multiToken: true };
|
|
3859
|
+
}
|
|
3860
|
+
} catch {
|
|
3861
|
+
}
|
|
3862
|
+
try {
|
|
3863
|
+
const rt = await client.readContract({
|
|
3864
|
+
address: gauge,
|
|
3865
|
+
abi: gaugeAbi,
|
|
3866
|
+
functionName: "rewardToken"
|
|
3867
|
+
});
|
|
3868
|
+
if (rt !== zeroAddress6) return { tokens: [rt], multiToken: false };
|
|
3869
|
+
} catch {
|
|
3870
|
+
}
|
|
3871
|
+
return { tokens: [], multiToken: false };
|
|
3872
|
+
}
|
|
3873
|
+
async buildClaimRewards(gauge, account) {
|
|
3874
|
+
if (!this.rpcUrl || !account) {
|
|
3875
|
+
const data2 = encodeFunctionData10({
|
|
3876
|
+
abi: gaugeAbi,
|
|
3877
|
+
functionName: "getReward",
|
|
3878
|
+
args: [account ?? zeroAddress6]
|
|
3879
|
+
});
|
|
3880
|
+
return { description: `[${this.protocolName}] Claim gauge rewards`, to: gauge, data: data2, value: 0n, gas_estimate: 2e5 };
|
|
3881
|
+
}
|
|
3882
|
+
const { tokens, multiToken } = await this.discoverRewardTokens(gauge);
|
|
3883
|
+
if (multiToken && tokens.length > 0) {
|
|
3884
|
+
const data2 = encodeFunctionData10({
|
|
3885
|
+
abi: gaugeAbi,
|
|
3886
|
+
functionName: "getReward",
|
|
3887
|
+
args: [account, tokens]
|
|
3888
|
+
});
|
|
3889
|
+
return {
|
|
3890
|
+
description: `[${this.protocolName}] Claim gauge rewards (${tokens.length} tokens)`,
|
|
3891
|
+
to: gauge,
|
|
3892
|
+
data: data2,
|
|
3893
|
+
value: 0n,
|
|
3894
|
+
gas_estimate: 3e5
|
|
3895
|
+
};
|
|
3896
|
+
}
|
|
3897
|
+
const data = encodeFunctionData10({
|
|
3898
|
+
abi: gaugeAbi,
|
|
3899
|
+
functionName: "getReward",
|
|
3900
|
+
args: []
|
|
3901
|
+
});
|
|
3902
|
+
return {
|
|
3903
|
+
description: `[${this.protocolName}] Claim gauge rewards`,
|
|
3904
|
+
to: gauge,
|
|
3905
|
+
data,
|
|
3906
|
+
value: 0n,
|
|
3907
|
+
gas_estimate: 2e5
|
|
3908
|
+
};
|
|
3909
|
+
}
|
|
3910
|
+
/**
|
|
3911
|
+
* Claim rewards for a CL gauge by NFT tokenId (Hybra V4 style).
|
|
3912
|
+
*/
|
|
3913
|
+
async buildClaimRewardsByTokenId(gauge, tokenId) {
|
|
3914
|
+
const data = encodeFunctionData10({
|
|
3915
|
+
abi: gaugeAbi,
|
|
3916
|
+
functionName: "getReward",
|
|
3917
|
+
args: [tokenId]
|
|
3918
|
+
});
|
|
3919
|
+
return {
|
|
3920
|
+
description: `[${this.protocolName}] Claim gauge rewards for NFT #${tokenId}`,
|
|
3921
|
+
to: gauge,
|
|
3922
|
+
data,
|
|
3923
|
+
value: 0n,
|
|
3924
|
+
gas_estimate: 3e5
|
|
3925
|
+
};
|
|
3926
|
+
}
|
|
3927
|
+
async getPendingRewards(gauge, user) {
|
|
3928
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC URL required");
|
|
3929
|
+
const client = createPublicClient6({ transport: http6(this.rpcUrl) });
|
|
3930
|
+
const results = [];
|
|
3931
|
+
const { tokens, multiToken } = await this.discoverRewardTokens(gauge);
|
|
3932
|
+
if (multiToken && tokens.length > 0) {
|
|
3933
|
+
for (const token of tokens) {
|
|
3934
|
+
try {
|
|
3935
|
+
const earned = await client.readContract({
|
|
3936
|
+
address: gauge,
|
|
3937
|
+
abi: gaugeAbi,
|
|
3938
|
+
functionName: "earned",
|
|
3939
|
+
args: [token, user]
|
|
3940
|
+
});
|
|
3941
|
+
results.push({ token, symbol: token.slice(0, 10), amount: earned });
|
|
3942
|
+
} catch {
|
|
3943
|
+
}
|
|
3944
|
+
}
|
|
3945
|
+
} else if (tokens.length > 0) {
|
|
3946
|
+
try {
|
|
3947
|
+
const earned = await client.readContract({
|
|
3948
|
+
address: gauge,
|
|
3949
|
+
abi: gaugeAbi,
|
|
3950
|
+
functionName: "earned",
|
|
3951
|
+
args: [user]
|
|
3952
|
+
});
|
|
3953
|
+
results.push({ token: tokens[0], symbol: tokens[0].slice(0, 10), amount: earned });
|
|
3954
|
+
} catch {
|
|
3955
|
+
}
|
|
3956
|
+
} else {
|
|
3957
|
+
try {
|
|
3958
|
+
const earned = await client.readContract({
|
|
3959
|
+
address: gauge,
|
|
3960
|
+
abi: gaugeAbi,
|
|
3961
|
+
functionName: "earned",
|
|
3962
|
+
args: [user]
|
|
3963
|
+
});
|
|
3964
|
+
results.push({ token: zeroAddress6, symbol: "unknown", amount: earned });
|
|
3965
|
+
} catch {
|
|
3966
|
+
}
|
|
3967
|
+
}
|
|
3968
|
+
return results;
|
|
3969
|
+
}
|
|
3970
|
+
/**
|
|
3971
|
+
* Get pending rewards for a CL gauge NFT position (Hybra V4 style).
|
|
3972
|
+
*/
|
|
3973
|
+
async getPendingRewardsByTokenId(gauge, tokenId) {
|
|
3974
|
+
if (!this.rpcUrl) throw DefiError.rpcError("RPC URL required");
|
|
3975
|
+
const client = createPublicClient6({ transport: http6(this.rpcUrl) });
|
|
3976
|
+
return await client.readContract({
|
|
3977
|
+
address: gauge,
|
|
3978
|
+
abi: gaugeAbi,
|
|
3979
|
+
functionName: "earned",
|
|
3980
|
+
args: [tokenId]
|
|
3981
|
+
});
|
|
3982
|
+
}
|
|
3983
|
+
// IVoteEscrow
|
|
3984
|
+
async buildCreateLock(amount, lockDuration) {
|
|
3985
|
+
const data = encodeFunctionData10({
|
|
3986
|
+
abi: veAbi2,
|
|
3987
|
+
functionName: "create_lock",
|
|
3988
|
+
args: [amount, BigInt(lockDuration)]
|
|
3989
|
+
});
|
|
3990
|
+
return {
|
|
3991
|
+
description: `[${this.protocolName}] Create veNFT lock: ${amount} tokens for ${lockDuration}s`,
|
|
3992
|
+
to: this.veToken,
|
|
3993
|
+
data,
|
|
3994
|
+
value: 0n,
|
|
3995
|
+
gas_estimate: 3e5
|
|
3996
|
+
};
|
|
3997
|
+
}
|
|
3998
|
+
async buildIncreaseAmount(tokenId, amount) {
|
|
3999
|
+
const data = encodeFunctionData10({
|
|
4000
|
+
abi: veAbi2,
|
|
4001
|
+
functionName: "increase_amount",
|
|
4002
|
+
args: [tokenId, amount]
|
|
4003
|
+
});
|
|
4004
|
+
return {
|
|
4005
|
+
description: `[${this.protocolName}] Increase veNFT #${tokenId} by ${amount}`,
|
|
4006
|
+
to: this.veToken,
|
|
4007
|
+
data,
|
|
4008
|
+
value: 0n,
|
|
4009
|
+
gas_estimate: 2e5
|
|
4010
|
+
};
|
|
4011
|
+
}
|
|
4012
|
+
async buildIncreaseUnlockTime(tokenId, lockDuration) {
|
|
4013
|
+
const data = encodeFunctionData10({
|
|
4014
|
+
abi: veAbi2,
|
|
4015
|
+
functionName: "increase_unlock_time",
|
|
4016
|
+
args: [tokenId, BigInt(lockDuration)]
|
|
4017
|
+
});
|
|
4018
|
+
return {
|
|
4019
|
+
description: `[${this.protocolName}] Extend veNFT #${tokenId} lock by ${lockDuration}s`,
|
|
3025
4020
|
to: this.veToken,
|
|
3026
4021
|
data,
|
|
3027
4022
|
value: 0n,
|
|
@@ -3029,8 +4024,8 @@ var SolidlyGaugeAdapter = class {
|
|
|
3029
4024
|
};
|
|
3030
4025
|
}
|
|
3031
4026
|
async buildWithdrawExpired(tokenId) {
|
|
3032
|
-
const data =
|
|
3033
|
-
abi:
|
|
4027
|
+
const data = encodeFunctionData10({
|
|
4028
|
+
abi: veAbi2,
|
|
3034
4029
|
functionName: "withdraw",
|
|
3035
4030
|
args: [tokenId]
|
|
3036
4031
|
});
|
|
@@ -3044,8 +4039,8 @@ var SolidlyGaugeAdapter = class {
|
|
|
3044
4039
|
}
|
|
3045
4040
|
// IVoter
|
|
3046
4041
|
async buildVote(tokenId, pools, weights) {
|
|
3047
|
-
const data =
|
|
3048
|
-
abi:
|
|
4042
|
+
const data = encodeFunctionData10({
|
|
4043
|
+
abi: voterAbi2,
|
|
3049
4044
|
functionName: "vote",
|
|
3050
4045
|
args: [tokenId, pools, weights]
|
|
3051
4046
|
});
|
|
@@ -3059,8 +4054,8 @@ var SolidlyGaugeAdapter = class {
|
|
|
3059
4054
|
}
|
|
3060
4055
|
async buildClaimBribes(bribes, tokenId) {
|
|
3061
4056
|
const tokensPerBribe = bribes.map(() => []);
|
|
3062
|
-
const data =
|
|
3063
|
-
abi:
|
|
4057
|
+
const data = encodeFunctionData10({
|
|
4058
|
+
abi: voterAbi2,
|
|
3064
4059
|
functionName: "claimBribes",
|
|
3065
4060
|
args: [bribes, tokensPerBribe, tokenId]
|
|
3066
4061
|
});
|
|
@@ -3074,8 +4069,8 @@ var SolidlyGaugeAdapter = class {
|
|
|
3074
4069
|
}
|
|
3075
4070
|
async buildClaimFees(fees, tokenId) {
|
|
3076
4071
|
const tokensPerFee = fees.map(() => []);
|
|
3077
|
-
const data =
|
|
3078
|
-
abi:
|
|
4072
|
+
const data = encodeFunctionData10({
|
|
4073
|
+
abi: voterAbi2,
|
|
3079
4074
|
functionName: "claimFees",
|
|
3080
4075
|
args: [fees, tokensPerFee, tokenId]
|
|
3081
4076
|
});
|
|
@@ -3088,7 +4083,7 @@ var SolidlyGaugeAdapter = class {
|
|
|
3088
4083
|
};
|
|
3089
4084
|
}
|
|
3090
4085
|
};
|
|
3091
|
-
var masterchefAbi =
|
|
4086
|
+
var masterchefAbi = parseAbi11([
|
|
3092
4087
|
"function deposit(uint256 pid, uint256 amount) external",
|
|
3093
4088
|
"function withdraw(uint256 pid, uint256 amount) external",
|
|
3094
4089
|
"function claim(uint256[] calldata pids) external",
|
|
@@ -3119,7 +4114,7 @@ var MasterChefAdapter = class {
|
|
|
3119
4114
|
*/
|
|
3120
4115
|
async buildDeposit(gauge, amount, tokenId) {
|
|
3121
4116
|
const pid = tokenId ?? 0n;
|
|
3122
|
-
const data =
|
|
4117
|
+
const data = encodeFunctionData11({
|
|
3123
4118
|
abi: masterchefAbi,
|
|
3124
4119
|
functionName: "deposit",
|
|
3125
4120
|
args: [pid, amount]
|
|
@@ -3140,7 +4135,7 @@ var MasterChefAdapter = class {
|
|
|
3140
4135
|
*/
|
|
3141
4136
|
async buildWithdraw(gauge, amount) {
|
|
3142
4137
|
const pid = 0n;
|
|
3143
|
-
const data =
|
|
4138
|
+
const data = encodeFunctionData11({
|
|
3144
4139
|
abi: masterchefAbi,
|
|
3145
4140
|
functionName: "withdraw",
|
|
3146
4141
|
args: [pid, amount]
|
|
@@ -3155,7 +4150,7 @@ var MasterChefAdapter = class {
|
|
|
3155
4150
|
}
|
|
3156
4151
|
/** Withdraw LP tokens specifying a pid explicitly (MasterChef extension beyond IGauge). */
|
|
3157
4152
|
async buildWithdrawPid(pid, amount) {
|
|
3158
|
-
const data =
|
|
4153
|
+
const data = encodeFunctionData11({
|
|
3159
4154
|
abi: masterchefAbi,
|
|
3160
4155
|
functionName: "withdraw",
|
|
3161
4156
|
args: [pid, amount]
|
|
@@ -3171,7 +4166,7 @@ var MasterChefAdapter = class {
|
|
|
3171
4166
|
/** Claim pending MOE rewards. IGauge interface provides no pid — defaults to pid=0. */
|
|
3172
4167
|
async buildClaimRewards(gauge) {
|
|
3173
4168
|
const pid = 0n;
|
|
3174
|
-
const data =
|
|
4169
|
+
const data = encodeFunctionData11({
|
|
3175
4170
|
abi: masterchefAbi,
|
|
3176
4171
|
functionName: "claim",
|
|
3177
4172
|
args: [[pid]]
|
|
@@ -3186,7 +4181,7 @@ var MasterChefAdapter = class {
|
|
|
3186
4181
|
}
|
|
3187
4182
|
/** Claim pending MOE rewards for a specific pid (MasterChef extension beyond IGauge). */
|
|
3188
4183
|
async buildClaimRewardsPid(pid) {
|
|
3189
|
-
const data =
|
|
4184
|
+
const data = encodeFunctionData11({
|
|
3190
4185
|
abi: masterchefAbi,
|
|
3191
4186
|
functionName: "claim",
|
|
3192
4187
|
args: [[pid]]
|
|
@@ -3204,7 +4199,7 @@ var MasterChefAdapter = class {
|
|
|
3204
4199
|
if (!this.rpcUrl) {
|
|
3205
4200
|
throw DefiError.unsupported(`[${this.protocolName}] getPendingRewards requires RPC`);
|
|
3206
4201
|
}
|
|
3207
|
-
const client =
|
|
4202
|
+
const client = createPublicClient7({ transport: http7(this.rpcUrl) });
|
|
3208
4203
|
const rewards = await client.readContract({
|
|
3209
4204
|
address: this.masterchef,
|
|
3210
4205
|
abi: masterchefAbi,
|
|
@@ -3218,16 +4213,16 @@ var MasterChefAdapter = class {
|
|
|
3218
4213
|
}));
|
|
3219
4214
|
}
|
|
3220
4215
|
};
|
|
3221
|
-
var lbRouterAbi =
|
|
4216
|
+
var lbRouterAbi = parseAbi12([
|
|
3222
4217
|
"struct LiquidityParameters { address tokenX; address tokenY; uint256 binStep; uint256 amountX; uint256 amountY; uint256 amountXMin; uint256 amountYMin; uint256 activeIdDesired; uint256 idSlippage; int256[] deltaIds; uint256[] distributionX; uint256[] distributionY; address to; address refundTo; uint256 deadline; }",
|
|
3223
4218
|
"function addLiquidity(LiquidityParameters calldata liquidityParameters) external returns (uint256 amountXAdded, uint256 amountYAdded, uint256 amountXLeft, uint256 amountYLeft, uint256[] memory depositIds, uint256[] memory liquidityMinted)",
|
|
3224
4219
|
"function removeLiquidity(address tokenX, address tokenY, uint16 binStep, uint256 amountXMin, uint256 amountYMin, uint256[] memory ids, uint256[] memory amounts, address to, uint256 deadline) external returns (uint256 amountX, uint256 amountY)"
|
|
3225
4220
|
]);
|
|
3226
|
-
var lbFactoryAbi =
|
|
4221
|
+
var lbFactoryAbi = parseAbi12([
|
|
3227
4222
|
"function getNumberOfLBPairs() external view returns (uint256)",
|
|
3228
4223
|
"function getLBPairAtIndex(uint256 index) external view returns (address)"
|
|
3229
4224
|
]);
|
|
3230
|
-
var lbPairAbi =
|
|
4225
|
+
var lbPairAbi = parseAbi12([
|
|
3231
4226
|
"function getLBHooksParameters() external view returns (bytes32)",
|
|
3232
4227
|
"function getActiveId() external view returns (uint24)",
|
|
3233
4228
|
"function getBinStep() external view returns (uint16)",
|
|
@@ -3236,7 +4231,7 @@ var lbPairAbi = parseAbi10([
|
|
|
3236
4231
|
"function balanceOf(address account, uint256 id) external view returns (uint256)",
|
|
3237
4232
|
"function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory)"
|
|
3238
4233
|
]);
|
|
3239
|
-
var lbRewarderAbi =
|
|
4234
|
+
var lbRewarderAbi = parseAbi12([
|
|
3240
4235
|
"function getRewardToken() external view returns (address)",
|
|
3241
4236
|
"function getRewardedRange() external view returns (uint256 minBinId, uint256 maxBinId)",
|
|
3242
4237
|
"function getPendingRewards(address user, uint256[] calldata ids) external view returns (uint256 pendingRewards)",
|
|
@@ -3246,50 +4241,50 @@ var lbRewarderAbi = parseAbi10([
|
|
|
3246
4241
|
"function getLBPair() external view returns (address)",
|
|
3247
4242
|
"function getMasterChef() external view returns (address)"
|
|
3248
4243
|
]);
|
|
3249
|
-
var masterChefAbi =
|
|
4244
|
+
var masterChefAbi = parseAbi12([
|
|
3250
4245
|
"function getMoePerSecond() external view returns (uint256)",
|
|
3251
4246
|
"function getTreasuryShare() external view returns (uint256)",
|
|
3252
4247
|
"function getStaticShare() external view returns (uint256)",
|
|
3253
4248
|
"function getVeMoe() external view returns (address)"
|
|
3254
4249
|
]);
|
|
3255
|
-
var veMoeAbi =
|
|
4250
|
+
var veMoeAbi = parseAbi12([
|
|
3256
4251
|
"function getWeight(uint256 pid) external view returns (uint256)",
|
|
3257
4252
|
"function getTotalWeight() external view returns (uint256)",
|
|
3258
4253
|
"function getTopPoolIds() external view returns (uint256[] memory)"
|
|
3259
4254
|
]);
|
|
3260
|
-
var lbPairBinAbi =
|
|
4255
|
+
var lbPairBinAbi = parseAbi12([
|
|
3261
4256
|
"function getBin(uint24 id) external view returns (uint128 reserveX, uint128 reserveY)",
|
|
3262
4257
|
"function getActiveId() external view returns (uint24)"
|
|
3263
4258
|
]);
|
|
3264
|
-
var lbQuoterAbi2 =
|
|
4259
|
+
var lbQuoterAbi2 = parseAbi12([
|
|
3265
4260
|
"function findBestPathFromAmountIn(address[] calldata route, uint128 amountIn) external view returns ((address[] route, address[] pairs, uint256[] binSteps, uint256[] versions, uint128[] amounts, uint128[] virtualAmountsWithoutSlippage, uint128[] fees))"
|
|
3266
4261
|
]);
|
|
3267
|
-
var erc20Abi2 =
|
|
4262
|
+
var erc20Abi2 = parseAbi12([
|
|
3268
4263
|
"function symbol() external view returns (string)"
|
|
3269
4264
|
]);
|
|
3270
|
-
var _addressAbi =
|
|
4265
|
+
var _addressAbi = parseAbi12(["function f() external view returns (address)"]);
|
|
3271
4266
|
function decodeAddressResult(data) {
|
|
3272
4267
|
if (!data) return null;
|
|
3273
4268
|
try {
|
|
3274
|
-
return
|
|
4269
|
+
return decodeFunctionResult4({ abi: _addressAbi, functionName: "f", data });
|
|
3275
4270
|
} catch {
|
|
3276
4271
|
return null;
|
|
3277
4272
|
}
|
|
3278
4273
|
}
|
|
3279
|
-
var _uint256Abi =
|
|
4274
|
+
var _uint256Abi = parseAbi12(["function f() external view returns (uint256)"]);
|
|
3280
4275
|
function decodeUint256Result(data) {
|
|
3281
4276
|
if (!data) return null;
|
|
3282
4277
|
try {
|
|
3283
|
-
return
|
|
4278
|
+
return decodeFunctionResult4({ abi: _uint256Abi, functionName: "f", data });
|
|
3284
4279
|
} catch {
|
|
3285
4280
|
return null;
|
|
3286
4281
|
}
|
|
3287
4282
|
}
|
|
3288
|
-
var _boolAbi =
|
|
4283
|
+
var _boolAbi = parseAbi12(["function f() external view returns (bool)"]);
|
|
3289
4284
|
function decodeBoolResult(data) {
|
|
3290
4285
|
if (!data) return null;
|
|
3291
4286
|
try {
|
|
3292
|
-
return
|
|
4287
|
+
return decodeFunctionResult4({ abi: _boolAbi, functionName: "f", data });
|
|
3293
4288
|
} catch {
|
|
3294
4289
|
return null;
|
|
3295
4290
|
}
|
|
@@ -3297,34 +4292,34 @@ function decodeBoolResult(data) {
|
|
|
3297
4292
|
function decodeStringResult(data) {
|
|
3298
4293
|
if (!data) return "?";
|
|
3299
4294
|
try {
|
|
3300
|
-
return
|
|
4295
|
+
return decodeFunctionResult4({ abi: erc20Abi2, functionName: "symbol", data });
|
|
3301
4296
|
} catch {
|
|
3302
4297
|
return "?";
|
|
3303
4298
|
}
|
|
3304
4299
|
}
|
|
3305
|
-
var _rangeAbi =
|
|
4300
|
+
var _rangeAbi = parseAbi12(["function f() external view returns (uint256 minBinId, uint256 maxBinId)"]);
|
|
3306
4301
|
function decodeRangeResult(data) {
|
|
3307
4302
|
if (!data) return null;
|
|
3308
4303
|
try {
|
|
3309
|
-
return
|
|
4304
|
+
return decodeFunctionResult4({ abi: _rangeAbi, functionName: "f", data });
|
|
3310
4305
|
} catch {
|
|
3311
4306
|
return null;
|
|
3312
4307
|
}
|
|
3313
4308
|
}
|
|
3314
|
-
var _binAbi =
|
|
4309
|
+
var _binAbi = parseAbi12(["function f() external view returns (uint128 reserveX, uint128 reserveY)"]);
|
|
3315
4310
|
function decodeBinResult(data) {
|
|
3316
4311
|
if (!data) return null;
|
|
3317
4312
|
try {
|
|
3318
|
-
return
|
|
4313
|
+
return decodeFunctionResult4({ abi: _binAbi, functionName: "f", data });
|
|
3319
4314
|
} catch {
|
|
3320
4315
|
return null;
|
|
3321
4316
|
}
|
|
3322
4317
|
}
|
|
3323
|
-
var _uint256ArrayAbi =
|
|
4318
|
+
var _uint256ArrayAbi = parseAbi12(["function f() external view returns (uint256[] memory)"]);
|
|
3324
4319
|
function decodeUint256ArrayResult(data) {
|
|
3325
4320
|
if (!data) return null;
|
|
3326
4321
|
try {
|
|
3327
|
-
return
|
|
4322
|
+
return decodeFunctionResult4({ abi: _uint256ArrayAbi, functionName: "f", data });
|
|
3328
4323
|
} catch {
|
|
3329
4324
|
return null;
|
|
3330
4325
|
}
|
|
@@ -3410,7 +4405,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3410
4405
|
let activeIdDesired = params.activeIdDesired;
|
|
3411
4406
|
if (activeIdDesired === void 0) {
|
|
3412
4407
|
const rpcUrl = this.requireRpc();
|
|
3413
|
-
const client =
|
|
4408
|
+
const client = createPublicClient8({ transport: http8(rpcUrl) });
|
|
3414
4409
|
const activeId = await client.readContract({
|
|
3415
4410
|
address: params.pool,
|
|
3416
4411
|
abi: lbPairAbi,
|
|
@@ -3423,7 +4418,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3423
4418
|
deltaIds.push(d);
|
|
3424
4419
|
}
|
|
3425
4420
|
const { distributionX, distributionY } = buildUniformDistribution(deltaIds);
|
|
3426
|
-
const data =
|
|
4421
|
+
const data = encodeFunctionData12({
|
|
3427
4422
|
abi: lbRouterAbi,
|
|
3428
4423
|
functionName: "addLiquidity",
|
|
3429
4424
|
args: [
|
|
@@ -3463,7 +4458,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3463
4458
|
*/
|
|
3464
4459
|
async buildRemoveLiquidity(params) {
|
|
3465
4460
|
const deadline = params.deadline ?? BigInt("18446744073709551615");
|
|
3466
|
-
const data =
|
|
4461
|
+
const data = encodeFunctionData12({
|
|
3467
4462
|
abi: lbRouterAbi,
|
|
3468
4463
|
functionName: "removeLiquidity",
|
|
3469
4464
|
args: [
|
|
@@ -3492,7 +4487,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3492
4487
|
*/
|
|
3493
4488
|
async autoDetectBins(pool) {
|
|
3494
4489
|
const rpcUrl = this.requireRpc();
|
|
3495
|
-
const client =
|
|
4490
|
+
const client = createPublicClient8({ transport: http8(rpcUrl) });
|
|
3496
4491
|
const hooksParams = await client.readContract({
|
|
3497
4492
|
address: pool,
|
|
3498
4493
|
abi: lbPairAbi,
|
|
@@ -3527,7 +4522,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3527
4522
|
*/
|
|
3528
4523
|
async getPendingRewards(user, pool, binIds) {
|
|
3529
4524
|
const rpcUrl = this.requireRpc();
|
|
3530
|
-
const client =
|
|
4525
|
+
const client = createPublicClient8({ transport: http8(rpcUrl) });
|
|
3531
4526
|
const hooksParams = await client.readContract({
|
|
3532
4527
|
address: pool,
|
|
3533
4528
|
abi: lbPairAbi,
|
|
@@ -3576,7 +4571,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3576
4571
|
*/
|
|
3577
4572
|
async buildClaimRewards(user, pool, binIds) {
|
|
3578
4573
|
const rpcUrl = this.requireRpc();
|
|
3579
|
-
const client =
|
|
4574
|
+
const client = createPublicClient8({ transport: http8(rpcUrl) });
|
|
3580
4575
|
const hooksParams = await client.readContract({
|
|
3581
4576
|
address: pool,
|
|
3582
4577
|
abi: lbPairAbi,
|
|
@@ -3598,7 +4593,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3598
4593
|
resolvedBinIds = [];
|
|
3599
4594
|
for (let b = min; b <= max; b++) resolvedBinIds.push(b);
|
|
3600
4595
|
}
|
|
3601
|
-
const data =
|
|
4596
|
+
const data = encodeFunctionData12({
|
|
3602
4597
|
abi: lbRewarderAbi,
|
|
3603
4598
|
functionName: "claim",
|
|
3604
4599
|
args: [user, resolvedBinIds.map(BigInt)]
|
|
@@ -3626,7 +4621,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3626
4621
|
*/
|
|
3627
4622
|
async discoverRewardedPools() {
|
|
3628
4623
|
const rpcUrl = this.requireRpc();
|
|
3629
|
-
const client =
|
|
4624
|
+
const client = createPublicClient8({ transport: http8(rpcUrl) });
|
|
3630
4625
|
const pairCount = await client.readContract({
|
|
3631
4626
|
address: this.lbFactory,
|
|
3632
4627
|
abi: lbFactoryAbi,
|
|
@@ -3636,14 +4631,14 @@ var MerchantMoeLBAdapter = class {
|
|
|
3636
4631
|
if (count === 0) return [];
|
|
3637
4632
|
const batch1Calls = Array.from({ length: count }, (_, i) => [
|
|
3638
4633
|
this.lbFactory,
|
|
3639
|
-
|
|
4634
|
+
encodeFunctionData12({ abi: lbFactoryAbi, functionName: "getLBPairAtIndex", args: [BigInt(i)] })
|
|
3640
4635
|
]);
|
|
3641
4636
|
const batch1Results = await multicallRead(rpcUrl, batch1Calls);
|
|
3642
4637
|
const pairAddresses = batch1Results.map((r) => decodeAddressResult(r)).filter((a) => a !== null);
|
|
3643
4638
|
if (pairAddresses.length === 0) return [];
|
|
3644
4639
|
const batch2Calls = pairAddresses.map((pair) => [
|
|
3645
4640
|
pair,
|
|
3646
|
-
|
|
4641
|
+
encodeFunctionData12({ abi: lbPairAbi, functionName: "getLBHooksParameters" })
|
|
3647
4642
|
]);
|
|
3648
4643
|
const batch2Results = await multicallRead(rpcUrl, batch2Calls);
|
|
3649
4644
|
const rewardedPairs = [];
|
|
@@ -3652,8 +4647,8 @@ var MerchantMoeLBAdapter = class {
|
|
|
3652
4647
|
if (!raw) continue;
|
|
3653
4648
|
let hooksBytes;
|
|
3654
4649
|
try {
|
|
3655
|
-
const _bytes32Abi =
|
|
3656
|
-
hooksBytes =
|
|
4650
|
+
const _bytes32Abi = parseAbi12(["function f() external view returns (bytes32)"]);
|
|
4651
|
+
hooksBytes = decodeFunctionResult4({ abi: _bytes32Abi, functionName: "f", data: raw });
|
|
3657
4652
|
} catch {
|
|
3658
4653
|
continue;
|
|
3659
4654
|
}
|
|
@@ -3665,17 +4660,17 @@ var MerchantMoeLBAdapter = class {
|
|
|
3665
4660
|
if (rewardedPairs.length === 0) return [];
|
|
3666
4661
|
const batch3Calls = [];
|
|
3667
4662
|
for (const { rewarder } of rewardedPairs) {
|
|
3668
|
-
batch3Calls.push([rewarder,
|
|
3669
|
-
batch3Calls.push([rewarder,
|
|
3670
|
-
batch3Calls.push([rewarder,
|
|
3671
|
-
batch3Calls.push([rewarder,
|
|
3672
|
-
batch3Calls.push([rewarder,
|
|
4663
|
+
batch3Calls.push([rewarder, encodeFunctionData12({ abi: lbRewarderAbi, functionName: "isStopped" })]);
|
|
4664
|
+
batch3Calls.push([rewarder, encodeFunctionData12({ abi: lbRewarderAbi, functionName: "getRewardedRange" })]);
|
|
4665
|
+
batch3Calls.push([rewarder, encodeFunctionData12({ abi: lbRewarderAbi, functionName: "getRewardToken" })]);
|
|
4666
|
+
batch3Calls.push([rewarder, encodeFunctionData12({ abi: lbRewarderAbi, functionName: "getPid" })]);
|
|
4667
|
+
batch3Calls.push([rewarder, encodeFunctionData12({ abi: lbRewarderAbi, functionName: "getMasterChef" })]);
|
|
3673
4668
|
}
|
|
3674
4669
|
const batch3Results = await multicallRead(rpcUrl, batch3Calls);
|
|
3675
4670
|
const batch4aCalls = [];
|
|
3676
4671
|
for (const { pool } of rewardedPairs) {
|
|
3677
|
-
batch4aCalls.push([pool,
|
|
3678
|
-
batch4aCalls.push([pool,
|
|
4672
|
+
batch4aCalls.push([pool, encodeFunctionData12({ abi: lbPairAbi, functionName: "getTokenX" })]);
|
|
4673
|
+
batch4aCalls.push([pool, encodeFunctionData12({ abi: lbPairAbi, functionName: "getTokenY" })]);
|
|
3679
4674
|
}
|
|
3680
4675
|
const batch4aResults = await multicallRead(rpcUrl, batch4aCalls);
|
|
3681
4676
|
const tokenXAddresses = [];
|
|
@@ -3689,7 +4684,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3689
4684
|
);
|
|
3690
4685
|
const batch4bCalls = uniqueTokens.map((token) => [
|
|
3691
4686
|
token,
|
|
3692
|
-
|
|
4687
|
+
encodeFunctionData12({ abi: erc20Abi2, functionName: "symbol" })
|
|
3693
4688
|
]);
|
|
3694
4689
|
const batch4bResults = await multicallRead(rpcUrl, batch4bCalls);
|
|
3695
4690
|
const symbolMap = /* @__PURE__ */ new Map();
|
|
@@ -3720,11 +4715,11 @@ var MerchantMoeLBAdapter = class {
|
|
|
3720
4715
|
functionName: "getVeMoe"
|
|
3721
4716
|
});
|
|
3722
4717
|
const batch5Calls = [
|
|
3723
|
-
[masterChefAddr,
|
|
3724
|
-
[masterChefAddr,
|
|
3725
|
-
[masterChefAddr,
|
|
3726
|
-
[veMoeAddr,
|
|
3727
|
-
[veMoeAddr,
|
|
4718
|
+
[masterChefAddr, encodeFunctionData12({ abi: masterChefAbi, functionName: "getMoePerSecond" })],
|
|
4719
|
+
[masterChefAddr, encodeFunctionData12({ abi: masterChefAbi, functionName: "getTreasuryShare" })],
|
|
4720
|
+
[masterChefAddr, encodeFunctionData12({ abi: masterChefAbi, functionName: "getStaticShare" })],
|
|
4721
|
+
[veMoeAddr, encodeFunctionData12({ abi: veMoeAbi, functionName: "getTotalWeight" })],
|
|
4722
|
+
[veMoeAddr, encodeFunctionData12({ abi: veMoeAbi, functionName: "getTopPoolIds" })]
|
|
3728
4723
|
];
|
|
3729
4724
|
const batch5Results = await multicallRead(rpcUrl, batch5Calls);
|
|
3730
4725
|
const moePerSecRaw = decodeUint256Result(batch5Results[0] ?? null) ?? 0n;
|
|
@@ -3741,7 +4736,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3741
4736
|
if (veMoeAddr && rewardedPairs.length > 0) {
|
|
3742
4737
|
const batch6Calls = poolData.map((d) => [
|
|
3743
4738
|
veMoeAddr,
|
|
3744
|
-
|
|
4739
|
+
encodeFunctionData12({ abi: veMoeAbi, functionName: "getWeight", args: [BigInt(d.pid)] })
|
|
3745
4740
|
]);
|
|
3746
4741
|
const batch6Results = await multicallRead(rpcUrl, batch6Calls);
|
|
3747
4742
|
for (let i = 0; i < poolData.length; i++) {
|
|
@@ -3788,7 +4783,7 @@ var MerchantMoeLBAdapter = class {
|
|
|
3788
4783
|
if (binRequests.length > 0) {
|
|
3789
4784
|
const batch7Calls = binRequests.map(({ poolIdx, binId }) => [
|
|
3790
4785
|
rewardedPairs[poolIdx].pool,
|
|
3791
|
-
|
|
4786
|
+
encodeFunctionData12({ abi: lbPairBinAbi, functionName: "getBin", args: [binId] })
|
|
3792
4787
|
]);
|
|
3793
4788
|
const batch7Results = await multicallRead(rpcUrl, batch7Calls);
|
|
3794
4789
|
for (let j = 0; j < binRequests.length; j++) {
|
|
@@ -3874,26 +4869,460 @@ var MerchantMoeLBAdapter = class {
|
|
|
3874
4869
|
}
|
|
3875
4870
|
return results;
|
|
3876
4871
|
}
|
|
3877
|
-
/**
|
|
3878
|
-
* Get a user's LB positions (bin balances) across a range of bin IDs.
|
|
3879
|
-
* If binIds is omitted, auto-detects from the rewarder's rewarded range (or active ± 50).
|
|
3880
|
-
*/
|
|
3881
|
-
async getUserPositions(user, pool, binIds) {
|
|
3882
|
-
const rpcUrl = this.requireRpc();
|
|
3883
|
-
const client =
|
|
3884
|
-
const resolvedBinIds = binIds && binIds.length > 0 ? binIds : await this.autoDetectBins(pool);
|
|
3885
|
-
const accounts = resolvedBinIds.map(() => user);
|
|
3886
|
-
const ids = resolvedBinIds.map(BigInt);
|
|
3887
|
-
const balances = await client.readContract({
|
|
3888
|
-
address: pool,
|
|
3889
|
-
abi: lbPairAbi,
|
|
3890
|
-
functionName: "balanceOfBatch",
|
|
3891
|
-
args: [accounts, ids]
|
|
3892
|
-
});
|
|
3893
|
-
return resolvedBinIds.map((binId, i) => ({ binId, balance: balances[i] ?? 0n })).filter((p) => p.balance > 0n);
|
|
3894
|
-
}
|
|
4872
|
+
/**
|
|
4873
|
+
* Get a user's LB positions (bin balances) across a range of bin IDs.
|
|
4874
|
+
* If binIds is omitted, auto-detects from the rewarder's rewarded range (or active ± 50).
|
|
4875
|
+
*/
|
|
4876
|
+
async getUserPositions(user, pool, binIds) {
|
|
4877
|
+
const rpcUrl = this.requireRpc();
|
|
4878
|
+
const client = createPublicClient8({ transport: http8(rpcUrl) });
|
|
4879
|
+
const resolvedBinIds = binIds && binIds.length > 0 ? binIds : await this.autoDetectBins(pool);
|
|
4880
|
+
const accounts = resolvedBinIds.map(() => user);
|
|
4881
|
+
const ids = resolvedBinIds.map(BigInt);
|
|
4882
|
+
const balances = await client.readContract({
|
|
4883
|
+
address: pool,
|
|
4884
|
+
abi: lbPairAbi,
|
|
4885
|
+
functionName: "balanceOfBatch",
|
|
4886
|
+
args: [accounts, ids]
|
|
4887
|
+
});
|
|
4888
|
+
return resolvedBinIds.map((binId, i) => ({ binId, balance: balances[i] ?? 0n })).filter((p) => p.balance > 0n);
|
|
4889
|
+
}
|
|
4890
|
+
};
|
|
4891
|
+
var KITTEN_TOKEN = "0x618275f8efe54c2afa87bfb9f210a52f0ff89364";
|
|
4892
|
+
var WHYPE_TOKEN = "0x5555555555555555555555555555555555555555";
|
|
4893
|
+
var MAX_NONCE_SCAN = 60;
|
|
4894
|
+
var HYPEREVM_TOKENS2 = [
|
|
4895
|
+
"0x5555555555555555555555555555555555555555",
|
|
4896
|
+
// WHYPE
|
|
4897
|
+
"0xb88339CB7199b77E23DB6E890353E22632Ba630f",
|
|
4898
|
+
// USDC
|
|
4899
|
+
"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
|
|
4900
|
+
// USDT0
|
|
4901
|
+
"0xBe6727B535545C67d5cAa73dEa54865B92CF7907",
|
|
4902
|
+
// UETH
|
|
4903
|
+
"0x9FDBdA0A5e284c32744D2f17Ee5c74B284993463",
|
|
4904
|
+
// UBTC
|
|
4905
|
+
"0x111111a1a0667d36bD57c0A9f569b98057111111",
|
|
4906
|
+
// USDH
|
|
4907
|
+
"0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34",
|
|
4908
|
+
// USDe
|
|
4909
|
+
"0x211Cc4DD073734dA055fbF44a2b4667d5E5fE5d2",
|
|
4910
|
+
// sUSDe
|
|
4911
|
+
"0xf4D9235269a96aaDaFc9aDAe454a0618eBE37949",
|
|
4912
|
+
// XAUt0
|
|
4913
|
+
"0xfD739d4e423301CE9385c1fb8850539D657C296D",
|
|
4914
|
+
// kHYPE
|
|
4915
|
+
KITTEN_TOKEN
|
|
4916
|
+
// KITTEN
|
|
4917
|
+
];
|
|
4918
|
+
var farmingCenterAbi = parseAbi13([
|
|
4919
|
+
"function multicall(bytes[] calldata data) external payable returns (bytes[] memory results)",
|
|
4920
|
+
"function enterFarming((address rewardToken, address bonusRewardToken, address pool, uint256 nonce) key, uint256 tokenId) external",
|
|
4921
|
+
"function exitFarming((address rewardToken, address bonusRewardToken, address pool, uint256 nonce) key, uint256 tokenId) external",
|
|
4922
|
+
"function collectRewards((address rewardToken, address bonusRewardToken, address pool, uint256 nonce) key, uint256 tokenId) external",
|
|
4923
|
+
"function claimReward(address rewardToken, address to, uint128 amountRequested) external returns (uint256 reward)"
|
|
4924
|
+
]);
|
|
4925
|
+
var positionManagerAbi2 = parseAbi13([
|
|
4926
|
+
"function approveForFarming(uint256 tokenId, bool approve, address farmingAddress) external",
|
|
4927
|
+
"function farmingApprovals(uint256 tokenId) external view returns (address)"
|
|
4928
|
+
]);
|
|
4929
|
+
var eternalFarmingAbi = parseAbi13([
|
|
4930
|
+
"function incentives(bytes32 incentiveId) external view returns (uint256 totalReward, uint256 bonusReward, address virtualPoolAddress, uint24 minimalPositionWidth, bool deactivated, address pluginAddress)",
|
|
4931
|
+
"function getRewardInfo((address rewardToken, address bonusRewardToken, address pool, uint256 nonce) key, uint256 tokenId) external view returns (uint256 reward, uint256 bonusReward)"
|
|
4932
|
+
]);
|
|
4933
|
+
var algebraFactoryAbi = parseAbi13([
|
|
4934
|
+
"function poolByPair(address tokenA, address tokenB) external view returns (address pool)"
|
|
4935
|
+
]);
|
|
4936
|
+
var _addressDecodeAbi3 = parseAbi13(["function f() external view returns (address)"]);
|
|
4937
|
+
function decodeAddress3(data) {
|
|
4938
|
+
if (!data) return null;
|
|
4939
|
+
try {
|
|
4940
|
+
return decodeFunctionResult5({ abi: _addressDecodeAbi3, functionName: "f", data });
|
|
4941
|
+
} catch {
|
|
4942
|
+
return null;
|
|
4943
|
+
}
|
|
4944
|
+
}
|
|
4945
|
+
function incentiveId(key) {
|
|
4946
|
+
return keccak256(
|
|
4947
|
+
encodeAbiParameters(
|
|
4948
|
+
[
|
|
4949
|
+
{ name: "rewardToken", type: "address" },
|
|
4950
|
+
{ name: "bonusRewardToken", type: "address" },
|
|
4951
|
+
{ name: "pool", type: "address" },
|
|
4952
|
+
{ name: "nonce", type: "uint256" }
|
|
4953
|
+
],
|
|
4954
|
+
[key.rewardToken, key.bonusRewardToken, key.pool, key.nonce]
|
|
4955
|
+
)
|
|
4956
|
+
);
|
|
4957
|
+
}
|
|
4958
|
+
function encodeEnterFarming(key, tokenId) {
|
|
4959
|
+
return encodeFunctionData13({
|
|
4960
|
+
abi: farmingCenterAbi,
|
|
4961
|
+
functionName: "enterFarming",
|
|
4962
|
+
args: [key, tokenId]
|
|
4963
|
+
});
|
|
4964
|
+
}
|
|
4965
|
+
function encodeExitFarming(key, tokenId) {
|
|
4966
|
+
return encodeFunctionData13({
|
|
4967
|
+
abi: farmingCenterAbi,
|
|
4968
|
+
functionName: "exitFarming",
|
|
4969
|
+
args: [key, tokenId]
|
|
4970
|
+
});
|
|
4971
|
+
}
|
|
4972
|
+
function encodeCollectRewards(key, tokenId) {
|
|
4973
|
+
return encodeFunctionData13({
|
|
4974
|
+
abi: farmingCenterAbi,
|
|
4975
|
+
functionName: "collectRewards",
|
|
4976
|
+
args: [key, tokenId]
|
|
4977
|
+
});
|
|
4978
|
+
}
|
|
4979
|
+
function encodeClaimReward(rewardToken, to) {
|
|
4980
|
+
return encodeFunctionData13({
|
|
4981
|
+
abi: farmingCenterAbi,
|
|
4982
|
+
functionName: "claimReward",
|
|
4983
|
+
args: [rewardToken, to, 2n ** 128n - 1n]
|
|
4984
|
+
// max uint128
|
|
4985
|
+
});
|
|
4986
|
+
}
|
|
4987
|
+
function encodeMulticall(calls) {
|
|
4988
|
+
return encodeFunctionData13({
|
|
4989
|
+
abi: farmingCenterAbi,
|
|
4990
|
+
functionName: "multicall",
|
|
4991
|
+
args: [calls]
|
|
4992
|
+
});
|
|
4993
|
+
}
|
|
4994
|
+
var nonceCache = /* @__PURE__ */ new Map();
|
|
4995
|
+
var KittenSwapFarmingAdapter = class {
|
|
4996
|
+
protocolName;
|
|
4997
|
+
farmingCenter;
|
|
4998
|
+
eternalFarming;
|
|
4999
|
+
positionManager;
|
|
5000
|
+
rpcUrl;
|
|
5001
|
+
factory;
|
|
5002
|
+
constructor(protocolName, farmingCenter, eternalFarming, positionManager, rpcUrl, factory) {
|
|
5003
|
+
this.protocolName = protocolName;
|
|
5004
|
+
this.farmingCenter = farmingCenter;
|
|
5005
|
+
this.eternalFarming = eternalFarming;
|
|
5006
|
+
this.positionManager = positionManager;
|
|
5007
|
+
this.rpcUrl = rpcUrl;
|
|
5008
|
+
this.factory = factory;
|
|
5009
|
+
}
|
|
5010
|
+
name() {
|
|
5011
|
+
return this.protocolName;
|
|
5012
|
+
}
|
|
5013
|
+
/**
|
|
5014
|
+
* Discover the active IncentiveKey for a given pool.
|
|
5015
|
+
* 1. Check runtime cache
|
|
5016
|
+
* 2. Batch-query nonces 0-60 via single multicall (61 calls)
|
|
5017
|
+
* 3. Return first non-zero incentive (totalReward > 0 and not deactivated)
|
|
5018
|
+
*/
|
|
5019
|
+
async discoverIncentiveKey(pool) {
|
|
5020
|
+
const poolLc = pool.toLowerCase();
|
|
5021
|
+
if (nonceCache.has(poolLc)) {
|
|
5022
|
+
return {
|
|
5023
|
+
rewardToken: KITTEN_TOKEN,
|
|
5024
|
+
bonusRewardToken: WHYPE_TOKEN,
|
|
5025
|
+
pool,
|
|
5026
|
+
nonce: nonceCache.get(poolLc)
|
|
5027
|
+
};
|
|
5028
|
+
}
|
|
5029
|
+
const calls = [];
|
|
5030
|
+
const nonces = [];
|
|
5031
|
+
for (let n = 0; n <= MAX_NONCE_SCAN; n++) {
|
|
5032
|
+
const nonce = BigInt(n);
|
|
5033
|
+
nonces.push(nonce);
|
|
5034
|
+
const key = {
|
|
5035
|
+
rewardToken: KITTEN_TOKEN,
|
|
5036
|
+
bonusRewardToken: WHYPE_TOKEN,
|
|
5037
|
+
pool,
|
|
5038
|
+
nonce
|
|
5039
|
+
};
|
|
5040
|
+
calls.push([
|
|
5041
|
+
this.eternalFarming,
|
|
5042
|
+
encodeFunctionData13({
|
|
5043
|
+
abi: eternalFarmingAbi,
|
|
5044
|
+
functionName: "incentives",
|
|
5045
|
+
args: [incentiveId(key)]
|
|
5046
|
+
})
|
|
5047
|
+
]);
|
|
5048
|
+
}
|
|
5049
|
+
const results = await multicallRead(this.rpcUrl, calls);
|
|
5050
|
+
for (let i = 0; i < results.length; i++) {
|
|
5051
|
+
const data = results[i];
|
|
5052
|
+
if (!data || data.length < 66) continue;
|
|
5053
|
+
try {
|
|
5054
|
+
const decoded = decodeAbiParameters5(
|
|
5055
|
+
[
|
|
5056
|
+
{ name: "totalReward", type: "uint256" },
|
|
5057
|
+
{ name: "bonusReward", type: "uint256" },
|
|
5058
|
+
{ name: "virtualPoolAddress", type: "address" },
|
|
5059
|
+
{ name: "minimalPositionWidth", type: "uint24" },
|
|
5060
|
+
{ name: "deactivated", type: "bool" },
|
|
5061
|
+
{ name: "pluginAddress", type: "address" }
|
|
5062
|
+
],
|
|
5063
|
+
data
|
|
5064
|
+
);
|
|
5065
|
+
const totalReward = decoded[0];
|
|
5066
|
+
const deactivated = decoded[4];
|
|
5067
|
+
if (totalReward > 0n && !deactivated) {
|
|
5068
|
+
const nonce = nonces[i];
|
|
5069
|
+
nonceCache.set(poolLc, nonce);
|
|
5070
|
+
return {
|
|
5071
|
+
rewardToken: KITTEN_TOKEN,
|
|
5072
|
+
bonusRewardToken: WHYPE_TOKEN,
|
|
5073
|
+
pool,
|
|
5074
|
+
nonce
|
|
5075
|
+
};
|
|
5076
|
+
}
|
|
5077
|
+
} catch {
|
|
5078
|
+
}
|
|
5079
|
+
}
|
|
5080
|
+
return null;
|
|
5081
|
+
}
|
|
5082
|
+
/**
|
|
5083
|
+
* Build approveForFarming tx on the PositionManager.
|
|
5084
|
+
* Required before enterFarming if not already approved.
|
|
5085
|
+
*/
|
|
5086
|
+
async buildApproveForFarming(tokenId) {
|
|
5087
|
+
const client = createPublicClient9({ transport: http9(this.rpcUrl) });
|
|
5088
|
+
const currentApproval = await client.readContract({
|
|
5089
|
+
address: this.positionManager,
|
|
5090
|
+
abi: positionManagerAbi2,
|
|
5091
|
+
functionName: "farmingApprovals",
|
|
5092
|
+
args: [tokenId]
|
|
5093
|
+
});
|
|
5094
|
+
if (currentApproval.toLowerCase() === this.farmingCenter.toLowerCase()) {
|
|
5095
|
+
return null;
|
|
5096
|
+
}
|
|
5097
|
+
return {
|
|
5098
|
+
description: `[${this.protocolName}] Approve NFT #${tokenId} for farming`,
|
|
5099
|
+
to: this.positionManager,
|
|
5100
|
+
data: encodeFunctionData13({
|
|
5101
|
+
abi: positionManagerAbi2,
|
|
5102
|
+
functionName: "approveForFarming",
|
|
5103
|
+
args: [tokenId, true, this.farmingCenter]
|
|
5104
|
+
}),
|
|
5105
|
+
value: 0n,
|
|
5106
|
+
gas_estimate: 6e4
|
|
5107
|
+
};
|
|
5108
|
+
}
|
|
5109
|
+
/**
|
|
5110
|
+
* Build enterFarming tx for a position NFT.
|
|
5111
|
+
* Checks farming approval first and returns pre_txs if needed.
|
|
5112
|
+
*/
|
|
5113
|
+
async buildEnterFarming(tokenId, pool, _owner) {
|
|
5114
|
+
const key = await this.discoverIncentiveKey(pool);
|
|
5115
|
+
if (!key) {
|
|
5116
|
+
throw new DefiError(
|
|
5117
|
+
"CONTRACT_ERROR",
|
|
5118
|
+
`[${this.protocolName}] No active incentive found for pool ${pool}`
|
|
5119
|
+
);
|
|
5120
|
+
}
|
|
5121
|
+
const approveTx = await this.buildApproveForFarming(tokenId);
|
|
5122
|
+
return {
|
|
5123
|
+
description: `[${this.protocolName}] Enter farming for NFT #${tokenId} in pool ${pool}`,
|
|
5124
|
+
to: this.farmingCenter,
|
|
5125
|
+
data: encodeEnterFarming(key, tokenId),
|
|
5126
|
+
value: 0n,
|
|
5127
|
+
gas_estimate: 4e5,
|
|
5128
|
+
pre_txs: approveTx ? [approveTx] : void 0
|
|
5129
|
+
};
|
|
5130
|
+
}
|
|
5131
|
+
/**
|
|
5132
|
+
* Build a tx that exits farming for a position NFT (unstakes).
|
|
5133
|
+
*/
|
|
5134
|
+
async buildExitFarming(tokenId, pool) {
|
|
5135
|
+
const key = await this.discoverIncentiveKey(pool);
|
|
5136
|
+
if (!key) {
|
|
5137
|
+
throw new DefiError(
|
|
5138
|
+
"CONTRACT_ERROR",
|
|
5139
|
+
`[${this.protocolName}] No active incentive found for pool ${pool}`
|
|
5140
|
+
);
|
|
5141
|
+
}
|
|
5142
|
+
return {
|
|
5143
|
+
description: `[${this.protocolName}] Exit farming for NFT #${tokenId} in pool ${pool}`,
|
|
5144
|
+
to: this.farmingCenter,
|
|
5145
|
+
data: encodeExitFarming(key, tokenId),
|
|
5146
|
+
value: 0n,
|
|
5147
|
+
gas_estimate: 3e5
|
|
5148
|
+
};
|
|
5149
|
+
}
|
|
5150
|
+
/**
|
|
5151
|
+
* Build a multicall tx that collects rewards for a staked position and claims them.
|
|
5152
|
+
* Pattern: multicall([collectRewards(key, tokenId), claimReward(KITTEN, owner, max), claimReward(WHYPE, owner, max)])
|
|
5153
|
+
*/
|
|
5154
|
+
async buildCollectRewards(tokenId, pool, owner) {
|
|
5155
|
+
const key = await this.discoverIncentiveKey(pool);
|
|
5156
|
+
if (!key) {
|
|
5157
|
+
throw new DefiError(
|
|
5158
|
+
"CONTRACT_ERROR",
|
|
5159
|
+
`[${this.protocolName}] No active incentive found for pool ${pool}`
|
|
5160
|
+
);
|
|
5161
|
+
}
|
|
5162
|
+
const calls = [
|
|
5163
|
+
encodeCollectRewards(key, tokenId),
|
|
5164
|
+
encodeClaimReward(KITTEN_TOKEN, owner),
|
|
5165
|
+
encodeClaimReward(WHYPE_TOKEN, owner)
|
|
5166
|
+
];
|
|
5167
|
+
return {
|
|
5168
|
+
description: `[${this.protocolName}] Collect + claim rewards for NFT #${tokenId} in pool ${pool}`,
|
|
5169
|
+
to: this.farmingCenter,
|
|
5170
|
+
data: encodeMulticall(calls),
|
|
5171
|
+
value: 0n,
|
|
5172
|
+
gas_estimate: 4e5
|
|
5173
|
+
};
|
|
5174
|
+
}
|
|
5175
|
+
/**
|
|
5176
|
+
* Build a tx that only claims already-accumulated rewards (no position change needed).
|
|
5177
|
+
*/
|
|
5178
|
+
async buildClaimReward(owner) {
|
|
5179
|
+
const calls = [
|
|
5180
|
+
encodeClaimReward(KITTEN_TOKEN, owner),
|
|
5181
|
+
encodeClaimReward(WHYPE_TOKEN, owner)
|
|
5182
|
+
];
|
|
5183
|
+
return {
|
|
5184
|
+
description: `[${this.protocolName}] Claim KITTEN + WHYPE farming rewards to ${owner}`,
|
|
5185
|
+
to: this.farmingCenter,
|
|
5186
|
+
data: encodeMulticall(calls),
|
|
5187
|
+
value: 0n,
|
|
5188
|
+
gas_estimate: 2e5
|
|
5189
|
+
};
|
|
5190
|
+
}
|
|
5191
|
+
/**
|
|
5192
|
+
* Query pending rewards for a staked position NFT.
|
|
5193
|
+
*/
|
|
5194
|
+
async getPendingRewards(tokenId, pool) {
|
|
5195
|
+
const key = await this.discoverIncentiveKey(pool);
|
|
5196
|
+
if (!key) {
|
|
5197
|
+
return { reward: 0n, bonusReward: 0n };
|
|
5198
|
+
}
|
|
5199
|
+
const client = createPublicClient9({ transport: http9(this.rpcUrl) });
|
|
5200
|
+
const result = await client.readContract({
|
|
5201
|
+
address: this.eternalFarming,
|
|
5202
|
+
abi: eternalFarmingAbi,
|
|
5203
|
+
functionName: "getRewardInfo",
|
|
5204
|
+
args: [key, tokenId]
|
|
5205
|
+
});
|
|
5206
|
+
return { reward: result[0], bonusReward: result[1] };
|
|
5207
|
+
}
|
|
5208
|
+
/**
|
|
5209
|
+
* Discover all KittenSwap pools with active farming incentives.
|
|
5210
|
+
*
|
|
5211
|
+
* Steps:
|
|
5212
|
+
* 1. Generate all unique token pair combos from HYPEREVM_TOKENS (includes KITTEN)
|
|
5213
|
+
* 2. Batch poolByPair calls via multicall against the Algebra factory
|
|
5214
|
+
* 3. For each found pool, batch-scan nonces 0-60 via multicall
|
|
5215
|
+
* 4. Return enriched FarmingPool[] for pools with active incentives
|
|
5216
|
+
*/
|
|
5217
|
+
async discoverFarmingPools() {
|
|
5218
|
+
if (!this.factory) {
|
|
5219
|
+
return [];
|
|
5220
|
+
}
|
|
5221
|
+
const pairs = [];
|
|
5222
|
+
for (let i = 0; i < HYPEREVM_TOKENS2.length; i++) {
|
|
5223
|
+
for (let j = i + 1; j < HYPEREVM_TOKENS2.length; j++) {
|
|
5224
|
+
pairs.push([HYPEREVM_TOKENS2[i], HYPEREVM_TOKENS2[j]]);
|
|
5225
|
+
}
|
|
5226
|
+
}
|
|
5227
|
+
const poolByPairCalls = pairs.map(([tokenA, tokenB]) => [
|
|
5228
|
+
this.factory,
|
|
5229
|
+
encodeFunctionData13({
|
|
5230
|
+
abi: algebraFactoryAbi,
|
|
5231
|
+
functionName: "poolByPair",
|
|
5232
|
+
args: [tokenA, tokenB]
|
|
5233
|
+
})
|
|
5234
|
+
]);
|
|
5235
|
+
const poolResults = await multicallRead(this.rpcUrl, poolByPairCalls);
|
|
5236
|
+
const poolSet = /* @__PURE__ */ new Set();
|
|
5237
|
+
for (const data of poolResults) {
|
|
5238
|
+
const addr = decodeAddress3(data);
|
|
5239
|
+
if (addr && addr !== zeroAddress7) {
|
|
5240
|
+
poolSet.add(addr.toLowerCase());
|
|
5241
|
+
}
|
|
5242
|
+
}
|
|
5243
|
+
if (poolSet.size === 0) return [];
|
|
5244
|
+
const pools = Array.from(poolSet);
|
|
5245
|
+
const NONCE_COUNT = MAX_NONCE_SCAN + 1;
|
|
5246
|
+
const allNonceCalls = [];
|
|
5247
|
+
for (const pool of pools) {
|
|
5248
|
+
for (let n = 0; n <= MAX_NONCE_SCAN; n++) {
|
|
5249
|
+
const key = {
|
|
5250
|
+
rewardToken: KITTEN_TOKEN,
|
|
5251
|
+
bonusRewardToken: WHYPE_TOKEN,
|
|
5252
|
+
pool,
|
|
5253
|
+
nonce: BigInt(n)
|
|
5254
|
+
};
|
|
5255
|
+
allNonceCalls.push([
|
|
5256
|
+
this.eternalFarming,
|
|
5257
|
+
encodeFunctionData13({
|
|
5258
|
+
abi: eternalFarmingAbi,
|
|
5259
|
+
functionName: "incentives",
|
|
5260
|
+
args: [incentiveId(key)]
|
|
5261
|
+
})
|
|
5262
|
+
]);
|
|
5263
|
+
}
|
|
5264
|
+
}
|
|
5265
|
+
const allNonceResults = await multicallRead(this.rpcUrl, allNonceCalls);
|
|
5266
|
+
const results = [];
|
|
5267
|
+
for (let pi = 0; pi < pools.length; pi++) {
|
|
5268
|
+
const pool = pools[pi];
|
|
5269
|
+
const poolLc = pool.toLowerCase();
|
|
5270
|
+
const base = pi * NONCE_COUNT;
|
|
5271
|
+
let bestKey = null;
|
|
5272
|
+
let bestTotalReward = 0n;
|
|
5273
|
+
let bestBonusReward = 0n;
|
|
5274
|
+
let bestActive = false;
|
|
5275
|
+
for (let n = 0; n <= MAX_NONCE_SCAN; n++) {
|
|
5276
|
+
const data = allNonceResults[base + n];
|
|
5277
|
+
if (!data || data.length < 66) continue;
|
|
5278
|
+
try {
|
|
5279
|
+
const decoded = decodeAbiParameters5(
|
|
5280
|
+
[
|
|
5281
|
+
{ name: "totalReward", type: "uint256" },
|
|
5282
|
+
{ name: "bonusReward", type: "uint256" },
|
|
5283
|
+
{ name: "virtualPoolAddress", type: "address" },
|
|
5284
|
+
{ name: "minimalPositionWidth", type: "uint24" },
|
|
5285
|
+
{ name: "deactivated", type: "bool" },
|
|
5286
|
+
{ name: "pluginAddress", type: "address" }
|
|
5287
|
+
],
|
|
5288
|
+
data
|
|
5289
|
+
);
|
|
5290
|
+
const totalReward = decoded[0];
|
|
5291
|
+
const bonusReward = decoded[1];
|
|
5292
|
+
const deactivated = decoded[4];
|
|
5293
|
+
if (totalReward > 0n) {
|
|
5294
|
+
const nonce = BigInt(n);
|
|
5295
|
+
const isActive = !deactivated;
|
|
5296
|
+
if (!bestKey || isActive && !bestActive || isActive === bestActive && nonce > bestKey.nonce) {
|
|
5297
|
+
bestKey = {
|
|
5298
|
+
rewardToken: KITTEN_TOKEN,
|
|
5299
|
+
bonusRewardToken: WHYPE_TOKEN,
|
|
5300
|
+
pool,
|
|
5301
|
+
nonce
|
|
5302
|
+
};
|
|
5303
|
+
bestTotalReward = totalReward;
|
|
5304
|
+
bestBonusReward = bonusReward;
|
|
5305
|
+
bestActive = isActive;
|
|
5306
|
+
}
|
|
5307
|
+
}
|
|
5308
|
+
} catch {
|
|
5309
|
+
}
|
|
5310
|
+
}
|
|
5311
|
+
if (bestKey) {
|
|
5312
|
+
nonceCache.set(poolLc, bestKey.nonce);
|
|
5313
|
+
results.push({
|
|
5314
|
+
pool,
|
|
5315
|
+
key: bestKey,
|
|
5316
|
+
totalReward: bestTotalReward,
|
|
5317
|
+
bonusReward: bestBonusReward,
|
|
5318
|
+
active: bestActive
|
|
5319
|
+
});
|
|
5320
|
+
}
|
|
5321
|
+
}
|
|
5322
|
+
return results;
|
|
5323
|
+
}
|
|
3895
5324
|
};
|
|
3896
|
-
var POOL_ABI =
|
|
5325
|
+
var POOL_ABI = parseAbi14([
|
|
3897
5326
|
"function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
|
|
3898
5327
|
"function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
|
|
3899
5328
|
"function repay(address asset, uint256 amount, uint256 interestRateMode, address onBehalfOf) external returns (uint256)",
|
|
@@ -3901,27 +5330,27 @@ var POOL_ABI = parseAbi11([
|
|
|
3901
5330
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)",
|
|
3902
5331
|
"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)"
|
|
3903
5332
|
]);
|
|
3904
|
-
var ERC20_ABI2 =
|
|
5333
|
+
var ERC20_ABI2 = parseAbi14([
|
|
3905
5334
|
"function totalSupply() external view returns (uint256)"
|
|
3906
5335
|
]);
|
|
3907
|
-
var INCENTIVES_ABI =
|
|
5336
|
+
var INCENTIVES_ABI = parseAbi14([
|
|
3908
5337
|
"function getIncentivesController() external view returns (address)"
|
|
3909
5338
|
]);
|
|
3910
|
-
var REWARDS_CONTROLLER_ABI =
|
|
5339
|
+
var REWARDS_CONTROLLER_ABI = parseAbi14([
|
|
3911
5340
|
"function getRewardsByAsset(address asset) external view returns (address[])",
|
|
3912
5341
|
"function getRewardsData(address asset, address reward) external view returns (uint256 index, uint256 emissionsPerSecond, uint256 lastUpdateTimestamp, uint256 distributionEnd)"
|
|
3913
5342
|
]);
|
|
3914
|
-
var POOL_PROVIDER_ABI =
|
|
5343
|
+
var POOL_PROVIDER_ABI = parseAbi14([
|
|
3915
5344
|
"function ADDRESSES_PROVIDER() external view returns (address)"
|
|
3916
5345
|
]);
|
|
3917
|
-
var ADDRESSES_PROVIDER_ABI =
|
|
5346
|
+
var ADDRESSES_PROVIDER_ABI = parseAbi14([
|
|
3918
5347
|
"function getPriceOracle() external view returns (address)"
|
|
3919
5348
|
]);
|
|
3920
|
-
var ORACLE_ABI =
|
|
5349
|
+
var ORACLE_ABI = parseAbi14([
|
|
3921
5350
|
"function getAssetPrice(address asset) external view returns (uint256)",
|
|
3922
5351
|
"function BASE_CURRENCY_UNIT() external view returns (uint256)"
|
|
3923
5352
|
]);
|
|
3924
|
-
var ERC20_DECIMALS_ABI =
|
|
5353
|
+
var ERC20_DECIMALS_ABI = parseAbi14([
|
|
3925
5354
|
"function decimals() external view returns (uint8)"
|
|
3926
5355
|
]);
|
|
3927
5356
|
function u256ToF64(v) {
|
|
@@ -3929,14 +5358,14 @@ function u256ToF64(v) {
|
|
|
3929
5358
|
if (v > MAX_U128) return Infinity;
|
|
3930
5359
|
return Number(v);
|
|
3931
5360
|
}
|
|
3932
|
-
function
|
|
5361
|
+
function decodeAddress4(data) {
|
|
3933
5362
|
if (!data || data.length < 66) return null;
|
|
3934
5363
|
return `0x${data.slice(26, 66)}`;
|
|
3935
5364
|
}
|
|
3936
5365
|
function decodeAddressArray(data) {
|
|
3937
5366
|
if (!data) return [];
|
|
3938
5367
|
try {
|
|
3939
|
-
return
|
|
5368
|
+
return decodeFunctionResult6({
|
|
3940
5369
|
abi: REWARDS_CONTROLLER_ABI,
|
|
3941
5370
|
functionName: "getRewardsByAsset",
|
|
3942
5371
|
data
|
|
@@ -3948,7 +5377,7 @@ function decodeAddressArray(data) {
|
|
|
3948
5377
|
function decodeReserveData(data) {
|
|
3949
5378
|
if (!data) return null;
|
|
3950
5379
|
try {
|
|
3951
|
-
return
|
|
5380
|
+
return decodeFunctionResult6({
|
|
3952
5381
|
abi: POOL_ABI,
|
|
3953
5382
|
functionName: "getReserveData",
|
|
3954
5383
|
data
|
|
@@ -3960,7 +5389,7 @@ function decodeReserveData(data) {
|
|
|
3960
5389
|
function decodeRewardsData(data) {
|
|
3961
5390
|
if (!data) return null;
|
|
3962
5391
|
try {
|
|
3963
|
-
return
|
|
5392
|
+
return decodeFunctionResult6({
|
|
3964
5393
|
abi: REWARDS_CONTROLLER_ABI,
|
|
3965
5394
|
functionName: "getRewardsData",
|
|
3966
5395
|
data
|
|
@@ -3984,7 +5413,7 @@ var AaveV3Adapter = class {
|
|
|
3984
5413
|
return this.protocolName;
|
|
3985
5414
|
}
|
|
3986
5415
|
async buildSupply(params) {
|
|
3987
|
-
const data =
|
|
5416
|
+
const data = encodeFunctionData14({
|
|
3988
5417
|
abi: POOL_ABI,
|
|
3989
5418
|
functionName: "supply",
|
|
3990
5419
|
args: [params.asset, params.amount, params.on_behalf_of, 0]
|
|
@@ -4000,7 +5429,7 @@ var AaveV3Adapter = class {
|
|
|
4000
5429
|
}
|
|
4001
5430
|
async buildBorrow(params) {
|
|
4002
5431
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
4003
|
-
const data =
|
|
5432
|
+
const data = encodeFunctionData14({
|
|
4004
5433
|
abi: POOL_ABI,
|
|
4005
5434
|
functionName: "borrow",
|
|
4006
5435
|
args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
|
|
@@ -4015,7 +5444,7 @@ var AaveV3Adapter = class {
|
|
|
4015
5444
|
}
|
|
4016
5445
|
async buildRepay(params) {
|
|
4017
5446
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
4018
|
-
const data =
|
|
5447
|
+
const data = encodeFunctionData14({
|
|
4019
5448
|
abi: POOL_ABI,
|
|
4020
5449
|
functionName: "repay",
|
|
4021
5450
|
args: [params.asset, params.amount, rateMode, params.on_behalf_of]
|
|
@@ -4030,7 +5459,7 @@ var AaveV3Adapter = class {
|
|
|
4030
5459
|
};
|
|
4031
5460
|
}
|
|
4032
5461
|
async buildWithdraw(params) {
|
|
4033
|
-
const data =
|
|
5462
|
+
const data = encodeFunctionData14({
|
|
4034
5463
|
abi: POOL_ABI,
|
|
4035
5464
|
functionName: "withdraw",
|
|
4036
5465
|
args: [params.asset, params.amount, params.to]
|
|
@@ -4045,7 +5474,7 @@ var AaveV3Adapter = class {
|
|
|
4045
5474
|
}
|
|
4046
5475
|
async getRates(asset) {
|
|
4047
5476
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4048
|
-
const reserveCallData =
|
|
5477
|
+
const reserveCallData = encodeFunctionData14({
|
|
4049
5478
|
abi: POOL_ABI,
|
|
4050
5479
|
functionName: "getReserveData",
|
|
4051
5480
|
args: [asset]
|
|
@@ -4072,8 +5501,8 @@ var AaveV3Adapter = class {
|
|
|
4072
5501
|
const aTokenAddress = result[8];
|
|
4073
5502
|
const variableDebtTokenAddress = result[10];
|
|
4074
5503
|
const [supplyRaw, borrowRaw] = await multicallRead(this.rpcUrl, [
|
|
4075
|
-
[aTokenAddress,
|
|
4076
|
-
[variableDebtTokenAddress,
|
|
5504
|
+
[aTokenAddress, encodeFunctionData14({ abi: ERC20_ABI2, functionName: "totalSupply" })],
|
|
5505
|
+
[variableDebtTokenAddress, encodeFunctionData14({ abi: ERC20_ABI2, functionName: "totalSupply" })]
|
|
4077
5506
|
]);
|
|
4078
5507
|
const totalSupply = decodeU256(supplyRaw ?? null);
|
|
4079
5508
|
const totalBorrow = decodeU256(borrowRaw ?? null);
|
|
@@ -4084,24 +5513,24 @@ var AaveV3Adapter = class {
|
|
|
4084
5513
|
const borrowEmissions = [];
|
|
4085
5514
|
try {
|
|
4086
5515
|
const [controllerRaw] = await multicallRead(this.rpcUrl, [
|
|
4087
|
-
[aTokenAddress,
|
|
5516
|
+
[aTokenAddress, encodeFunctionData14({ abi: INCENTIVES_ABI, functionName: "getIncentivesController" })]
|
|
4088
5517
|
]);
|
|
4089
|
-
const controllerAddr =
|
|
4090
|
-
if (controllerAddr && controllerAddr !==
|
|
5518
|
+
const controllerAddr = decodeAddress4(controllerRaw ?? null);
|
|
5519
|
+
if (controllerAddr && controllerAddr !== zeroAddress8) {
|
|
4091
5520
|
const [supplyRewardsRaw, borrowRewardsRaw] = await multicallRead(this.rpcUrl, [
|
|
4092
|
-
[controllerAddr,
|
|
4093
|
-
[controllerAddr,
|
|
5521
|
+
[controllerAddr, encodeFunctionData14({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [aTokenAddress] })],
|
|
5522
|
+
[controllerAddr, encodeFunctionData14({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [variableDebtTokenAddress] })]
|
|
4094
5523
|
]);
|
|
4095
5524
|
const supplyRewards = decodeAddressArray(supplyRewardsRaw ?? null);
|
|
4096
5525
|
const borrowRewards = decodeAddressArray(borrowRewardsRaw ?? null);
|
|
4097
5526
|
const rewardsDataCalls = [
|
|
4098
5527
|
...supplyRewards.map((reward) => [
|
|
4099
5528
|
controllerAddr,
|
|
4100
|
-
|
|
5529
|
+
encodeFunctionData14({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [aTokenAddress, reward] })
|
|
4101
5530
|
]),
|
|
4102
5531
|
...borrowRewards.map((reward) => [
|
|
4103
5532
|
controllerAddr,
|
|
4104
|
-
|
|
5533
|
+
encodeFunctionData14({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [variableDebtTokenAddress, reward] })
|
|
4105
5534
|
])
|
|
4106
5535
|
];
|
|
4107
5536
|
if (rewardsDataCalls.length > 0) {
|
|
@@ -4133,19 +5562,19 @@ var AaveV3Adapter = class {
|
|
|
4133
5562
|
if ((hasSupplyRewards || hasBorrowRewards) && totalSupply > 0n) {
|
|
4134
5563
|
try {
|
|
4135
5564
|
const [providerRaw] = await multicallRead(this.rpcUrl, [
|
|
4136
|
-
[this.pool,
|
|
5565
|
+
[this.pool, encodeFunctionData14({ abi: POOL_PROVIDER_ABI, functionName: "ADDRESSES_PROVIDER" })]
|
|
4137
5566
|
]);
|
|
4138
|
-
const providerAddr =
|
|
5567
|
+
const providerAddr = decodeAddress4(providerRaw ?? null);
|
|
4139
5568
|
if (!providerAddr) throw new Error("No provider address");
|
|
4140
5569
|
const [oracleRaw] = await multicallRead(this.rpcUrl, [
|
|
4141
|
-
[providerAddr,
|
|
5570
|
+
[providerAddr, encodeFunctionData14({ abi: ADDRESSES_PROVIDER_ABI, functionName: "getPriceOracle" })]
|
|
4142
5571
|
]);
|
|
4143
|
-
const oracleAddr =
|
|
5572
|
+
const oracleAddr = decodeAddress4(oracleRaw ?? null);
|
|
4144
5573
|
if (!oracleAddr) throw new Error("No oracle address");
|
|
4145
5574
|
const [assetPriceRaw, baseCurrencyUnitRaw, assetDecimalsRaw] = await multicallRead(this.rpcUrl, [
|
|
4146
|
-
[oracleAddr,
|
|
4147
|
-
[oracleAddr,
|
|
4148
|
-
[asset,
|
|
5575
|
+
[oracleAddr, encodeFunctionData14({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [asset] })],
|
|
5576
|
+
[oracleAddr, encodeFunctionData14({ abi: ORACLE_ABI, functionName: "BASE_CURRENCY_UNIT" })],
|
|
5577
|
+
[asset, encodeFunctionData14({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
|
|
4149
5578
|
]);
|
|
4150
5579
|
const assetPrice = decodeU256(assetPriceRaw ?? null);
|
|
4151
5580
|
const baseCurrencyUnit = decodeU256(baseCurrencyUnitRaw ?? null);
|
|
@@ -4155,8 +5584,8 @@ var AaveV3Adapter = class {
|
|
|
4155
5584
|
const assetDecimalsDivisor = 10 ** assetDecimals;
|
|
4156
5585
|
const allRewardTokens = Array.from(/* @__PURE__ */ new Set([...supplyRewardTokens, ...borrowRewardTokens]));
|
|
4157
5586
|
const rewardPriceCalls = allRewardTokens.flatMap((token) => [
|
|
4158
|
-
[oracleAddr,
|
|
4159
|
-
[token,
|
|
5587
|
+
[oracleAddr, encodeFunctionData14({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [token] })],
|
|
5588
|
+
[token, encodeFunctionData14({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
|
|
4160
5589
|
]);
|
|
4161
5590
|
const rewardPriceResults = rewardPriceCalls.length > 0 ? await multicallRead(this.rpcUrl, rewardPriceCalls) : [];
|
|
4162
5591
|
const rewardPriceMap = /* @__PURE__ */ new Map();
|
|
@@ -4229,7 +5658,7 @@ var AaveV3Adapter = class {
|
|
|
4229
5658
|
}
|
|
4230
5659
|
async getUserPosition(user) {
|
|
4231
5660
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4232
|
-
const client =
|
|
5661
|
+
const client = createPublicClient10({ transport: http10(this.rpcUrl) });
|
|
4233
5662
|
const result = await client.readContract({
|
|
4234
5663
|
address: this.pool,
|
|
4235
5664
|
abi: POOL_ABI,
|
|
@@ -4244,8 +5673,8 @@ var AaveV3Adapter = class {
|
|
|
4244
5673
|
const collateralUsd = u256ToF64(totalCollateralBase) / 1e8;
|
|
4245
5674
|
const debtUsd = u256ToF64(totalDebtBase) / 1e8;
|
|
4246
5675
|
const ltvBps = u256ToF64(ltv);
|
|
4247
|
-
const supplies = collateralUsd > 0 ? [{ asset:
|
|
4248
|
-
const borrows = debtUsd > 0 ? [{ asset:
|
|
5676
|
+
const supplies = collateralUsd > 0 ? [{ asset: zeroAddress8, symbol: "Total Collateral", amount: totalCollateralBase, value_usd: collateralUsd }] : [];
|
|
5677
|
+
const borrows = debtUsd > 0 ? [{ asset: zeroAddress8, symbol: "Total Debt", amount: totalDebtBase, value_usd: debtUsd }] : [];
|
|
4249
5678
|
return {
|
|
4250
5679
|
protocol: this.protocolName,
|
|
4251
5680
|
user,
|
|
@@ -4256,7 +5685,7 @@ var AaveV3Adapter = class {
|
|
|
4256
5685
|
};
|
|
4257
5686
|
}
|
|
4258
5687
|
};
|
|
4259
|
-
var POOL_ABI2 =
|
|
5688
|
+
var POOL_ABI2 = parseAbi15([
|
|
4260
5689
|
"function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
|
|
4261
5690
|
"function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
|
|
4262
5691
|
"function repay(address asset, uint256 amount, uint256 rateMode, address onBehalfOf) external returns (uint256)",
|
|
@@ -4269,7 +5698,7 @@ var POOL_ABI2 = parseAbi12([
|
|
|
4269
5698
|
// [9]=variableDebtTokenAddress, [10]=interestRateStrategyAddress, [11]=id
|
|
4270
5699
|
"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)"
|
|
4271
5700
|
]);
|
|
4272
|
-
var ERC20_ABI22 =
|
|
5701
|
+
var ERC20_ABI22 = parseAbi15([
|
|
4273
5702
|
"function totalSupply() external view returns (uint256)"
|
|
4274
5703
|
]);
|
|
4275
5704
|
function u256ToF642(v) {
|
|
@@ -4292,7 +5721,7 @@ var AaveV2Adapter = class {
|
|
|
4292
5721
|
return this.protocolName;
|
|
4293
5722
|
}
|
|
4294
5723
|
async buildSupply(params) {
|
|
4295
|
-
const data =
|
|
5724
|
+
const data = encodeFunctionData15({
|
|
4296
5725
|
abi: POOL_ABI2,
|
|
4297
5726
|
functionName: "deposit",
|
|
4298
5727
|
args: [params.asset, params.amount, params.on_behalf_of, 0]
|
|
@@ -4308,7 +5737,7 @@ var AaveV2Adapter = class {
|
|
|
4308
5737
|
}
|
|
4309
5738
|
async buildBorrow(params) {
|
|
4310
5739
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
4311
|
-
const data =
|
|
5740
|
+
const data = encodeFunctionData15({
|
|
4312
5741
|
abi: POOL_ABI2,
|
|
4313
5742
|
functionName: "borrow",
|
|
4314
5743
|
args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
|
|
@@ -4323,7 +5752,7 @@ var AaveV2Adapter = class {
|
|
|
4323
5752
|
}
|
|
4324
5753
|
async buildRepay(params) {
|
|
4325
5754
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
4326
|
-
const data =
|
|
5755
|
+
const data = encodeFunctionData15({
|
|
4327
5756
|
abi: POOL_ABI2,
|
|
4328
5757
|
functionName: "repay",
|
|
4329
5758
|
args: [params.asset, params.amount, rateMode, params.on_behalf_of]
|
|
@@ -4338,7 +5767,7 @@ var AaveV2Adapter = class {
|
|
|
4338
5767
|
};
|
|
4339
5768
|
}
|
|
4340
5769
|
async buildWithdraw(params) {
|
|
4341
|
-
const data =
|
|
5770
|
+
const data = encodeFunctionData15({
|
|
4342
5771
|
abi: POOL_ABI2,
|
|
4343
5772
|
functionName: "withdraw",
|
|
4344
5773
|
args: [params.asset, params.amount, params.to]
|
|
@@ -4353,7 +5782,7 @@ var AaveV2Adapter = class {
|
|
|
4353
5782
|
}
|
|
4354
5783
|
async getRates(asset) {
|
|
4355
5784
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4356
|
-
const client =
|
|
5785
|
+
const client = createPublicClient11({ transport: http11(this.rpcUrl) });
|
|
4357
5786
|
const result = await client.readContract({
|
|
4358
5787
|
address: this.pool,
|
|
4359
5788
|
abi: POOL_ABI2,
|
|
@@ -4399,7 +5828,7 @@ var AaveV2Adapter = class {
|
|
|
4399
5828
|
}
|
|
4400
5829
|
async getUserPosition(user) {
|
|
4401
5830
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4402
|
-
const client =
|
|
5831
|
+
const client = createPublicClient11({ transport: http11(this.rpcUrl) });
|
|
4403
5832
|
const result = await client.readContract({
|
|
4404
5833
|
address: this.pool,
|
|
4405
5834
|
abi: POOL_ABI2,
|
|
@@ -4414,8 +5843,8 @@ var AaveV2Adapter = class {
|
|
|
4414
5843
|
const collateralUsd = u256ToF642(totalCollateralBase) / 1e18;
|
|
4415
5844
|
const debtUsd = u256ToF642(totalDebtBase) / 1e18;
|
|
4416
5845
|
const ltvBps = u256ToF642(ltv);
|
|
4417
|
-
const supplies = collateralUsd > 0 ? [{ asset:
|
|
4418
|
-
const borrows = debtUsd > 0 ? [{ asset:
|
|
5846
|
+
const supplies = collateralUsd > 0 ? [{ asset: zeroAddress9, symbol: "Total Collateral", amount: totalCollateralBase, value_usd: collateralUsd }] : [];
|
|
5847
|
+
const borrows = debtUsd > 0 ? [{ asset: zeroAddress9, symbol: "Total Debt", amount: totalDebtBase, value_usd: debtUsd }] : [];
|
|
4419
5848
|
return {
|
|
4420
5849
|
protocol: this.protocolName,
|
|
4421
5850
|
user,
|
|
@@ -4426,7 +5855,7 @@ var AaveV2Adapter = class {
|
|
|
4426
5855
|
};
|
|
4427
5856
|
}
|
|
4428
5857
|
};
|
|
4429
|
-
var ORACLE_ABI2 =
|
|
5858
|
+
var ORACLE_ABI2 = parseAbi16([
|
|
4430
5859
|
"function getAssetPrice(address asset) external view returns (uint256)",
|
|
4431
5860
|
"function getAssetsPrices(address[] calldata assets) external view returns (uint256[] memory)",
|
|
4432
5861
|
"function BASE_CURRENCY_UNIT() external view returns (uint256)"
|
|
@@ -4447,7 +5876,7 @@ var AaveOracleAdapter = class {
|
|
|
4447
5876
|
return this.protocolName;
|
|
4448
5877
|
}
|
|
4449
5878
|
async getPrice(asset) {
|
|
4450
|
-
const client =
|
|
5879
|
+
const client = createPublicClient12({ transport: http12(this.rpcUrl) });
|
|
4451
5880
|
const baseUnit = await client.readContract({
|
|
4452
5881
|
address: this.oracle,
|
|
4453
5882
|
abi: ORACLE_ABI2,
|
|
@@ -4474,7 +5903,7 @@ var AaveOracleAdapter = class {
|
|
|
4474
5903
|
};
|
|
4475
5904
|
}
|
|
4476
5905
|
async getPrices(assets) {
|
|
4477
|
-
const client =
|
|
5906
|
+
const client = createPublicClient12({ transport: http12(this.rpcUrl) });
|
|
4478
5907
|
const baseUnit = await client.readContract({
|
|
4479
5908
|
address: this.oracle,
|
|
4480
5909
|
abi: ORACLE_ABI2,
|
|
@@ -4503,7 +5932,7 @@ var AaveOracleAdapter = class {
|
|
|
4503
5932
|
});
|
|
4504
5933
|
}
|
|
4505
5934
|
};
|
|
4506
|
-
var CTOKEN_ABI =
|
|
5935
|
+
var CTOKEN_ABI = parseAbi17([
|
|
4507
5936
|
"function supplyRatePerBlock() external view returns (uint256)",
|
|
4508
5937
|
"function borrowRatePerBlock() external view returns (uint256)",
|
|
4509
5938
|
"function totalSupply() external view returns (uint256)",
|
|
@@ -4530,7 +5959,7 @@ var CompoundV2Adapter = class {
|
|
|
4530
5959
|
return this.protocolName;
|
|
4531
5960
|
}
|
|
4532
5961
|
async buildSupply(params) {
|
|
4533
|
-
const data =
|
|
5962
|
+
const data = encodeFunctionData16({
|
|
4534
5963
|
abi: CTOKEN_ABI,
|
|
4535
5964
|
functionName: "mint",
|
|
4536
5965
|
args: [params.amount]
|
|
@@ -4544,7 +5973,7 @@ var CompoundV2Adapter = class {
|
|
|
4544
5973
|
};
|
|
4545
5974
|
}
|
|
4546
5975
|
async buildBorrow(params) {
|
|
4547
|
-
const data =
|
|
5976
|
+
const data = encodeFunctionData16({
|
|
4548
5977
|
abi: CTOKEN_ABI,
|
|
4549
5978
|
functionName: "borrow",
|
|
4550
5979
|
args: [params.amount]
|
|
@@ -4558,7 +5987,7 @@ var CompoundV2Adapter = class {
|
|
|
4558
5987
|
};
|
|
4559
5988
|
}
|
|
4560
5989
|
async buildRepay(params) {
|
|
4561
|
-
const data =
|
|
5990
|
+
const data = encodeFunctionData16({
|
|
4562
5991
|
abi: CTOKEN_ABI,
|
|
4563
5992
|
functionName: "repayBorrow",
|
|
4564
5993
|
args: [params.amount]
|
|
@@ -4572,7 +6001,7 @@ var CompoundV2Adapter = class {
|
|
|
4572
6001
|
};
|
|
4573
6002
|
}
|
|
4574
6003
|
async buildWithdraw(params) {
|
|
4575
|
-
const data =
|
|
6004
|
+
const data = encodeFunctionData16({
|
|
4576
6005
|
abi: CTOKEN_ABI,
|
|
4577
6006
|
functionName: "redeem",
|
|
4578
6007
|
args: [params.amount]
|
|
@@ -4587,7 +6016,7 @@ var CompoundV2Adapter = class {
|
|
|
4587
6016
|
}
|
|
4588
6017
|
async getRates(asset) {
|
|
4589
6018
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4590
|
-
const client =
|
|
6019
|
+
const client = createPublicClient13({ transport: http13(this.rpcUrl) });
|
|
4591
6020
|
const [supplyRate, borrowRate, totalSupply, totalBorrows] = await Promise.all([
|
|
4592
6021
|
client.readContract({ address: this.defaultVtoken, abi: CTOKEN_ABI, functionName: "supplyRatePerBlock" }).catch((e) => {
|
|
4593
6022
|
throw DefiError.rpcError(`[${this.protocolName}] supplyRatePerBlock failed: ${e}`);
|
|
@@ -4621,7 +6050,7 @@ var CompoundV2Adapter = class {
|
|
|
4621
6050
|
);
|
|
4622
6051
|
}
|
|
4623
6052
|
};
|
|
4624
|
-
var COMET_ABI =
|
|
6053
|
+
var COMET_ABI = parseAbi18([
|
|
4625
6054
|
"function getUtilization() external view returns (uint256)",
|
|
4626
6055
|
"function getSupplyRate(uint256 utilization) external view returns (uint64)",
|
|
4627
6056
|
"function getBorrowRate(uint256 utilization) external view returns (uint64)",
|
|
@@ -4647,7 +6076,7 @@ var CompoundV3Adapter = class {
|
|
|
4647
6076
|
return this.protocolName;
|
|
4648
6077
|
}
|
|
4649
6078
|
async buildSupply(params) {
|
|
4650
|
-
const data =
|
|
6079
|
+
const data = encodeFunctionData17({
|
|
4651
6080
|
abi: COMET_ABI,
|
|
4652
6081
|
functionName: "supply",
|
|
4653
6082
|
args: [params.asset, params.amount]
|
|
@@ -4661,7 +6090,7 @@ var CompoundV3Adapter = class {
|
|
|
4661
6090
|
};
|
|
4662
6091
|
}
|
|
4663
6092
|
async buildBorrow(params) {
|
|
4664
|
-
const data =
|
|
6093
|
+
const data = encodeFunctionData17({
|
|
4665
6094
|
abi: COMET_ABI,
|
|
4666
6095
|
functionName: "withdraw",
|
|
4667
6096
|
args: [params.asset, params.amount]
|
|
@@ -4675,7 +6104,7 @@ var CompoundV3Adapter = class {
|
|
|
4675
6104
|
};
|
|
4676
6105
|
}
|
|
4677
6106
|
async buildRepay(params) {
|
|
4678
|
-
const data =
|
|
6107
|
+
const data = encodeFunctionData17({
|
|
4679
6108
|
abi: COMET_ABI,
|
|
4680
6109
|
functionName: "supply",
|
|
4681
6110
|
args: [params.asset, params.amount]
|
|
@@ -4689,7 +6118,7 @@ var CompoundV3Adapter = class {
|
|
|
4689
6118
|
};
|
|
4690
6119
|
}
|
|
4691
6120
|
async buildWithdraw(params) {
|
|
4692
|
-
const data =
|
|
6121
|
+
const data = encodeFunctionData17({
|
|
4693
6122
|
abi: COMET_ABI,
|
|
4694
6123
|
functionName: "withdraw",
|
|
4695
6124
|
args: [params.asset, params.amount]
|
|
@@ -4704,7 +6133,7 @@ var CompoundV3Adapter = class {
|
|
|
4704
6133
|
}
|
|
4705
6134
|
async getRates(asset) {
|
|
4706
6135
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4707
|
-
const client =
|
|
6136
|
+
const client = createPublicClient14({ transport: http14(this.rpcUrl) });
|
|
4708
6137
|
const utilization = await client.readContract({
|
|
4709
6138
|
address: this.comet,
|
|
4710
6139
|
abi: COMET_ABI,
|
|
@@ -4743,7 +6172,7 @@ var CompoundV3Adapter = class {
|
|
|
4743
6172
|
);
|
|
4744
6173
|
}
|
|
4745
6174
|
};
|
|
4746
|
-
var EULER_VAULT_ABI =
|
|
6175
|
+
var EULER_VAULT_ABI = parseAbi19([
|
|
4747
6176
|
"function deposit(uint256 amount, address receiver) external returns (uint256)",
|
|
4748
6177
|
"function withdraw(uint256 amount, address receiver, address owner) external returns (uint256)",
|
|
4749
6178
|
"function borrow(uint256 amount, address receiver) external returns (uint256)",
|
|
@@ -4769,7 +6198,7 @@ var EulerV2Adapter = class {
|
|
|
4769
6198
|
return this.protocolName;
|
|
4770
6199
|
}
|
|
4771
6200
|
async buildSupply(params) {
|
|
4772
|
-
const data =
|
|
6201
|
+
const data = encodeFunctionData18({
|
|
4773
6202
|
abi: EULER_VAULT_ABI,
|
|
4774
6203
|
functionName: "deposit",
|
|
4775
6204
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -4783,7 +6212,7 @@ var EulerV2Adapter = class {
|
|
|
4783
6212
|
};
|
|
4784
6213
|
}
|
|
4785
6214
|
async buildBorrow(params) {
|
|
4786
|
-
const data =
|
|
6215
|
+
const data = encodeFunctionData18({
|
|
4787
6216
|
abi: EULER_VAULT_ABI,
|
|
4788
6217
|
functionName: "borrow",
|
|
4789
6218
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -4797,7 +6226,7 @@ var EulerV2Adapter = class {
|
|
|
4797
6226
|
};
|
|
4798
6227
|
}
|
|
4799
6228
|
async buildRepay(params) {
|
|
4800
|
-
const data =
|
|
6229
|
+
const data = encodeFunctionData18({
|
|
4801
6230
|
abi: EULER_VAULT_ABI,
|
|
4802
6231
|
functionName: "repay",
|
|
4803
6232
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -4811,7 +6240,7 @@ var EulerV2Adapter = class {
|
|
|
4811
6240
|
};
|
|
4812
6241
|
}
|
|
4813
6242
|
async buildWithdraw(params) {
|
|
4814
|
-
const data =
|
|
6243
|
+
const data = encodeFunctionData18({
|
|
4815
6244
|
abi: EULER_VAULT_ABI,
|
|
4816
6245
|
functionName: "withdraw",
|
|
4817
6246
|
args: [params.amount, params.to, params.to]
|
|
@@ -4826,7 +6255,7 @@ var EulerV2Adapter = class {
|
|
|
4826
6255
|
}
|
|
4827
6256
|
async getRates(asset) {
|
|
4828
6257
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4829
|
-
const client =
|
|
6258
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4830
6259
|
const [totalSupply, totalBorrows, interestRate] = await Promise.all([
|
|
4831
6260
|
client.readContract({ address: this.euler, abi: EULER_VAULT_ABI, functionName: "totalSupply" }).catch((e) => {
|
|
4832
6261
|
throw DefiError.rpcError(`[${this.protocolName}] totalSupply failed: ${e}`);
|
|
@@ -4860,7 +6289,7 @@ var EulerV2Adapter = class {
|
|
|
4860
6289
|
);
|
|
4861
6290
|
}
|
|
4862
6291
|
};
|
|
4863
|
-
var MORPHO_ABI =
|
|
6292
|
+
var MORPHO_ABI = parseAbi20([
|
|
4864
6293
|
"function market(bytes32 id) external view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)",
|
|
4865
6294
|
"function idToMarketParams(bytes32 id) external view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)",
|
|
4866
6295
|
"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)",
|
|
@@ -4868,29 +6297,29 @@ var MORPHO_ABI = parseAbi17([
|
|
|
4868
6297
|
"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)",
|
|
4869
6298
|
"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)"
|
|
4870
6299
|
]);
|
|
4871
|
-
var META_MORPHO_ABI =
|
|
6300
|
+
var META_MORPHO_ABI = parseAbi20([
|
|
4872
6301
|
"function supplyQueueLength() external view returns (uint256)",
|
|
4873
6302
|
"function supplyQueue(uint256 index) external view returns (bytes32)",
|
|
4874
6303
|
"function totalAssets() external view returns (uint256)",
|
|
4875
6304
|
"function totalSupply() external view returns (uint256)"
|
|
4876
6305
|
]);
|
|
4877
|
-
var IRM_ABI =
|
|
6306
|
+
var IRM_ABI = parseAbi20([
|
|
4878
6307
|
"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)"
|
|
4879
6308
|
]);
|
|
4880
6309
|
var SECONDS_PER_YEAR3 = 365.25 * 24 * 3600;
|
|
4881
|
-
function defaultMarketParams(loanToken =
|
|
6310
|
+
function defaultMarketParams(loanToken = zeroAddress10) {
|
|
4882
6311
|
return {
|
|
4883
6312
|
loanToken,
|
|
4884
|
-
collateralToken:
|
|
4885
|
-
oracle:
|
|
4886
|
-
irm:
|
|
6313
|
+
collateralToken: zeroAddress10,
|
|
6314
|
+
oracle: zeroAddress10,
|
|
6315
|
+
irm: zeroAddress10,
|
|
4887
6316
|
lltv: 0n
|
|
4888
6317
|
};
|
|
4889
6318
|
}
|
|
4890
6319
|
function decodeMarket(data) {
|
|
4891
6320
|
if (!data) return null;
|
|
4892
6321
|
try {
|
|
4893
|
-
return
|
|
6322
|
+
return decodeFunctionResult7({
|
|
4894
6323
|
abi: MORPHO_ABI,
|
|
4895
6324
|
functionName: "market",
|
|
4896
6325
|
data
|
|
@@ -4902,7 +6331,7 @@ function decodeMarket(data) {
|
|
|
4902
6331
|
function decodeMarketParams(data) {
|
|
4903
6332
|
if (!data) return null;
|
|
4904
6333
|
try {
|
|
4905
|
-
return
|
|
6334
|
+
return decodeFunctionResult7({
|
|
4906
6335
|
abi: MORPHO_ABI,
|
|
4907
6336
|
functionName: "idToMarketParams",
|
|
4908
6337
|
data
|
|
@@ -4930,7 +6359,7 @@ var MorphoBlueAdapter = class {
|
|
|
4930
6359
|
}
|
|
4931
6360
|
async buildSupply(params) {
|
|
4932
6361
|
const market = defaultMarketParams(params.asset);
|
|
4933
|
-
const data =
|
|
6362
|
+
const data = encodeFunctionData19({
|
|
4934
6363
|
abi: MORPHO_ABI,
|
|
4935
6364
|
functionName: "supply",
|
|
4936
6365
|
args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
|
|
@@ -4945,7 +6374,7 @@ var MorphoBlueAdapter = class {
|
|
|
4945
6374
|
}
|
|
4946
6375
|
async buildBorrow(params) {
|
|
4947
6376
|
const market = defaultMarketParams(params.asset);
|
|
4948
|
-
const data =
|
|
6377
|
+
const data = encodeFunctionData19({
|
|
4949
6378
|
abi: MORPHO_ABI,
|
|
4950
6379
|
functionName: "borrow",
|
|
4951
6380
|
args: [market, params.amount, 0n, params.on_behalf_of, params.on_behalf_of]
|
|
@@ -4960,7 +6389,7 @@ var MorphoBlueAdapter = class {
|
|
|
4960
6389
|
}
|
|
4961
6390
|
async buildRepay(params) {
|
|
4962
6391
|
const market = defaultMarketParams(params.asset);
|
|
4963
|
-
const data =
|
|
6392
|
+
const data = encodeFunctionData19({
|
|
4964
6393
|
abi: MORPHO_ABI,
|
|
4965
6394
|
functionName: "repay",
|
|
4966
6395
|
args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
|
|
@@ -4975,7 +6404,7 @@ var MorphoBlueAdapter = class {
|
|
|
4975
6404
|
}
|
|
4976
6405
|
async buildWithdraw(params) {
|
|
4977
6406
|
const market = defaultMarketParams(params.asset);
|
|
4978
|
-
const data =
|
|
6407
|
+
const data = encodeFunctionData19({
|
|
4979
6408
|
abi: MORPHO_ABI,
|
|
4980
6409
|
functionName: "withdraw",
|
|
4981
6410
|
args: [market, params.amount, 0n, params.to, params.to]
|
|
@@ -4994,7 +6423,7 @@ var MorphoBlueAdapter = class {
|
|
|
4994
6423
|
throw DefiError.contractError(`[${this.protocolName}] No MetaMorpho vault configured for rate query`);
|
|
4995
6424
|
}
|
|
4996
6425
|
const [queueLenRaw] = await multicallRead(this.rpcUrl, [
|
|
4997
|
-
[this.defaultVault,
|
|
6426
|
+
[this.defaultVault, encodeFunctionData19({ abi: META_MORPHO_ABI, functionName: "supplyQueueLength" })]
|
|
4998
6427
|
]).catch((e) => {
|
|
4999
6428
|
throw DefiError.rpcError(`[${this.protocolName}] supplyQueueLength failed: ${e}`);
|
|
5000
6429
|
});
|
|
@@ -5011,7 +6440,7 @@ var MorphoBlueAdapter = class {
|
|
|
5011
6440
|
};
|
|
5012
6441
|
}
|
|
5013
6442
|
const [marketIdRaw] = await multicallRead(this.rpcUrl, [
|
|
5014
|
-
[this.defaultVault,
|
|
6443
|
+
[this.defaultVault, encodeFunctionData19({ abi: META_MORPHO_ABI, functionName: "supplyQueue", args: [0n] })]
|
|
5015
6444
|
]).catch((e) => {
|
|
5016
6445
|
throw DefiError.rpcError(`[${this.protocolName}] supplyQueue(0) failed: ${e}`);
|
|
5017
6446
|
});
|
|
@@ -5020,8 +6449,8 @@ var MorphoBlueAdapter = class {
|
|
|
5020
6449
|
}
|
|
5021
6450
|
const marketId = marketIdRaw.slice(0, 66);
|
|
5022
6451
|
const [marketRaw, paramsRaw] = await multicallRead(this.rpcUrl, [
|
|
5023
|
-
[this.morpho,
|
|
5024
|
-
[this.morpho,
|
|
6452
|
+
[this.morpho, encodeFunctionData19({ abi: MORPHO_ABI, functionName: "market", args: [marketId] })],
|
|
6453
|
+
[this.morpho, encodeFunctionData19({ abi: MORPHO_ABI, functionName: "idToMarketParams", args: [marketId] })]
|
|
5025
6454
|
]).catch((e) => {
|
|
5026
6455
|
throw DefiError.rpcError(`[${this.protocolName}] market/idToMarketParams failed: ${e}`);
|
|
5027
6456
|
});
|
|
@@ -5038,7 +6467,7 @@ var MorphoBlueAdapter = class {
|
|
|
5038
6467
|
const irmMarket = { totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee };
|
|
5039
6468
|
const borrowRatePerSec = await (async () => {
|
|
5040
6469
|
const [borrowRateRaw] = await multicallRead(this.rpcUrl, [
|
|
5041
|
-
[irm,
|
|
6470
|
+
[irm, encodeFunctionData19({ abi: IRM_ABI, functionName: "borrowRateView", args: [irmMarketParams, irmMarket] })]
|
|
5042
6471
|
]).catch((e) => {
|
|
5043
6472
|
throw DefiError.rpcError(`[${this.protocolName}] borrowRateView failed: ${e}`);
|
|
5044
6473
|
});
|
|
@@ -5064,18 +6493,18 @@ var MorphoBlueAdapter = class {
|
|
|
5064
6493
|
);
|
|
5065
6494
|
}
|
|
5066
6495
|
};
|
|
5067
|
-
var BORROWER_OPS_ABI =
|
|
6496
|
+
var BORROWER_OPS_ABI = parseAbi21([
|
|
5068
6497
|
"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)",
|
|
5069
6498
|
"function adjustTrove(uint256 _troveId, uint256 _collChange, bool _isCollIncrease, uint256 _debtChange, bool _isDebtIncrease, uint256 _upperHint, uint256 _lowerHint, uint256 _maxUpfrontFee) external",
|
|
5070
6499
|
"function closeTrove(uint256 _troveId) external"
|
|
5071
6500
|
]);
|
|
5072
|
-
var TROVE_MANAGER_ABI =
|
|
6501
|
+
var TROVE_MANAGER_ABI = parseAbi21([
|
|
5073
6502
|
"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)"
|
|
5074
6503
|
]);
|
|
5075
|
-
var HINT_HELPERS_ABI =
|
|
6504
|
+
var HINT_HELPERS_ABI = parseAbi21([
|
|
5076
6505
|
"function getApproxHint(uint256 _collIndex, uint256 _interestRate, uint256 _numTrials, uint256 _inputRandomSeed) external view returns (uint256 hintId, uint256 diff, uint256 latestRandomSeed)"
|
|
5077
6506
|
]);
|
|
5078
|
-
var SORTED_TROVES_ABI =
|
|
6507
|
+
var SORTED_TROVES_ABI = parseAbi21([
|
|
5079
6508
|
"function findInsertPosition(uint256 _annualInterestRate, uint256 _prevId, uint256 _nextId) external view returns (uint256 prevId, uint256 nextId)"
|
|
5080
6509
|
]);
|
|
5081
6510
|
var FelixCdpAdapter = class {
|
|
@@ -5103,7 +6532,7 @@ var FelixCdpAdapter = class {
|
|
|
5103
6532
|
if (!this.hintHelpers || !this.sortedTroves || !this.rpcUrl) {
|
|
5104
6533
|
return [0n, 0n];
|
|
5105
6534
|
}
|
|
5106
|
-
const client =
|
|
6535
|
+
const client = createPublicClient16({ transport: http16(this.rpcUrl) });
|
|
5107
6536
|
const approxResult = await client.readContract({
|
|
5108
6537
|
address: this.hintHelpers,
|
|
5109
6538
|
abi: HINT_HELPERS_ABI,
|
|
@@ -5126,7 +6555,7 @@ var FelixCdpAdapter = class {
|
|
|
5126
6555
|
const interestRate = 50000000000000000n;
|
|
5127
6556
|
const [upperHint, lowerHint] = await this.getHints(interestRate);
|
|
5128
6557
|
const hasHints = upperHint !== 0n || lowerHint !== 0n;
|
|
5129
|
-
const data =
|
|
6558
|
+
const data = encodeFunctionData20({
|
|
5130
6559
|
abi: BORROWER_OPS_ABI,
|
|
5131
6560
|
functionName: "openTrove",
|
|
5132
6561
|
args: [
|
|
@@ -5155,7 +6584,7 @@ var FelixCdpAdapter = class {
|
|
|
5155
6584
|
async buildAdjust(params) {
|
|
5156
6585
|
const collChange = params.collateral_delta ?? 0n;
|
|
5157
6586
|
const debtChange = params.debt_delta ?? 0n;
|
|
5158
|
-
const data =
|
|
6587
|
+
const data = encodeFunctionData20({
|
|
5159
6588
|
abi: BORROWER_OPS_ABI,
|
|
5160
6589
|
functionName: "adjustTrove",
|
|
5161
6590
|
args: [
|
|
@@ -5178,7 +6607,7 @@ var FelixCdpAdapter = class {
|
|
|
5178
6607
|
};
|
|
5179
6608
|
}
|
|
5180
6609
|
async buildClose(params) {
|
|
5181
|
-
const data =
|
|
6610
|
+
const data = encodeFunctionData20({
|
|
5182
6611
|
abi: BORROWER_OPS_ABI,
|
|
5183
6612
|
functionName: "closeTrove",
|
|
5184
6613
|
args: [params.cdp_id]
|
|
@@ -5194,7 +6623,7 @@ var FelixCdpAdapter = class {
|
|
|
5194
6623
|
async getCdpInfo(cdpId) {
|
|
5195
6624
|
if (!this.rpcUrl) throw DefiError.rpcError(`[${this.protocolName}] getCdpInfo requires RPC \u2014 set HYPEREVM_RPC_URL`);
|
|
5196
6625
|
if (!this.troveManager) throw DefiError.contractError(`[${this.protocolName}] trove_manager contract not configured`);
|
|
5197
|
-
const client =
|
|
6626
|
+
const client = createPublicClient16({ transport: http16(this.rpcUrl) });
|
|
5198
6627
|
const data = await client.readContract({
|
|
5199
6628
|
address: this.troveManager,
|
|
5200
6629
|
abi: TROVE_MANAGER_ABI,
|
|
@@ -5212,13 +6641,13 @@ var FelixCdpAdapter = class {
|
|
|
5212
6641
|
protocol: this.protocolName,
|
|
5213
6642
|
cdp_id: cdpId,
|
|
5214
6643
|
collateral: {
|
|
5215
|
-
token:
|
|
6644
|
+
token: zeroAddress11,
|
|
5216
6645
|
symbol: "WHYPE",
|
|
5217
6646
|
amount: entireColl,
|
|
5218
6647
|
decimals: 18
|
|
5219
6648
|
},
|
|
5220
6649
|
debt: {
|
|
5221
|
-
token:
|
|
6650
|
+
token: zeroAddress11,
|
|
5222
6651
|
symbol: "feUSD",
|
|
5223
6652
|
amount: entireDebt,
|
|
5224
6653
|
decimals: 18
|
|
@@ -5227,7 +6656,7 @@ var FelixCdpAdapter = class {
|
|
|
5227
6656
|
};
|
|
5228
6657
|
}
|
|
5229
6658
|
};
|
|
5230
|
-
var PRICE_FEED_ABI =
|
|
6659
|
+
var PRICE_FEED_ABI = parseAbi222([
|
|
5231
6660
|
"function fetchPrice() external view returns (uint256 price, bool isNewOracleFailureDetected)",
|
|
5232
6661
|
"function lastGoodPrice() external view returns (uint256)"
|
|
5233
6662
|
]);
|
|
@@ -5253,7 +6682,7 @@ var FelixOracleAdapter = class {
|
|
|
5253
6682
|
if (asset !== this.asset && this.asset !== "0x0000000000000000000000000000000000000000") {
|
|
5254
6683
|
throw DefiError.unsupported(`[${this.protocolName}] Felix PriceFeed only supports asset ${this.asset}`);
|
|
5255
6684
|
}
|
|
5256
|
-
const client =
|
|
6685
|
+
const client = createPublicClient17({ transport: http17(this.rpcUrl) });
|
|
5257
6686
|
let priceVal;
|
|
5258
6687
|
try {
|
|
5259
6688
|
const result = await client.readContract({
|
|
@@ -5292,7 +6721,7 @@ var FelixOracleAdapter = class {
|
|
|
5292
6721
|
return results;
|
|
5293
6722
|
}
|
|
5294
6723
|
};
|
|
5295
|
-
var ERC4626_ABI =
|
|
6724
|
+
var ERC4626_ABI = parseAbi23([
|
|
5296
6725
|
"function asset() external view returns (address)",
|
|
5297
6726
|
"function totalAssets() external view returns (uint256)",
|
|
5298
6727
|
"function totalSupply() external view returns (uint256)",
|
|
@@ -5316,7 +6745,7 @@ var ERC4626VaultAdapter = class {
|
|
|
5316
6745
|
return this.protocolName;
|
|
5317
6746
|
}
|
|
5318
6747
|
async buildDeposit(assets, receiver) {
|
|
5319
|
-
const data =
|
|
6748
|
+
const data = encodeFunctionData21({
|
|
5320
6749
|
abi: ERC4626_ABI,
|
|
5321
6750
|
functionName: "deposit",
|
|
5322
6751
|
args: [assets, receiver]
|
|
@@ -5330,7 +6759,7 @@ var ERC4626VaultAdapter = class {
|
|
|
5330
6759
|
};
|
|
5331
6760
|
}
|
|
5332
6761
|
async buildWithdraw(assets, receiver, owner) {
|
|
5333
|
-
const data =
|
|
6762
|
+
const data = encodeFunctionData21({
|
|
5334
6763
|
abi: ERC4626_ABI,
|
|
5335
6764
|
functionName: "withdraw",
|
|
5336
6765
|
args: [assets, receiver, owner]
|
|
@@ -5345,7 +6774,7 @@ var ERC4626VaultAdapter = class {
|
|
|
5345
6774
|
}
|
|
5346
6775
|
async totalAssets() {
|
|
5347
6776
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5348
|
-
const client =
|
|
6777
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
5349
6778
|
return client.readContract({
|
|
5350
6779
|
address: this.vaultAddress,
|
|
5351
6780
|
abi: ERC4626_ABI,
|
|
@@ -5356,7 +6785,7 @@ var ERC4626VaultAdapter = class {
|
|
|
5356
6785
|
}
|
|
5357
6786
|
async convertToShares(assets) {
|
|
5358
6787
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5359
|
-
const client =
|
|
6788
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
5360
6789
|
return client.readContract({
|
|
5361
6790
|
address: this.vaultAddress,
|
|
5362
6791
|
abi: ERC4626_ABI,
|
|
@@ -5368,7 +6797,7 @@ var ERC4626VaultAdapter = class {
|
|
|
5368
6797
|
}
|
|
5369
6798
|
async convertToAssets(shares) {
|
|
5370
6799
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5371
|
-
const client =
|
|
6800
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
5372
6801
|
return client.readContract({
|
|
5373
6802
|
address: this.vaultAddress,
|
|
5374
6803
|
abi: ERC4626_ABI,
|
|
@@ -5380,7 +6809,7 @@ var ERC4626VaultAdapter = class {
|
|
|
5380
6809
|
}
|
|
5381
6810
|
async getVaultInfo() {
|
|
5382
6811
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5383
|
-
const client =
|
|
6812
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
5384
6813
|
const [totalAssets, totalSupply, asset] = await Promise.all([
|
|
5385
6814
|
client.readContract({ address: this.vaultAddress, abi: ERC4626_ABI, functionName: "totalAssets" }).catch((e) => {
|
|
5386
6815
|
throw DefiError.rpcError(`[${this.protocolName}] totalAssets failed: ${e}`);
|
|
@@ -5401,7 +6830,7 @@ var ERC4626VaultAdapter = class {
|
|
|
5401
6830
|
};
|
|
5402
6831
|
}
|
|
5403
6832
|
};
|
|
5404
|
-
var GENERIC_LST_ABI =
|
|
6833
|
+
var GENERIC_LST_ABI = parseAbi24([
|
|
5405
6834
|
"function stake() external payable returns (uint256)",
|
|
5406
6835
|
"function unstake(uint256 amount) external returns (uint256)"
|
|
5407
6836
|
]);
|
|
@@ -5418,7 +6847,7 @@ var GenericLstAdapter = class {
|
|
|
5418
6847
|
return this.protocolName;
|
|
5419
6848
|
}
|
|
5420
6849
|
async buildStake(params) {
|
|
5421
|
-
const data =
|
|
6850
|
+
const data = encodeFunctionData222({ abi: GENERIC_LST_ABI, functionName: "stake" });
|
|
5422
6851
|
return {
|
|
5423
6852
|
description: `[${this.protocolName}] Stake ${params.amount} HYPE`,
|
|
5424
6853
|
to: this.staking,
|
|
@@ -5428,7 +6857,7 @@ var GenericLstAdapter = class {
|
|
|
5428
6857
|
};
|
|
5429
6858
|
}
|
|
5430
6859
|
async buildUnstake(params) {
|
|
5431
|
-
const data =
|
|
6860
|
+
const data = encodeFunctionData222({
|
|
5432
6861
|
abi: GENERIC_LST_ABI,
|
|
5433
6862
|
functionName: "unstake",
|
|
5434
6863
|
args: [params.amount]
|
|
@@ -5445,11 +6874,11 @@ var GenericLstAdapter = class {
|
|
|
5445
6874
|
throw DefiError.unsupported(`[${this.protocolName}] getInfo requires RPC`);
|
|
5446
6875
|
}
|
|
5447
6876
|
};
|
|
5448
|
-
var STHYPE_ABI =
|
|
6877
|
+
var STHYPE_ABI = parseAbi25([
|
|
5449
6878
|
"function submit(address referral) external payable returns (uint256)",
|
|
5450
6879
|
"function requestWithdrawals(uint256[] amounts, address owner) external returns (uint256[] requestIds)"
|
|
5451
6880
|
]);
|
|
5452
|
-
var ERC20_ABI3 =
|
|
6881
|
+
var ERC20_ABI3 = parseAbi25([
|
|
5453
6882
|
"function totalSupply() external view returns (uint256)"
|
|
5454
6883
|
]);
|
|
5455
6884
|
var StHypeAdapter = class {
|
|
@@ -5469,10 +6898,10 @@ var StHypeAdapter = class {
|
|
|
5469
6898
|
return this.protocolName;
|
|
5470
6899
|
}
|
|
5471
6900
|
async buildStake(params) {
|
|
5472
|
-
const data =
|
|
6901
|
+
const data = encodeFunctionData23({
|
|
5473
6902
|
abi: STHYPE_ABI,
|
|
5474
6903
|
functionName: "submit",
|
|
5475
|
-
args: [
|
|
6904
|
+
args: [zeroAddress12]
|
|
5476
6905
|
});
|
|
5477
6906
|
return {
|
|
5478
6907
|
description: `[${this.protocolName}] Stake ${params.amount} HYPE for stHYPE`,
|
|
@@ -5483,7 +6912,7 @@ var StHypeAdapter = class {
|
|
|
5483
6912
|
};
|
|
5484
6913
|
}
|
|
5485
6914
|
async buildUnstake(params) {
|
|
5486
|
-
const data =
|
|
6915
|
+
const data = encodeFunctionData23({
|
|
5487
6916
|
abi: STHYPE_ABI,
|
|
5488
6917
|
functionName: "requestWithdrawals",
|
|
5489
6918
|
args: [[params.amount], params.recipient]
|
|
@@ -5498,7 +6927,7 @@ var StHypeAdapter = class {
|
|
|
5498
6927
|
}
|
|
5499
6928
|
async getInfo() {
|
|
5500
6929
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5501
|
-
const client =
|
|
6930
|
+
const client = createPublicClient19({ transport: http19(this.rpcUrl) });
|
|
5502
6931
|
const tokenAddr = this.sthypeToken ?? this.staking;
|
|
5503
6932
|
const totalSupply = await client.readContract({
|
|
5504
6933
|
address: tokenAddr,
|
|
@@ -5509,19 +6938,19 @@ var StHypeAdapter = class {
|
|
|
5509
6938
|
});
|
|
5510
6939
|
return {
|
|
5511
6940
|
protocol: this.protocolName,
|
|
5512
|
-
staked_token:
|
|
6941
|
+
staked_token: zeroAddress12,
|
|
5513
6942
|
liquid_token: tokenAddr,
|
|
5514
6943
|
exchange_rate: 1,
|
|
5515
6944
|
total_staked: totalSupply
|
|
5516
6945
|
};
|
|
5517
6946
|
}
|
|
5518
6947
|
};
|
|
5519
|
-
var KINETIQ_ABI =
|
|
6948
|
+
var KINETIQ_ABI = parseAbi26([
|
|
5520
6949
|
"function stake() external payable returns (uint256)",
|
|
5521
6950
|
"function requestUnstake(uint256 amount) external returns (uint256)",
|
|
5522
6951
|
"function totalStaked() external view returns (uint256)"
|
|
5523
6952
|
]);
|
|
5524
|
-
var ORACLE_ABI3 =
|
|
6953
|
+
var ORACLE_ABI3 = parseAbi26([
|
|
5525
6954
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
5526
6955
|
]);
|
|
5527
6956
|
var WHYPE = "0x5555555555555555555555555555555555555555";
|
|
@@ -5543,7 +6972,7 @@ var KinetiqAdapter = class {
|
|
|
5543
6972
|
return this.protocolName;
|
|
5544
6973
|
}
|
|
5545
6974
|
async buildStake(params) {
|
|
5546
|
-
const data =
|
|
6975
|
+
const data = encodeFunctionData24({ abi: KINETIQ_ABI, functionName: "stake" });
|
|
5547
6976
|
return {
|
|
5548
6977
|
description: `[${this.protocolName}] Stake ${params.amount} HYPE for kHYPE`,
|
|
5549
6978
|
to: this.staking,
|
|
@@ -5553,7 +6982,7 @@ var KinetiqAdapter = class {
|
|
|
5553
6982
|
};
|
|
5554
6983
|
}
|
|
5555
6984
|
async buildUnstake(params) {
|
|
5556
|
-
const data =
|
|
6985
|
+
const data = encodeFunctionData24({
|
|
5557
6986
|
abi: KINETIQ_ABI,
|
|
5558
6987
|
functionName: "requestUnstake",
|
|
5559
6988
|
args: [params.amount]
|
|
@@ -5568,7 +6997,7 @@ var KinetiqAdapter = class {
|
|
|
5568
6997
|
}
|
|
5569
6998
|
async getInfo() {
|
|
5570
6999
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5571
|
-
const client =
|
|
7000
|
+
const client = createPublicClient20({ transport: http20(this.rpcUrl) });
|
|
5572
7001
|
const totalStaked = await client.readContract({
|
|
5573
7002
|
address: this.staking,
|
|
5574
7003
|
abi: KINETIQ_ABI,
|
|
@@ -5583,22 +7012,22 @@ var KinetiqAdapter = class {
|
|
|
5583
7012
|
const rateF64 = hypePrice > 0n && khypePrice > 0n ? Number(khypePrice * 10n ** 18n / hypePrice) / 1e18 : 1;
|
|
5584
7013
|
return {
|
|
5585
7014
|
protocol: this.protocolName,
|
|
5586
|
-
staked_token:
|
|
7015
|
+
staked_token: zeroAddress13,
|
|
5587
7016
|
liquid_token: this.liquidToken,
|
|
5588
7017
|
exchange_rate: rateF64,
|
|
5589
7018
|
total_staked: totalStaked
|
|
5590
7019
|
};
|
|
5591
7020
|
}
|
|
5592
7021
|
};
|
|
5593
|
-
var HLP_ABI =
|
|
7022
|
+
var HLP_ABI = parseAbi27([
|
|
5594
7023
|
"function deposit(uint256 amount) external returns (uint256)",
|
|
5595
7024
|
"function withdraw(uint256 shares) external returns (uint256)"
|
|
5596
7025
|
]);
|
|
5597
|
-
var RYSK_ABI =
|
|
7026
|
+
var RYSK_ABI = parseAbi28([
|
|
5598
7027
|
"function openOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 premium)",
|
|
5599
7028
|
"function closeOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 payout)"
|
|
5600
7029
|
]);
|
|
5601
|
-
var ERC721_ABI =
|
|
7030
|
+
var ERC721_ABI = parseAbi29([
|
|
5602
7031
|
"function name() returns (string)",
|
|
5603
7032
|
"function symbol() returns (string)",
|
|
5604
7033
|
"function totalSupply() returns (uint256)",
|
|
@@ -5618,7 +7047,7 @@ var ERC721Adapter = class {
|
|
|
5618
7047
|
}
|
|
5619
7048
|
async getCollectionInfo(collection) {
|
|
5620
7049
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5621
|
-
const client =
|
|
7050
|
+
const client = createPublicClient21({ transport: http21(this.rpcUrl) });
|
|
5622
7051
|
const [collectionName, symbol, totalSupply] = await Promise.all([
|
|
5623
7052
|
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "name" }).catch((e) => {
|
|
5624
7053
|
throw DefiError.rpcError(`[${this.protocolName}] name failed: ${e}`);
|
|
@@ -5637,7 +7066,7 @@ var ERC721Adapter = class {
|
|
|
5637
7066
|
}
|
|
5638
7067
|
async getTokenInfo(collection, tokenId) {
|
|
5639
7068
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5640
|
-
const client =
|
|
7069
|
+
const client = createPublicClient21({ transport: http21(this.rpcUrl) });
|
|
5641
7070
|
const [owner, tokenUri] = await Promise.all([
|
|
5642
7071
|
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "ownerOf", args: [tokenId] }).catch((e) => {
|
|
5643
7072
|
throw DefiError.rpcError(`[${this.protocolName}] ownerOf failed: ${e}`);
|
|
@@ -5653,7 +7082,7 @@ var ERC721Adapter = class {
|
|
|
5653
7082
|
}
|
|
5654
7083
|
async getBalance(owner, collection) {
|
|
5655
7084
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
5656
|
-
const client =
|
|
7085
|
+
const client = createPublicClient21({ transport: http21(this.rpcUrl) });
|
|
5657
7086
|
return client.readContract({ address: collection, abi: ERC721_ABI, functionName: "balanceOf", args: [owner] }).catch((e) => {
|
|
5658
7087
|
throw DefiError.rpcError(`[${this.protocolName}] balanceOf failed: ${e}`);
|
|
5659
7088
|
});
|
|
@@ -5674,6 +7103,8 @@ function createDex(entry, rpcUrl) {
|
|
|
5674
7103
|
case "solidly_v2":
|
|
5675
7104
|
case "solidly_cl":
|
|
5676
7105
|
return new SolidlyAdapter(entry, rpcUrl);
|
|
7106
|
+
case "hybra":
|
|
7107
|
+
return new ThenaCLAdapter(entry, rpcUrl);
|
|
5677
7108
|
case "curve_stableswap":
|
|
5678
7109
|
return new CurveStableSwapAdapter(entry);
|
|
5679
7110
|
case "balancer_v3":
|
|
@@ -5734,11 +7165,13 @@ function createLiquidStaking(entry, rpcUrl) {
|
|
|
5734
7165
|
}
|
|
5735
7166
|
}
|
|
5736
7167
|
function createGauge(entry, rpcUrl) {
|
|
7168
|
+
if (entry.interface === "hybra" || entry.contracts?.["gauge_manager"]) {
|
|
7169
|
+
return new HybraGaugeAdapter(entry, rpcUrl);
|
|
7170
|
+
}
|
|
5737
7171
|
switch (entry.interface) {
|
|
5738
7172
|
case "solidly_v2":
|
|
5739
7173
|
case "solidly_cl":
|
|
5740
7174
|
case "algebra_v3":
|
|
5741
|
-
case "hybra":
|
|
5742
7175
|
return new SolidlyGaugeAdapter(entry, rpcUrl);
|
|
5743
7176
|
default:
|
|
5744
7177
|
throw DefiError.unsupported(`Gauge interface '${entry.interface}' not supported`);
|
|
@@ -5777,6 +7210,22 @@ function createOracleFromCdp(entry, _asset, rpcUrl) {
|
|
|
5777
7210
|
function createMerchantMoeLB(entry, rpcUrl) {
|
|
5778
7211
|
return new MerchantMoeLBAdapter(entry, rpcUrl);
|
|
5779
7212
|
}
|
|
7213
|
+
function createKittenSwapFarming(entry, rpcUrl) {
|
|
7214
|
+
const farmingCenter = entry.contracts?.["farming_center"];
|
|
7215
|
+
if (!farmingCenter) {
|
|
7216
|
+
throw new DefiError("CONTRACT_ERROR", `[${entry.name}] Missing 'farming_center' contract address`);
|
|
7217
|
+
}
|
|
7218
|
+
const eternalFarming = entry.contracts?.["eternal_farming"];
|
|
7219
|
+
if (!eternalFarming) {
|
|
7220
|
+
throw new DefiError("CONTRACT_ERROR", `[${entry.name}] Missing 'eternal_farming' contract address`);
|
|
7221
|
+
}
|
|
7222
|
+
const positionManager = entry.contracts?.["position_manager"];
|
|
7223
|
+
if (!positionManager) {
|
|
7224
|
+
throw new DefiError("CONTRACT_ERROR", `[${entry.name}] Missing 'position_manager' contract address`);
|
|
7225
|
+
}
|
|
7226
|
+
const factory = entry.contracts?.["factory"];
|
|
7227
|
+
return new KittenSwapFarmingAdapter(entry.name, farmingCenter, eternalFarming, positionManager, rpcUrl, factory);
|
|
7228
|
+
}
|
|
5780
7229
|
var DexSpotPrice = class {
|
|
5781
7230
|
/**
|
|
5782
7231
|
* Get the spot price for `token` denominated in `quoteToken` (e.g. USDC).
|
|
@@ -5849,7 +7298,7 @@ function registerDex(parent, getOpts, makeExecutor2) {
|
|
|
5849
7298
|
const result = await executor.execute(tx);
|
|
5850
7299
|
printOutput(result, getOpts());
|
|
5851
7300
|
});
|
|
5852
|
-
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) => {
|
|
7301
|
+
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) => {
|
|
5853
7302
|
const executor = makeExecutor2();
|
|
5854
7303
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
5855
7304
|
const registry = Registry.loadEmbedded();
|
|
@@ -5859,13 +7308,26 @@ function registerDex(parent, getOpts, makeExecutor2) {
|
|
|
5859
7308
|
const tokenA = opts.tokenA.startsWith("0x") ? opts.tokenA : registry.resolveToken(chainName, opts.tokenA).address;
|
|
5860
7309
|
const tokenB = opts.tokenB.startsWith("0x") ? opts.tokenB : registry.resolveToken(chainName, opts.tokenB).address;
|
|
5861
7310
|
const recipient = opts.recipient ?? process.env.DEFI_WALLET_ADDRESS ?? "0x0000000000000000000000000000000000000001";
|
|
7311
|
+
let poolAddr;
|
|
7312
|
+
if (opts.pool) {
|
|
7313
|
+
if (opts.pool.startsWith("0x")) {
|
|
7314
|
+
poolAddr = opts.pool;
|
|
7315
|
+
} else {
|
|
7316
|
+
const poolInfo = registry.resolvePool(opts.protocol, opts.pool);
|
|
7317
|
+
poolAddr = poolInfo.address;
|
|
7318
|
+
}
|
|
7319
|
+
}
|
|
5862
7320
|
const tx = await adapter.buildAddLiquidity({
|
|
5863
7321
|
protocol: protocol.name,
|
|
5864
7322
|
token_a: tokenA,
|
|
5865
7323
|
token_b: tokenB,
|
|
5866
7324
|
amount_a: BigInt(opts.amountA),
|
|
5867
7325
|
amount_b: BigInt(opts.amountB),
|
|
5868
|
-
recipient
|
|
7326
|
+
recipient,
|
|
7327
|
+
tick_lower: opts.tickLower !== void 0 ? parseInt(opts.tickLower) : void 0,
|
|
7328
|
+
tick_upper: opts.tickUpper !== void 0 ? parseInt(opts.tickUpper) : void 0,
|
|
7329
|
+
range_pct: opts.range !== void 0 ? parseFloat(opts.range) : void 0,
|
|
7330
|
+
pool: poolAddr
|
|
5869
7331
|
});
|
|
5870
7332
|
const result = await executor.execute(tx);
|
|
5871
7333
|
printOutput(result, getOpts());
|
|
@@ -5914,57 +7376,96 @@ function registerDex(parent, getOpts, makeExecutor2) {
|
|
|
5914
7376
|
|
|
5915
7377
|
// src/commands/gauge.ts
|
|
5916
7378
|
import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
7379
|
+
function resolveAccount() {
|
|
7380
|
+
const walletAddr = process.env["DEFI_WALLET_ADDRESS"];
|
|
7381
|
+
if (walletAddr) return walletAddr;
|
|
7382
|
+
const privateKey = process.env["DEFI_PRIVATE_KEY"];
|
|
7383
|
+
if (privateKey) return privateKeyToAccount2(privateKey).address;
|
|
7384
|
+
return void 0;
|
|
7385
|
+
}
|
|
5917
7386
|
function registerGauge(parent, getOpts, makeExecutor2) {
|
|
5918
|
-
const gauge = parent.command("gauge").description("Gauge operations: deposit, withdraw, claim,
|
|
5919
|
-
gauge.command("
|
|
5920
|
-
const
|
|
7387
|
+
const gauge = parent.command("gauge").description("Gauge operations: find, deposit, withdraw, claim, earned");
|
|
7388
|
+
gauge.command("discover").description("Find all pools with emission gauges (scans V2 + CL factories)").requiredOption("--protocol <protocol>", "Protocol slug").action(async (opts) => {
|
|
7389
|
+
const chainName = parent.opts().chain ?? "hyperevm";
|
|
5921
7390
|
const registry = Registry.loadEmbedded();
|
|
7391
|
+
const chain = registry.getChain(chainName);
|
|
5922
7392
|
const protocol = registry.getProtocol(opts.protocol);
|
|
5923
|
-
const adapter = createGauge(protocol);
|
|
5924
|
-
|
|
5925
|
-
const
|
|
5926
|
-
|
|
5927
|
-
printOutput(result, getOpts());
|
|
7393
|
+
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7394
|
+
if (!adapter.discoverGaugedPools) throw new Error(`${protocol.name} does not support gauge discovery`);
|
|
7395
|
+
const pools = await adapter.discoverGaugedPools();
|
|
7396
|
+
printOutput(pools, getOpts());
|
|
5928
7397
|
});
|
|
5929
|
-
gauge.command("
|
|
5930
|
-
const
|
|
7398
|
+
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) => {
|
|
7399
|
+
const chainName = parent.opts().chain ?? "hyperevm";
|
|
5931
7400
|
const registry = Registry.loadEmbedded();
|
|
7401
|
+
const chain = registry.getChain(chainName);
|
|
5932
7402
|
const protocol = registry.getProtocol(opts.protocol);
|
|
5933
|
-
const adapter = createGauge(protocol);
|
|
5934
|
-
|
|
5935
|
-
const
|
|
5936
|
-
printOutput(
|
|
7403
|
+
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7404
|
+
if (!adapter.resolveGauge) throw new Error(`${protocol.name} does not support gauge lookup`);
|
|
7405
|
+
const gaugeAddr = await adapter.resolveGauge(opts.pool);
|
|
7406
|
+
printOutput({ pool: opts.pool, gauge: gaugeAddr, protocol: protocol.name }, getOpts());
|
|
7407
|
+
});
|
|
7408
|
+
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) => {
|
|
7409
|
+
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7410
|
+
const registry = Registry.loadEmbedded();
|
|
7411
|
+
const chain = registry.getChain(chainName);
|
|
7412
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
7413
|
+
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7414
|
+
if (opts.tokenId) {
|
|
7415
|
+
if (!adapter.getPendingRewardsByTokenId) throw new Error(`${protocol.name} does not support NFT rewards`);
|
|
7416
|
+
const earned = await adapter.getPendingRewardsByTokenId(opts.gauge, BigInt(opts.tokenId));
|
|
7417
|
+
printOutput({ gauge: opts.gauge, token_id: opts.tokenId, earned: earned.toString() }, getOpts());
|
|
7418
|
+
} else {
|
|
7419
|
+
const account = resolveAccount();
|
|
7420
|
+
if (!account) throw new Error("DEFI_WALLET_ADDRESS or DEFI_PRIVATE_KEY required");
|
|
7421
|
+
const rewards = await adapter.getPendingRewards(opts.gauge, account);
|
|
7422
|
+
printOutput(rewards.map((r) => ({ token: r.token, amount: r.amount.toString() })), getOpts());
|
|
7423
|
+
}
|
|
5937
7424
|
});
|
|
5938
|
-
gauge.command("
|
|
7425
|
+
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) => {
|
|
5939
7426
|
const executor = makeExecutor2();
|
|
7427
|
+
const chainName = parent.opts().chain ?? "hyperevm";
|
|
5940
7428
|
const registry = Registry.loadEmbedded();
|
|
7429
|
+
const chain = registry.getChain(chainName);
|
|
5941
7430
|
const protocol = registry.getProtocol(opts.protocol);
|
|
5942
|
-
const adapter = createGauge(protocol,
|
|
5943
|
-
const
|
|
5944
|
-
const
|
|
5945
|
-
const tx = await adapter.
|
|
7431
|
+
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7432
|
+
const amount = opts.amount ? BigInt(opts.amount) : 0n;
|
|
7433
|
+
const tokenId = opts.tokenId ? BigInt(opts.tokenId) : void 0;
|
|
7434
|
+
const tx = await adapter.buildDeposit(opts.gauge, amount, tokenId);
|
|
5946
7435
|
const result = await executor.execute(tx);
|
|
5947
7436
|
printOutput(result, getOpts());
|
|
5948
7437
|
});
|
|
5949
|
-
gauge.command("
|
|
7438
|
+
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) => {
|
|
5950
7439
|
const executor = makeExecutor2();
|
|
7440
|
+
const chainName = parent.opts().chain ?? "hyperevm";
|
|
5951
7441
|
const registry = Registry.loadEmbedded();
|
|
7442
|
+
const chain = registry.getChain(chainName);
|
|
5952
7443
|
const protocol = registry.getProtocol(opts.protocol);
|
|
5953
|
-
const adapter = createGauge(protocol);
|
|
5954
|
-
const
|
|
7444
|
+
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7445
|
+
const amount = opts.amount ? BigInt(opts.amount) : 0n;
|
|
7446
|
+
const tokenId = opts.tokenId ? BigInt(opts.tokenId) : void 0;
|
|
7447
|
+
const tx = await adapter.buildWithdraw(opts.gauge, amount, tokenId);
|
|
5955
7448
|
const result = await executor.execute(tx);
|
|
5956
7449
|
printOutput(result, getOpts());
|
|
5957
7450
|
});
|
|
5958
|
-
gauge.command("
|
|
7451
|
+
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) => {
|
|
5959
7452
|
const executor = makeExecutor2();
|
|
7453
|
+
const chainName = parent.opts().chain ?? "hyperevm";
|
|
5960
7454
|
const registry = Registry.loadEmbedded();
|
|
7455
|
+
const chain = registry.getChain(chainName);
|
|
5961
7456
|
const protocol = registry.getProtocol(opts.protocol);
|
|
5962
|
-
const adapter = createGauge(protocol);
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
7457
|
+
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7458
|
+
if (opts.tokenId) {
|
|
7459
|
+
if (!adapter.buildClaimRewardsByTokenId) throw new Error(`${protocol.name} does not support NFT claim`);
|
|
7460
|
+
const tx = await adapter.buildClaimRewardsByTokenId(opts.gauge, BigInt(opts.tokenId));
|
|
7461
|
+
const result = await executor.execute(tx);
|
|
7462
|
+
printOutput(result, getOpts());
|
|
7463
|
+
} else {
|
|
7464
|
+
const account = resolveAccount();
|
|
7465
|
+
const tx = await adapter.buildClaimRewards(opts.gauge, account);
|
|
7466
|
+
const result = await executor.execute(tx);
|
|
7467
|
+
printOutput(result, getOpts());
|
|
7468
|
+
}
|
|
5968
7469
|
});
|
|
5969
7470
|
}
|
|
5970
7471
|
|
|
@@ -6211,9 +7712,7 @@ function resolveAsset(registry, chain, asset) {
|
|
|
6211
7712
|
return registry.resolveToken(chain, asset).address;
|
|
6212
7713
|
}
|
|
6213
7714
|
async function collectLendingRates(registry, chainName, rpc, assetAddr) {
|
|
6214
|
-
const protos = registry.getProtocolsForChain(chainName).filter(
|
|
6215
|
-
(p) => p.category === ProtocolCategory.Lending && (p.interface === "aave_v3" || p.interface === "aave_v3_isolated")
|
|
6216
|
-
);
|
|
7715
|
+
const protos = registry.getProtocolsForChain(chainName).filter((p) => p.category === ProtocolCategory.Lending);
|
|
6217
7716
|
const results = [];
|
|
6218
7717
|
let first = true;
|
|
6219
7718
|
for (const proto of protos) {
|
|
@@ -6301,7 +7800,7 @@ async function runYieldScan(registry, asset, output) {
|
|
|
6301
7800
|
} catch {
|
|
6302
7801
|
return [];
|
|
6303
7802
|
}
|
|
6304
|
-
const protos = registry.getProtocolsForChain(chainName).filter((p) => p.category === ProtocolCategory.Lending
|
|
7803
|
+
const protos = registry.getProtocolsForChain(chainName).filter((p) => p.category === ProtocolCategory.Lending);
|
|
6305
7804
|
if (protos.length === 0) return [];
|
|
6306
7805
|
const rpc = chain.effectiveRpcUrl();
|
|
6307
7806
|
const rates = [];
|
|
@@ -6384,7 +7883,7 @@ async function scanRatesForExecute(registry, asset) {
|
|
|
6384
7883
|
} catch {
|
|
6385
7884
|
return [];
|
|
6386
7885
|
}
|
|
6387
|
-
const protos = registry.getProtocolsForChain(chainName).filter((p) => p.category === ProtocolCategory.Lending
|
|
7886
|
+
const protos = registry.getProtocolsForChain(chainName).filter((p) => p.category === ProtocolCategory.Lending);
|
|
6388
7887
|
if (protos.length === 0) return [];
|
|
6389
7888
|
const rpc = chain.effectiveRpcUrl();
|
|
6390
7889
|
const rates = [];
|
|
@@ -6416,7 +7915,26 @@ async function scanRatesForExecute(registry, asset) {
|
|
|
6416
7915
|
}
|
|
6417
7916
|
function registerYield(parent, getOpts, makeExecutor2) {
|
|
6418
7917
|
const yieldCmd = parent.command("yield").description("Yield operations: compare, scan, optimize, execute");
|
|
6419
|
-
yieldCmd.
|
|
7918
|
+
yieldCmd.option("--asset <token>", "Token symbol or address", "USDC").action(async (opts) => {
|
|
7919
|
+
try {
|
|
7920
|
+
const registry = Registry.loadEmbedded();
|
|
7921
|
+
const chainName = (parent.opts().chain ?? "hyperevm").toLowerCase();
|
|
7922
|
+
const chain = registry.getChain(chainName);
|
|
7923
|
+
const rpc = chain.effectiveRpcUrl();
|
|
7924
|
+
const assetAddr = resolveAsset(registry, chainName, opts.asset);
|
|
7925
|
+
const results = await collectLendingRates(registry, chainName, rpc, assetAddr);
|
|
7926
|
+
results.sort((a, b) => b.supply_apy - a.supply_apy);
|
|
7927
|
+
const bestSupply = results[0]?.protocol ?? null;
|
|
7928
|
+
const bestBorrow = results.reduce((best, r) => {
|
|
7929
|
+
if (!best || r.borrow_variable_apy < best.borrow_variable_apy) return r;
|
|
7930
|
+
return best;
|
|
7931
|
+
}, null)?.protocol ?? null;
|
|
7932
|
+
printOutput({ asset: opts.asset, chain: chainName, rates: results, best_supply: bestSupply, best_borrow: bestBorrow }, getOpts());
|
|
7933
|
+
} catch (err) {
|
|
7934
|
+
printOutput({ error: String(err) }, getOpts());
|
|
7935
|
+
}
|
|
7936
|
+
});
|
|
7937
|
+
yieldCmd.command("compare").description("Compare lending rates across protocols for an asset").option("--asset <token>", "Token symbol or address", "USDC").action(async (opts) => {
|
|
6420
7938
|
try {
|
|
6421
7939
|
const registry = Registry.loadEmbedded();
|
|
6422
7940
|
const chainName = (parent.opts().chain ?? "hyperevm").toLowerCase();
|
|
@@ -6592,7 +8110,7 @@ function registerYield(parent, getOpts, makeExecutor2) {
|
|
|
6592
8110
|
return;
|
|
6593
8111
|
}
|
|
6594
8112
|
} else {
|
|
6595
|
-
const candidates = registry.getProtocolsForChain(chainName).filter((p) => p.category === ProtocolCategory.Lending
|
|
8113
|
+
const candidates = registry.getProtocolsForChain(chainName).filter((p) => p.category === ProtocolCategory.Lending);
|
|
6596
8114
|
if (candidates.length === 0) {
|
|
6597
8115
|
printOutput({ error: `No aave_v3 lending protocol found on ${chainName}` }, getOpts());
|
|
6598
8116
|
process.exit(1);
|
|
@@ -6784,20 +8302,20 @@ function registerYield(parent, getOpts, makeExecutor2) {
|
|
|
6784
8302
|
}
|
|
6785
8303
|
|
|
6786
8304
|
// src/commands/portfolio.ts
|
|
6787
|
-
import { encodeFunctionData as
|
|
8305
|
+
import { encodeFunctionData as encodeFunctionData28, parseAbi as parseAbi31 } from "viem";
|
|
6788
8306
|
|
|
6789
8307
|
// src/portfolio-tracker.ts
|
|
6790
8308
|
import { mkdirSync, writeFileSync, readdirSync as readdirSync2, readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
6791
8309
|
import { homedir } from "os";
|
|
6792
8310
|
import { resolve as resolve2 } from "path";
|
|
6793
|
-
import { encodeFunctionData as
|
|
6794
|
-
var ERC20_ABI4 =
|
|
8311
|
+
import { encodeFunctionData as encodeFunctionData27, parseAbi as parseAbi30 } from "viem";
|
|
8312
|
+
var ERC20_ABI4 = parseAbi30([
|
|
6795
8313
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
6796
8314
|
]);
|
|
6797
|
-
var ORACLE_ABI4 =
|
|
8315
|
+
var ORACLE_ABI4 = parseAbi30([
|
|
6798
8316
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
6799
8317
|
]);
|
|
6800
|
-
var POOL_ABI3 =
|
|
8318
|
+
var POOL_ABI3 = parseAbi30([
|
|
6801
8319
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
6802
8320
|
]);
|
|
6803
8321
|
function decodeU256Word(data, wordOffset = 0) {
|
|
@@ -6826,7 +8344,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
6826
8344
|
tokenEntries.push({ symbol: t.symbol, address: entry.address, decimals: entry.decimals });
|
|
6827
8345
|
calls.push([
|
|
6828
8346
|
entry.address,
|
|
6829
|
-
|
|
8347
|
+
encodeFunctionData27({ abi: ERC20_ABI4, functionName: "balanceOf", args: [user] })
|
|
6830
8348
|
]);
|
|
6831
8349
|
callLabels.push(`balance:${t.symbol}`);
|
|
6832
8350
|
}
|
|
@@ -6834,7 +8352,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
6834
8352
|
for (const p of lendingProtocols) {
|
|
6835
8353
|
calls.push([
|
|
6836
8354
|
p.contracts["pool"],
|
|
6837
|
-
|
|
8355
|
+
encodeFunctionData27({ abi: POOL_ABI3, functionName: "getUserAccountData", args: [user] })
|
|
6838
8356
|
]);
|
|
6839
8357
|
callLabels.push(`lending:${p.name}`);
|
|
6840
8358
|
}
|
|
@@ -6844,7 +8362,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
6844
8362
|
if (oracleAddr) {
|
|
6845
8363
|
calls.push([
|
|
6846
8364
|
oracleAddr,
|
|
6847
|
-
|
|
8365
|
+
encodeFunctionData27({ abi: ORACLE_ABI4, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
6848
8366
|
]);
|
|
6849
8367
|
callLabels.push("price:native");
|
|
6850
8368
|
}
|
|
@@ -6982,13 +8500,13 @@ function calculatePnL(current, previous) {
|
|
|
6982
8500
|
}
|
|
6983
8501
|
|
|
6984
8502
|
// src/commands/portfolio.ts
|
|
6985
|
-
var ERC20_ABI5 =
|
|
8503
|
+
var ERC20_ABI5 = parseAbi31([
|
|
6986
8504
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
6987
8505
|
]);
|
|
6988
|
-
var POOL_ABI4 =
|
|
8506
|
+
var POOL_ABI4 = parseAbi31([
|
|
6989
8507
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
6990
8508
|
]);
|
|
6991
|
-
var ORACLE_ABI5 =
|
|
8509
|
+
var ORACLE_ABI5 = parseAbi31([
|
|
6992
8510
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
6993
8511
|
]);
|
|
6994
8512
|
function decodeU2562(data, wordOffset = 0) {
|
|
@@ -7028,7 +8546,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
7028
8546
|
if (entry.address === "0x0000000000000000000000000000000000000000") continue;
|
|
7029
8547
|
calls.push([
|
|
7030
8548
|
entry.address,
|
|
7031
|
-
|
|
8549
|
+
encodeFunctionData28({ abi: ERC20_ABI5, functionName: "balanceOf", args: [user] })
|
|
7032
8550
|
]);
|
|
7033
8551
|
callLabels.push(`balance:${symbol}`);
|
|
7034
8552
|
}
|
|
@@ -7036,7 +8554,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
7036
8554
|
for (const p of lendingProtocols) {
|
|
7037
8555
|
calls.push([
|
|
7038
8556
|
p.contracts["pool"],
|
|
7039
|
-
|
|
8557
|
+
encodeFunctionData28({ abi: POOL_ABI4, functionName: "getUserAccountData", args: [user] })
|
|
7040
8558
|
]);
|
|
7041
8559
|
callLabels.push(`lending:${p.name}`);
|
|
7042
8560
|
}
|
|
@@ -7046,7 +8564,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
7046
8564
|
if (oracleAddr) {
|
|
7047
8565
|
calls.push([
|
|
7048
8566
|
oracleAddr,
|
|
7049
|
-
|
|
8567
|
+
encodeFunctionData28({ abi: ORACLE_ABI5, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
7050
8568
|
]);
|
|
7051
8569
|
callLabels.push("price:native");
|
|
7052
8570
|
}
|
|
@@ -7408,14 +8926,14 @@ function registerAlert(parent, getOpts) {
|
|
|
7408
8926
|
}
|
|
7409
8927
|
|
|
7410
8928
|
// src/commands/scan.ts
|
|
7411
|
-
import { encodeFunctionData as
|
|
7412
|
-
var AAVE_ORACLE_ABI =
|
|
8929
|
+
import { encodeFunctionData as encodeFunctionData29, parseAbi as parseAbi33 } from "viem";
|
|
8930
|
+
var AAVE_ORACLE_ABI = parseAbi33([
|
|
7413
8931
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
7414
8932
|
]);
|
|
7415
|
-
var UNIV2_ROUTER_ABI =
|
|
8933
|
+
var UNIV2_ROUTER_ABI = parseAbi33([
|
|
7416
8934
|
"function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory)"
|
|
7417
8935
|
]);
|
|
7418
|
-
var VTOKEN_ABI =
|
|
8936
|
+
var VTOKEN_ABI = parseAbi33([
|
|
7419
8937
|
"function exchangeRateStored() external view returns (uint256)"
|
|
7420
8938
|
]);
|
|
7421
8939
|
var STABLECOINS = /* @__PURE__ */ new Set(["USDC", "USDT", "DAI", "USDT0"]);
|
|
@@ -7525,7 +9043,7 @@ function registerScan(parent, getOpts) {
|
|
|
7525
9043
|
callTypes.push({ kind: "oracle", oracle: oracle.name, token: token.symbol, oracleDecimals: oracle.decimals });
|
|
7526
9044
|
calls.push([
|
|
7527
9045
|
oracle.addr,
|
|
7528
|
-
|
|
9046
|
+
encodeFunctionData29({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })
|
|
7529
9047
|
]);
|
|
7530
9048
|
}
|
|
7531
9049
|
}
|
|
@@ -7536,7 +9054,7 @@ function registerScan(parent, getOpts) {
|
|
|
7536
9054
|
callTypes.push({ kind: "dex", token: token.symbol, outDecimals: quoteStable.decimals });
|
|
7537
9055
|
calls.push([
|
|
7538
9056
|
dexRouter,
|
|
7539
|
-
|
|
9057
|
+
encodeFunctionData29({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [amountIn, path] })
|
|
7540
9058
|
]);
|
|
7541
9059
|
}
|
|
7542
9060
|
}
|
|
@@ -7545,7 +9063,7 @@ function registerScan(parent, getOpts) {
|
|
|
7545
9063
|
callTypes.push({ kind: "stable", from: "USDC", to: "USDT", outDecimals: usdt.decimals });
|
|
7546
9064
|
calls.push([
|
|
7547
9065
|
dexRouter,
|
|
7548
|
-
|
|
9066
|
+
encodeFunctionData29({
|
|
7549
9067
|
abi: UNIV2_ROUTER_ABI,
|
|
7550
9068
|
functionName: "getAmountsOut",
|
|
7551
9069
|
args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]]
|
|
@@ -7554,7 +9072,7 @@ function registerScan(parent, getOpts) {
|
|
|
7554
9072
|
callTypes.push({ kind: "stable", from: "USDT", to: "USDC", outDecimals: usdc.decimals });
|
|
7555
9073
|
calls.push([
|
|
7556
9074
|
dexRouter,
|
|
7557
|
-
|
|
9075
|
+
encodeFunctionData29({
|
|
7558
9076
|
abi: UNIV2_ROUTER_ABI,
|
|
7559
9077
|
functionName: "getAmountsOut",
|
|
7560
9078
|
args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]]
|
|
@@ -7565,7 +9083,7 @@ function registerScan(parent, getOpts) {
|
|
|
7565
9083
|
for (const fork of compoundForks) {
|
|
7566
9084
|
for (const { key, addr } of fork.vtokens) {
|
|
7567
9085
|
callTypes.push({ kind: "exchangeRate", protocol: fork.name, vtoken: key });
|
|
7568
|
-
calls.push([addr,
|
|
9086
|
+
calls.push([addr, encodeFunctionData29({ abi: VTOKEN_ABI, functionName: "exchangeRateStored", args: [] })]);
|
|
7569
9087
|
}
|
|
7570
9088
|
}
|
|
7571
9089
|
}
|
|
@@ -7783,22 +9301,22 @@ async function runAllChains(registry, patterns, oracleThreshold, stableThreshold
|
|
|
7783
9301
|
for (const oracle of oracles) {
|
|
7784
9302
|
for (const token of scanTokens) {
|
|
7785
9303
|
cts.push({ kind: "oracle", oracle: oracle.name, token: token.symbol, dec: oracle.decimals });
|
|
7786
|
-
calls.push([oracle.addr,
|
|
9304
|
+
calls.push([oracle.addr, encodeFunctionData29({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })]);
|
|
7787
9305
|
}
|
|
7788
9306
|
}
|
|
7789
9307
|
if (dexRouter) {
|
|
7790
9308
|
for (const token of scanTokens) {
|
|
7791
9309
|
const path = wrappedNative && token.address.toLowerCase() === wrappedNative.toLowerCase() ? [token.address, quoteStable.address] : wrappedNative ? [token.address, wrappedNative, quoteStable.address] : [token.address, quoteStable.address];
|
|
7792
9310
|
cts.push({ kind: "dex", token: token.symbol, dec: quoteStable.decimals });
|
|
7793
|
-
calls.push([dexRouter,
|
|
9311
|
+
calls.push([dexRouter, encodeFunctionData29({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(token.decimals), path] })]);
|
|
7794
9312
|
}
|
|
7795
9313
|
}
|
|
7796
9314
|
}
|
|
7797
9315
|
if (doStable && usdc && usdt && dexRouter) {
|
|
7798
9316
|
cts.push({ kind: "stable", from: "USDC", to: "USDT", dec: usdt.decimals });
|
|
7799
|
-
calls.push([dexRouter,
|
|
9317
|
+
calls.push([dexRouter, encodeFunctionData29({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]] })]);
|
|
7800
9318
|
cts.push({ kind: "stable", from: "USDT", to: "USDC", dec: usdc.decimals });
|
|
7801
|
-
calls.push([dexRouter,
|
|
9319
|
+
calls.push([dexRouter, encodeFunctionData29({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]] })]);
|
|
7802
9320
|
}
|
|
7803
9321
|
if (calls.length === 0) return null;
|
|
7804
9322
|
const ct0 = Date.now();
|
|
@@ -7926,14 +9444,14 @@ function registerArb(parent, getOpts, makeExecutor2) {
|
|
|
7926
9444
|
}
|
|
7927
9445
|
|
|
7928
9446
|
// src/commands/positions.ts
|
|
7929
|
-
import { encodeFunctionData as
|
|
7930
|
-
var ERC20_ABI6 =
|
|
9447
|
+
import { encodeFunctionData as encodeFunctionData30, parseAbi as parseAbi34 } from "viem";
|
|
9448
|
+
var ERC20_ABI6 = parseAbi34([
|
|
7931
9449
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
7932
9450
|
]);
|
|
7933
|
-
var POOL_ABI5 =
|
|
9451
|
+
var POOL_ABI5 = parseAbi34([
|
|
7934
9452
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
7935
9453
|
]);
|
|
7936
|
-
var ORACLE_ABI6 =
|
|
9454
|
+
var ORACLE_ABI6 = parseAbi34([
|
|
7937
9455
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
7938
9456
|
]);
|
|
7939
9457
|
function round22(x) {
|
|
@@ -7962,7 +9480,7 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7962
9480
|
callTypes.push({ kind: "token", symbol: token.symbol, decimals: token.decimals });
|
|
7963
9481
|
calls.push([
|
|
7964
9482
|
token.address,
|
|
7965
|
-
|
|
9483
|
+
encodeFunctionData30({ abi: ERC20_ABI6, functionName: "balanceOf", args: [user] })
|
|
7966
9484
|
]);
|
|
7967
9485
|
}
|
|
7968
9486
|
}
|
|
@@ -7970,14 +9488,14 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7970
9488
|
callTypes.push({ kind: "lending", protocol: name, iface });
|
|
7971
9489
|
calls.push([
|
|
7972
9490
|
pool,
|
|
7973
|
-
|
|
9491
|
+
encodeFunctionData30({ abi: POOL_ABI5, functionName: "getUserAccountData", args: [user] })
|
|
7974
9492
|
]);
|
|
7975
9493
|
}
|
|
7976
9494
|
if (oracleAddr) {
|
|
7977
9495
|
callTypes.push({ kind: "native_price" });
|
|
7978
9496
|
calls.push([
|
|
7979
9497
|
oracleAddr,
|
|
7980
|
-
|
|
9498
|
+
encodeFunctionData30({ abi: ORACLE_ABI6, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
7981
9499
|
]);
|
|
7982
9500
|
}
|
|
7983
9501
|
if (calls.length === 0) return null;
|
|
@@ -8270,14 +9788,14 @@ function registerPrice(parent, getOpts) {
|
|
|
8270
9788
|
}
|
|
8271
9789
|
|
|
8272
9790
|
// src/commands/wallet.ts
|
|
8273
|
-
import { createPublicClient as
|
|
9791
|
+
import { createPublicClient as createPublicClient23, http as http23, formatEther } from "viem";
|
|
8274
9792
|
function registerWallet(parent, getOpts) {
|
|
8275
9793
|
const wallet = parent.command("wallet").description("Wallet management");
|
|
8276
9794
|
wallet.command("balance").description("Show native token balance").requiredOption("--address <address>", "Wallet address to query").action(async (opts) => {
|
|
8277
9795
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
8278
9796
|
const registry = Registry.loadEmbedded();
|
|
8279
9797
|
const chain = registry.getChain(chainName);
|
|
8280
|
-
const client =
|
|
9798
|
+
const client = createPublicClient23({ transport: http23(chain.effectiveRpcUrl()) });
|
|
8281
9799
|
const balance = await client.getBalance({ address: opts.address });
|
|
8282
9800
|
printOutput({
|
|
8283
9801
|
chain: chain.name,
|
|
@@ -8294,14 +9812,14 @@ function registerWallet(parent, getOpts) {
|
|
|
8294
9812
|
}
|
|
8295
9813
|
|
|
8296
9814
|
// src/commands/token.ts
|
|
8297
|
-
import { createPublicClient as
|
|
9815
|
+
import { createPublicClient as createPublicClient24, http as http24, maxUint256 } from "viem";
|
|
8298
9816
|
function registerToken(parent, getOpts, makeExecutor2) {
|
|
8299
9817
|
const token = parent.command("token").description("Token operations: approve, allowance, transfer, balance");
|
|
8300
9818
|
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) => {
|
|
8301
9819
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
8302
9820
|
const registry = Registry.loadEmbedded();
|
|
8303
9821
|
const chain = registry.getChain(chainName);
|
|
8304
|
-
const client =
|
|
9822
|
+
const client = createPublicClient24({ transport: http24(chain.effectiveRpcUrl()) });
|
|
8305
9823
|
const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
|
|
8306
9824
|
const [balance, symbol, decimals] = await Promise.all([
|
|
8307
9825
|
client.readContract({ address: tokenAddr, abi: erc20Abi, functionName: "balanceOf", args: [opts.owner] }),
|
|
@@ -8330,7 +9848,7 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
8330
9848
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
8331
9849
|
const registry = Registry.loadEmbedded();
|
|
8332
9850
|
const chain = registry.getChain(chainName);
|
|
8333
|
-
const client =
|
|
9851
|
+
const client = createPublicClient24({ transport: http24(chain.effectiveRpcUrl()) });
|
|
8334
9852
|
const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
|
|
8335
9853
|
const allowance = await client.readContract({
|
|
8336
9854
|
address: tokenAddr,
|
|
@@ -8352,8 +9870,8 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
8352
9870
|
}
|
|
8353
9871
|
|
|
8354
9872
|
// src/commands/whales.ts
|
|
8355
|
-
import { encodeFunctionData as
|
|
8356
|
-
var POOL_ABI6 =
|
|
9873
|
+
import { encodeFunctionData as encodeFunctionData31, parseAbi as parseAbi35 } from "viem";
|
|
9874
|
+
var POOL_ABI6 = parseAbi35([
|
|
8357
9875
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
8358
9876
|
]);
|
|
8359
9877
|
function round24(x) {
|
|
@@ -8464,7 +9982,7 @@ function registerWhales(parent, getOpts) {
|
|
|
8464
9982
|
for (const { pool } of lendingPools) {
|
|
8465
9983
|
calls.push([
|
|
8466
9984
|
pool,
|
|
8467
|
-
|
|
9985
|
+
encodeFunctionData31({ abi: POOL_ABI6, functionName: "getUserAccountData", args: [whale.address] })
|
|
8468
9986
|
]);
|
|
8469
9987
|
}
|
|
8470
9988
|
}
|
|
@@ -8892,11 +10410,11 @@ function registerBridge(parent, getOpts) {
|
|
|
8892
10410
|
const amountUsdc = Number(BigInt(opts.amount)) / 1e6;
|
|
8893
10411
|
const { fee, maxFeeSubunits } = await getCctpFeeEstimate(srcDomain, dstDomain, amountUsdc);
|
|
8894
10412
|
const recipientPadded = `0x${"0".repeat(24)}${recipient.replace("0x", "").toLowerCase()}`;
|
|
8895
|
-
const { encodeFunctionData:
|
|
8896
|
-
const tokenMessengerAbi =
|
|
10413
|
+
const { encodeFunctionData: encodeFunctionData33, parseAbi: parseAbi36 } = await import("viem");
|
|
10414
|
+
const tokenMessengerAbi = parseAbi36([
|
|
8897
10415
|
"function depositForBurn(uint256 amount, uint32 destinationDomain, bytes32 mintRecipient, address burnToken, bytes32 destinationCaller, uint256 maxFee, uint32 minFinalityThreshold) external returns (uint64 nonce)"
|
|
8898
10416
|
]);
|
|
8899
|
-
const data =
|
|
10417
|
+
const data = encodeFunctionData33({
|
|
8900
10418
|
abi: tokenMessengerAbi,
|
|
8901
10419
|
functionName: "depositForBurn",
|
|
8902
10420
|
args: [
|
|
@@ -9089,6 +10607,124 @@ function registerFarm(parent, getOpts, makeExecutor2) {
|
|
|
9089
10607
|
});
|
|
9090
10608
|
}
|
|
9091
10609
|
|
|
10610
|
+
// src/commands/farming.ts
|
|
10611
|
+
import { privateKeyToAccount as privateKeyToAccount3 } from "viem/accounts";
|
|
10612
|
+
function registerFarming(parent, getOpts, makeExecutor2) {
|
|
10613
|
+
const farming = parent.command("farming").description("Algebra eternal farming operations (KittenSwap): enter, exit, collect rewards, claim, discover");
|
|
10614
|
+
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) => {
|
|
10615
|
+
const executor = makeExecutor2();
|
|
10616
|
+
const registry = Registry.loadEmbedded();
|
|
10617
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
10618
|
+
const chainName = parent.opts().chain;
|
|
10619
|
+
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10620
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
10621
|
+
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10622
|
+
const owner = resolveOwner(opts.owner);
|
|
10623
|
+
const tx = await adapter.buildEnterFarming(
|
|
10624
|
+
BigInt(opts.tokenId),
|
|
10625
|
+
opts.pool,
|
|
10626
|
+
owner
|
|
10627
|
+
);
|
|
10628
|
+
const result = await executor.execute(tx);
|
|
10629
|
+
printOutput(result, getOpts());
|
|
10630
|
+
});
|
|
10631
|
+
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) => {
|
|
10632
|
+
const executor = makeExecutor2();
|
|
10633
|
+
const registry = Registry.loadEmbedded();
|
|
10634
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
10635
|
+
const chainName = parent.opts().chain;
|
|
10636
|
+
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10637
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
10638
|
+
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10639
|
+
const tx = await adapter.buildExitFarming(
|
|
10640
|
+
BigInt(opts.tokenId),
|
|
10641
|
+
opts.pool
|
|
10642
|
+
);
|
|
10643
|
+
const result = await executor.execute(tx);
|
|
10644
|
+
printOutput(result, getOpts());
|
|
10645
|
+
});
|
|
10646
|
+
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) => {
|
|
10647
|
+
const executor = makeExecutor2();
|
|
10648
|
+
const registry = Registry.loadEmbedded();
|
|
10649
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
10650
|
+
const chainName = parent.opts().chain;
|
|
10651
|
+
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10652
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
10653
|
+
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10654
|
+
const owner = resolveOwner(opts.owner);
|
|
10655
|
+
const tx = await adapter.buildCollectRewards(
|
|
10656
|
+
BigInt(opts.tokenId),
|
|
10657
|
+
opts.pool,
|
|
10658
|
+
owner
|
|
10659
|
+
);
|
|
10660
|
+
const result = await executor.execute(tx);
|
|
10661
|
+
printOutput(result, getOpts());
|
|
10662
|
+
});
|
|
10663
|
+
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) => {
|
|
10664
|
+
const executor = makeExecutor2();
|
|
10665
|
+
const registry = Registry.loadEmbedded();
|
|
10666
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
10667
|
+
const chainName = parent.opts().chain;
|
|
10668
|
+
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10669
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
10670
|
+
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10671
|
+
const owner = resolveOwner(opts.owner);
|
|
10672
|
+
const tx = await adapter.buildClaimReward(owner);
|
|
10673
|
+
const result = await executor.execute(tx);
|
|
10674
|
+
printOutput(result, getOpts());
|
|
10675
|
+
});
|
|
10676
|
+
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) => {
|
|
10677
|
+
const registry = Registry.loadEmbedded();
|
|
10678
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
10679
|
+
const chainName = parent.opts().chain;
|
|
10680
|
+
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10681
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
10682
|
+
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10683
|
+
const rewards = await adapter.getPendingRewards(
|
|
10684
|
+
BigInt(opts.tokenId),
|
|
10685
|
+
opts.pool
|
|
10686
|
+
);
|
|
10687
|
+
printOutput(
|
|
10688
|
+
{
|
|
10689
|
+
tokenId: opts.tokenId,
|
|
10690
|
+
pool: opts.pool,
|
|
10691
|
+
reward_kitten: rewards.reward.toString(),
|
|
10692
|
+
bonus_reward_whype: rewards.bonusReward.toString()
|
|
10693
|
+
},
|
|
10694
|
+
getOpts()
|
|
10695
|
+
);
|
|
10696
|
+
});
|
|
10697
|
+
farming.command("discover").description("Discover all pools with active KittenSwap farming incentives").requiredOption("--protocol <protocol>", "Protocol slug (e.g. kittenswap)").action(async (opts) => {
|
|
10698
|
+
const registry = Registry.loadEmbedded();
|
|
10699
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
10700
|
+
const chainName = parent.opts().chain;
|
|
10701
|
+
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10702
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
10703
|
+
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10704
|
+
const pools = await adapter.discoverFarmingPools();
|
|
10705
|
+
const output = pools.map((p) => ({
|
|
10706
|
+
pool: p.pool,
|
|
10707
|
+
nonce: p.key.nonce.toString(),
|
|
10708
|
+
total_reward: p.totalReward.toString(),
|
|
10709
|
+
bonus_reward: p.bonusReward.toString(),
|
|
10710
|
+
active: p.active
|
|
10711
|
+
}));
|
|
10712
|
+
printOutput(output, getOpts());
|
|
10713
|
+
});
|
|
10714
|
+
}
|
|
10715
|
+
function resolveOwner(optOwner) {
|
|
10716
|
+
if (optOwner) return optOwner;
|
|
10717
|
+
const walletAddr = process.env["DEFI_WALLET_ADDRESS"];
|
|
10718
|
+
if (walletAddr) return walletAddr;
|
|
10719
|
+
const privateKey = process.env["DEFI_PRIVATE_KEY"];
|
|
10720
|
+
if (privateKey) {
|
|
10721
|
+
return privateKeyToAccount3(privateKey).address;
|
|
10722
|
+
}
|
|
10723
|
+
throw new Error(
|
|
10724
|
+
"--owner, DEFI_WALLET_ADDRESS, or DEFI_PRIVATE_KEY is required to resolve reward recipient"
|
|
10725
|
+
);
|
|
10726
|
+
}
|
|
10727
|
+
|
|
9092
10728
|
// src/commands/setup.ts
|
|
9093
10729
|
import pc2 from "picocolors";
|
|
9094
10730
|
import { createInterface } from "readline";
|
|
@@ -9137,8 +10773,8 @@ function isValidPrivateKey(s) {
|
|
|
9137
10773
|
}
|
|
9138
10774
|
async function deriveAddress(privateKey) {
|
|
9139
10775
|
try {
|
|
9140
|
-
const { privateKeyToAccount:
|
|
9141
|
-
const account =
|
|
10776
|
+
const { privateKeyToAccount: privateKeyToAccount4 } = await import("viem/accounts");
|
|
10777
|
+
const account = privateKeyToAccount4(privateKey);
|
|
9142
10778
|
return account.address;
|
|
9143
10779
|
} catch {
|
|
9144
10780
|
return null;
|
|
@@ -9345,7 +10981,7 @@ var BANNER = `
|
|
|
9345
10981
|
\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
|
|
9346
10982
|
\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
|
|
9347
10983
|
|
|
9348
|
-
2 chains \xB7
|
|
10984
|
+
2 chains \xB7 23 protocols \xB7 by HypurrQuant
|
|
9349
10985
|
|
|
9350
10986
|
Scan exploits, swap tokens, bridge assets, track whales,
|
|
9351
10987
|
compare yields \u2014 all from your terminal.
|
|
@@ -9385,6 +11021,7 @@ registerSwap(program, getOutputMode, makeExecutor);
|
|
|
9385
11021
|
registerBridge(program, getOutputMode);
|
|
9386
11022
|
registerNft(program, getOutputMode);
|
|
9387
11023
|
registerFarm(program, getOutputMode, makeExecutor);
|
|
11024
|
+
registerFarming(program, getOutputMode, makeExecutor);
|
|
9388
11025
|
registerLB(program, getOutputMode, makeExecutor);
|
|
9389
11026
|
registerSetup(program);
|
|
9390
11027
|
program.command("agent").description("Agent mode: read JSON commands from stdin (for AI agents)").action(async () => {
|