@hypurrquant/defi-cli 0.2.5 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1200 -330
- package/dist/index.js.map +1 -1
- package/dist/main.js +1186 -319
- package/dist/main.js.map +1 -1
- package/dist/mcp-server.js +1043 -284
- package/dist/mcp-server.js.map +1 -1
- package/package.json +1 -1
- package/config/protocols/liquid_staking/kinetiq.toml +0 -12
- package/config/protocols/liquid_staking/sthype.toml +0 -13
package/dist/main.js
CHANGED
|
@@ -707,6 +707,16 @@ function parse(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
|
|
|
707
707
|
|
|
708
708
|
// ../defi-core/dist/index.js
|
|
709
709
|
import { existsSync } from "fs";
|
|
710
|
+
var TxStatus = /* @__PURE__ */ ((TxStatus2) => {
|
|
711
|
+
TxStatus2["DryRun"] = "dry_run";
|
|
712
|
+
TxStatus2["Simulated"] = "simulated";
|
|
713
|
+
TxStatus2["SimulationFailed"] = "simulation_failed";
|
|
714
|
+
TxStatus2["NeedsApproval"] = "needs_approval";
|
|
715
|
+
TxStatus2["Pending"] = "pending";
|
|
716
|
+
TxStatus2["Confirmed"] = "confirmed";
|
|
717
|
+
TxStatus2["Failed"] = "failed";
|
|
718
|
+
return TxStatus2;
|
|
719
|
+
})(TxStatus || {});
|
|
710
720
|
var InterestRateMode = /* @__PURE__ */ ((InterestRateMode2) => {
|
|
711
721
|
InterestRateMode2["Variable"] = "variable";
|
|
712
722
|
InterestRateMode2["Stable"] = "stable";
|
|
@@ -1135,6 +1145,46 @@ var Executor = class _Executor {
|
|
|
1135
1145
|
const client = createPublicClient2({ transport: http2(rpcUrl) });
|
|
1136
1146
|
const privateKey = process.env["DEFI_PRIVATE_KEY"];
|
|
1137
1147
|
const from = privateKey ? privateKeyToAccount(privateKey).address : "0x0000000000000000000000000000000000000001";
|
|
1148
|
+
if (tx.approvals && tx.approvals.length > 0) {
|
|
1149
|
+
const pendingApprovals = [];
|
|
1150
|
+
for (const approval of tx.approvals) {
|
|
1151
|
+
try {
|
|
1152
|
+
const allowance = await client.readContract({
|
|
1153
|
+
address: approval.token,
|
|
1154
|
+
abi: ERC20_ABI,
|
|
1155
|
+
functionName: "allowance",
|
|
1156
|
+
args: [from, approval.spender]
|
|
1157
|
+
});
|
|
1158
|
+
if (allowance < approval.amount) {
|
|
1159
|
+
pendingApprovals.push({
|
|
1160
|
+
token: approval.token,
|
|
1161
|
+
spender: approval.spender,
|
|
1162
|
+
needed: approval.amount.toString(),
|
|
1163
|
+
current: allowance.toString()
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
} catch {
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
if (pendingApprovals.length > 0) {
|
|
1170
|
+
return {
|
|
1171
|
+
tx_hash: void 0,
|
|
1172
|
+
status: TxStatus.NeedsApproval,
|
|
1173
|
+
gas_used: tx.gas_estimate,
|
|
1174
|
+
description: tx.description,
|
|
1175
|
+
details: {
|
|
1176
|
+
to: tx.to,
|
|
1177
|
+
from,
|
|
1178
|
+
data: tx.data,
|
|
1179
|
+
value: tx.value.toString(),
|
|
1180
|
+
mode: "simulated",
|
|
1181
|
+
result: "needs_approval",
|
|
1182
|
+
pending_approvals: pendingApprovals,
|
|
1183
|
+
hint: "Use --broadcast to auto-approve and execute"
|
|
1184
|
+
}
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1138
1188
|
try {
|
|
1139
1189
|
await client.call({ to: tx.to, data: tx.data, value: tx.value, account: from });
|
|
1140
1190
|
const gasEstimate = await this.estimateGasWithBuffer(rpcUrl, tx, from);
|
|
@@ -1800,26 +1850,33 @@ import { encodeFunctionData as encodeFunctionData22, parseAbi as parseAbi22, cre
|
|
|
1800
1850
|
import { encodeFunctionData as encodeFunctionData32, parseAbi as parseAbi32, createPublicClient as createPublicClient32, http as http32, decodeAbiParameters as decodeAbiParameters3, concatHex, zeroAddress } from "viem";
|
|
1801
1851
|
import { encodeFunctionData as encodeFunctionData42, parseAbi as parseAbi42, zeroAddress as zeroAddress2 } from "viem";
|
|
1802
1852
|
import { encodeFunctionData as encodeFunctionData5, parseAbi as parseAbi5 } from "viem";
|
|
1803
|
-
import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6,
|
|
1853
|
+
import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6, decodeAbiParameters as decodeAbiParameters4 } from "viem";
|
|
1804
1854
|
import { encodeFunctionData as encodeFunctionData7, parseAbi as parseAbi7, zeroAddress as zeroAddress3 } from "viem";
|
|
1805
|
-
import { createPublicClient as
|
|
1806
|
-
import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9, createPublicClient as
|
|
1807
|
-
import {
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
import { createPublicClient as
|
|
1815
|
-
import { createPublicClient as
|
|
1816
|
-
import { createPublicClient as
|
|
1817
|
-
import { parseAbi as
|
|
1818
|
-
import { createPublicClient as
|
|
1819
|
-
import { createPublicClient as
|
|
1820
|
-
import { parseAbi as
|
|
1855
|
+
import { createPublicClient as createPublicClient42, encodeFunctionData as encodeFunctionData8, http as http42, parseAbi as parseAbi8, zeroAddress as zeroAddress4 } from "viem";
|
|
1856
|
+
import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9, createPublicClient as createPublicClient5, http as http5 } from "viem";
|
|
1857
|
+
import {
|
|
1858
|
+
encodeFunctionData as encodeFunctionData10,
|
|
1859
|
+
decodeFunctionResult as decodeFunctionResult22,
|
|
1860
|
+
parseAbi as parseAbi10,
|
|
1861
|
+
createPublicClient as createPublicClient6,
|
|
1862
|
+
http as http6
|
|
1863
|
+
} from "viem";
|
|
1864
|
+
import { createPublicClient as createPublicClient7, http as http7, parseAbi as parseAbi11, encodeFunctionData as encodeFunctionData11, decodeFunctionResult as decodeFunctionResult3, zeroAddress as zeroAddress5 } from "viem";
|
|
1865
|
+
import { createPublicClient as createPublicClient8, http as http8, parseAbi as parseAbi12, encodeFunctionData as encodeFunctionData12, zeroAddress as zeroAddress6 } from "viem";
|
|
1866
|
+
import { createPublicClient as createPublicClient9, http as http9, parseAbi as parseAbi13 } from "viem";
|
|
1867
|
+
import { createPublicClient as createPublicClient10, http as http10, parseAbi as parseAbi14, encodeFunctionData as encodeFunctionData13 } from "viem";
|
|
1868
|
+
import { createPublicClient as createPublicClient11, http as http11, parseAbi as parseAbi15, encodeFunctionData as encodeFunctionData14 } from "viem";
|
|
1869
|
+
import { createPublicClient as createPublicClient12, http as http12, parseAbi as parseAbi16, encodeFunctionData as encodeFunctionData15 } from "viem";
|
|
1870
|
+
import { parseAbi as parseAbi17, encodeFunctionData as encodeFunctionData16, decodeFunctionResult as decodeFunctionResult4, zeroAddress as zeroAddress7 } from "viem";
|
|
1871
|
+
import { createPublicClient as createPublicClient13, http as http13, parseAbi as parseAbi18, encodeFunctionData as encodeFunctionData17, zeroAddress as zeroAddress8 } from "viem";
|
|
1872
|
+
import { createPublicClient as createPublicClient14, http as http14, parseAbi as parseAbi19 } from "viem";
|
|
1873
|
+
import { createPublicClient as createPublicClient15, http as http15, parseAbi as parseAbi20, encodeFunctionData as encodeFunctionData18 } from "viem";
|
|
1874
|
+
import { parseAbi as parseAbi21, encodeFunctionData as encodeFunctionData19 } from "viem";
|
|
1875
|
+
import { createPublicClient as createPublicClient16, http as http16, parseAbi as parseAbi222, encodeFunctionData as encodeFunctionData20, zeroAddress as zeroAddress9 } from "viem";
|
|
1876
|
+
import { createPublicClient as createPublicClient17, http as http17, parseAbi as parseAbi23, encodeFunctionData as encodeFunctionData21, zeroAddress as zeroAddress10 } from "viem";
|
|
1821
1877
|
import { parseAbi as parseAbi24, encodeFunctionData as encodeFunctionData222 } from "viem";
|
|
1822
|
-
import {
|
|
1878
|
+
import { parseAbi as parseAbi25, encodeFunctionData as encodeFunctionData23 } from "viem";
|
|
1879
|
+
import { createPublicClient as createPublicClient18, http as http18, parseAbi as parseAbi26 } from "viem";
|
|
1823
1880
|
var DEFAULT_FEE = 3e3;
|
|
1824
1881
|
var swapRouterAbi = parseAbi4([
|
|
1825
1882
|
"struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; }",
|
|
@@ -2636,15 +2693,6 @@ var SolidlyAdapter = class {
|
|
|
2636
2693
|
approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
|
|
2637
2694
|
};
|
|
2638
2695
|
}
|
|
2639
|
-
async callGetAmountsOut(client, callData) {
|
|
2640
|
-
const result = await client.call({ to: this.router, data: callData });
|
|
2641
|
-
if (!result.data) return 0n;
|
|
2642
|
-
const [amounts] = decodeAbiParameters4(
|
|
2643
|
-
[{ name: "amounts", type: "uint256[]" }],
|
|
2644
|
-
result.data
|
|
2645
|
-
);
|
|
2646
|
-
return amounts.length >= 2 ? amounts[amounts.length - 1] : 0n;
|
|
2647
|
-
}
|
|
2648
2696
|
encodeV1(params, stable) {
|
|
2649
2697
|
return encodeFunctionData6({
|
|
2650
2698
|
abi: abi4,
|
|
@@ -2661,7 +2709,6 @@ var SolidlyAdapter = class {
|
|
|
2661
2709
|
}
|
|
2662
2710
|
async quote(params) {
|
|
2663
2711
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
2664
|
-
const client = createPublicClient42({ transport: http42(this.rpcUrl) });
|
|
2665
2712
|
const candidates = [
|
|
2666
2713
|
{ callData: this.encodeV1(params, false), stable: false },
|
|
2667
2714
|
{ callData: this.encodeV1(params, true), stable: true }
|
|
@@ -2672,16 +2719,26 @@ var SolidlyAdapter = class {
|
|
|
2672
2719
|
{ callData: this.encodeV2(params, true), stable: true }
|
|
2673
2720
|
);
|
|
2674
2721
|
}
|
|
2675
|
-
const
|
|
2676
|
-
|
|
2722
|
+
const rawResults = await multicallRead(
|
|
2723
|
+
this.rpcUrl,
|
|
2724
|
+
candidates.map((c) => [this.router, c.callData])
|
|
2677
2725
|
);
|
|
2678
2726
|
let bestOut = 0n;
|
|
2679
2727
|
let bestStable = false;
|
|
2680
|
-
for (let i = 0; i <
|
|
2681
|
-
const
|
|
2682
|
-
if (
|
|
2683
|
-
|
|
2684
|
-
|
|
2728
|
+
for (let i = 0; i < rawResults.length; i++) {
|
|
2729
|
+
const raw = rawResults[i];
|
|
2730
|
+
if (!raw) continue;
|
|
2731
|
+
try {
|
|
2732
|
+
const [amounts] = decodeAbiParameters4(
|
|
2733
|
+
[{ name: "amounts", type: "uint256[]" }],
|
|
2734
|
+
raw
|
|
2735
|
+
);
|
|
2736
|
+
const out = amounts.length >= 2 ? amounts[amounts.length - 1] : 0n;
|
|
2737
|
+
if (out > bestOut) {
|
|
2738
|
+
bestOut = out;
|
|
2739
|
+
bestStable = candidates[i].stable;
|
|
2740
|
+
}
|
|
2741
|
+
} catch {
|
|
2685
2742
|
}
|
|
2686
2743
|
}
|
|
2687
2744
|
if (bestOut === 0n) {
|
|
@@ -2893,7 +2950,7 @@ var SolidlyGaugeAdapter = class {
|
|
|
2893
2950
|
async buildClaimRewards(gauge, account) {
|
|
2894
2951
|
if (account && this.rpcUrl) {
|
|
2895
2952
|
try {
|
|
2896
|
-
const client =
|
|
2953
|
+
const client = createPublicClient42({ transport: http42(this.rpcUrl) });
|
|
2897
2954
|
const listLen = await client.readContract({
|
|
2898
2955
|
address: gauge,
|
|
2899
2956
|
abi: gaugeAbi,
|
|
@@ -3151,7 +3208,7 @@ var MasterChefAdapter = class {
|
|
|
3151
3208
|
if (!this.rpcUrl) {
|
|
3152
3209
|
throw DefiError.unsupported(`[${this.protocolName}] getPendingRewards requires RPC`);
|
|
3153
3210
|
}
|
|
3154
|
-
const client =
|
|
3211
|
+
const client = createPublicClient5({ transport: http5(this.rpcUrl) });
|
|
3155
3212
|
const rewards = await client.readContract({
|
|
3156
3213
|
address: this.masterchef,
|
|
3157
3214
|
abi: masterchefAbi,
|
|
@@ -3165,7 +3222,682 @@ var MasterChefAdapter = class {
|
|
|
3165
3222
|
}));
|
|
3166
3223
|
}
|
|
3167
3224
|
};
|
|
3168
|
-
var
|
|
3225
|
+
var lbRouterAbi = parseAbi10([
|
|
3226
|
+
"struct LiquidityParameters { address tokenX; address tokenY; uint256 binStep; uint256 amountX; uint256 amountY; uint256 amountXMin; uint256 amountYMin; uint256 activeIdDesired; uint256 idSlippage; int256[] deltaIds; uint256[] distributionX; uint256[] distributionY; address to; address refundTo; uint256 deadline; }",
|
|
3227
|
+
"function addLiquidity(LiquidityParameters calldata liquidityParameters) external returns (uint256 amountXAdded, uint256 amountYAdded, uint256 amountXLeft, uint256 amountYLeft, uint256[] memory depositIds, uint256[] memory liquidityMinted)",
|
|
3228
|
+
"function removeLiquidity(address tokenX, address tokenY, uint16 binStep, uint256 amountXMin, uint256 amountYMin, uint256[] memory ids, uint256[] memory amounts, address to, uint256 deadline) external returns (uint256 amountX, uint256 amountY)"
|
|
3229
|
+
]);
|
|
3230
|
+
var lbFactoryAbi = parseAbi10([
|
|
3231
|
+
"function getNumberOfLBPairs() external view returns (uint256)",
|
|
3232
|
+
"function getLBPairAtIndex(uint256 index) external view returns (address)"
|
|
3233
|
+
]);
|
|
3234
|
+
var lbPairAbi = parseAbi10([
|
|
3235
|
+
"function getLBHooksParameters() external view returns (bytes32)",
|
|
3236
|
+
"function getActiveId() external view returns (uint24)",
|
|
3237
|
+
"function getBinStep() external view returns (uint16)",
|
|
3238
|
+
"function getTokenX() external view returns (address)",
|
|
3239
|
+
"function getTokenY() external view returns (address)",
|
|
3240
|
+
"function balanceOf(address account, uint256 id) external view returns (uint256)",
|
|
3241
|
+
"function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory)"
|
|
3242
|
+
]);
|
|
3243
|
+
var lbRewarderAbi = parseAbi10([
|
|
3244
|
+
"function getRewardToken() external view returns (address)",
|
|
3245
|
+
"function getRewardedRange() external view returns (uint256 minBinId, uint256 maxBinId)",
|
|
3246
|
+
"function getPendingRewards(address user, uint256[] calldata ids) external view returns (uint256 pendingRewards)",
|
|
3247
|
+
"function claim(address user, uint256[] calldata ids) external",
|
|
3248
|
+
"function getPid() external view returns (uint256)",
|
|
3249
|
+
"function isStopped() external view returns (bool)",
|
|
3250
|
+
"function getLBPair() external view returns (address)",
|
|
3251
|
+
"function getMasterChef() external view returns (address)"
|
|
3252
|
+
]);
|
|
3253
|
+
var masterChefAbi = parseAbi10([
|
|
3254
|
+
"function getMoePerSecond() external view returns (uint256)",
|
|
3255
|
+
"function getTreasuryShare() external view returns (uint256)",
|
|
3256
|
+
"function getStaticShare() external view returns (uint256)",
|
|
3257
|
+
"function getVeMoe() external view returns (address)"
|
|
3258
|
+
]);
|
|
3259
|
+
var veMoeAbi = parseAbi10([
|
|
3260
|
+
"function getWeight(uint256 pid) external view returns (uint256)",
|
|
3261
|
+
"function getTotalWeight() external view returns (uint256)",
|
|
3262
|
+
"function getTopPoolIds() external view returns (uint256[] memory)"
|
|
3263
|
+
]);
|
|
3264
|
+
var lbPairBinAbi = parseAbi10([
|
|
3265
|
+
"function getBin(uint24 id) external view returns (uint128 reserveX, uint128 reserveY)",
|
|
3266
|
+
"function getActiveId() external view returns (uint24)"
|
|
3267
|
+
]);
|
|
3268
|
+
var lbQuoterAbi2 = parseAbi10([
|
|
3269
|
+
"function findBestPathFromAmountIn(address[] calldata route, uint128 amountIn) external view returns ((address[] route, address[] pairs, uint256[] binSteps, uint256[] versions, uint128[] amounts, uint128[] virtualAmountsWithoutSlippage, uint128[] fees))"
|
|
3270
|
+
]);
|
|
3271
|
+
var erc20Abi2 = parseAbi10([
|
|
3272
|
+
"function symbol() external view returns (string)"
|
|
3273
|
+
]);
|
|
3274
|
+
var _addressAbi = parseAbi10(["function f() external view returns (address)"]);
|
|
3275
|
+
function decodeAddressResult(data) {
|
|
3276
|
+
if (!data) return null;
|
|
3277
|
+
try {
|
|
3278
|
+
return decodeFunctionResult22({ abi: _addressAbi, functionName: "f", data });
|
|
3279
|
+
} catch {
|
|
3280
|
+
return null;
|
|
3281
|
+
}
|
|
3282
|
+
}
|
|
3283
|
+
var _uint256Abi = parseAbi10(["function f() external view returns (uint256)"]);
|
|
3284
|
+
function decodeUint256Result(data) {
|
|
3285
|
+
if (!data) return null;
|
|
3286
|
+
try {
|
|
3287
|
+
return decodeFunctionResult22({ abi: _uint256Abi, functionName: "f", data });
|
|
3288
|
+
} catch {
|
|
3289
|
+
return null;
|
|
3290
|
+
}
|
|
3291
|
+
}
|
|
3292
|
+
var _boolAbi = parseAbi10(["function f() external view returns (bool)"]);
|
|
3293
|
+
function decodeBoolResult(data) {
|
|
3294
|
+
if (!data) return null;
|
|
3295
|
+
try {
|
|
3296
|
+
return decodeFunctionResult22({ abi: _boolAbi, functionName: "f", data });
|
|
3297
|
+
} catch {
|
|
3298
|
+
return null;
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
function decodeStringResult(data) {
|
|
3302
|
+
if (!data) return "?";
|
|
3303
|
+
try {
|
|
3304
|
+
return decodeFunctionResult22({ abi: erc20Abi2, functionName: "symbol", data });
|
|
3305
|
+
} catch {
|
|
3306
|
+
return "?";
|
|
3307
|
+
}
|
|
3308
|
+
}
|
|
3309
|
+
var _rangeAbi = parseAbi10(["function f() external view returns (uint256 minBinId, uint256 maxBinId)"]);
|
|
3310
|
+
function decodeRangeResult(data) {
|
|
3311
|
+
if (!data) return null;
|
|
3312
|
+
try {
|
|
3313
|
+
return decodeFunctionResult22({ abi: _rangeAbi, functionName: "f", data });
|
|
3314
|
+
} catch {
|
|
3315
|
+
return null;
|
|
3316
|
+
}
|
|
3317
|
+
}
|
|
3318
|
+
var _binAbi = parseAbi10(["function f() external view returns (uint128 reserveX, uint128 reserveY)"]);
|
|
3319
|
+
function decodeBinResult(data) {
|
|
3320
|
+
if (!data) return null;
|
|
3321
|
+
try {
|
|
3322
|
+
return decodeFunctionResult22({ abi: _binAbi, functionName: "f", data });
|
|
3323
|
+
} catch {
|
|
3324
|
+
return null;
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3327
|
+
var _uint256ArrayAbi = parseAbi10(["function f() external view returns (uint256[] memory)"]);
|
|
3328
|
+
function decodeUint256ArrayResult(data) {
|
|
3329
|
+
if (!data) return null;
|
|
3330
|
+
try {
|
|
3331
|
+
return decodeFunctionResult22({ abi: _uint256ArrayAbi, functionName: "f", data });
|
|
3332
|
+
} catch {
|
|
3333
|
+
return null;
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
function extractRewarderAddress(hooksParams) {
|
|
3337
|
+
if (!hooksParams || hooksParams === "0x0000000000000000000000000000000000000000000000000000000000000000") {
|
|
3338
|
+
return null;
|
|
3339
|
+
}
|
|
3340
|
+
const hex = hooksParams.slice(2);
|
|
3341
|
+
if (hex.length < 64) return null;
|
|
3342
|
+
const addrHex = hex.slice(24, 64);
|
|
3343
|
+
if (addrHex === "0000000000000000000000000000000000000000") return null;
|
|
3344
|
+
return `0x${addrHex}`;
|
|
3345
|
+
}
|
|
3346
|
+
function buildUniformDistribution(deltaIds) {
|
|
3347
|
+
const PRECISION = 10n ** 18n;
|
|
3348
|
+
const n = deltaIds.length;
|
|
3349
|
+
const xBins = deltaIds.filter((d) => d >= 0).length;
|
|
3350
|
+
const yBins = deltaIds.filter((d) => d <= 0).length;
|
|
3351
|
+
const distributionX = [];
|
|
3352
|
+
const distributionY = [];
|
|
3353
|
+
for (const delta of deltaIds) {
|
|
3354
|
+
const xShare = delta >= 0 && xBins > 0 ? PRECISION / BigInt(xBins) : 0n;
|
|
3355
|
+
const yShare = delta <= 0 && yBins > 0 ? PRECISION / BigInt(yBins) : 0n;
|
|
3356
|
+
distributionX.push(xShare);
|
|
3357
|
+
distributionY.push(yShare);
|
|
3358
|
+
}
|
|
3359
|
+
const xSum = distributionX.reduce((a, b) => a + b, 0n);
|
|
3360
|
+
const ySum = distributionY.reduce((a, b) => a + b, 0n);
|
|
3361
|
+
if (xSum > 0n && xSum !== PRECISION) {
|
|
3362
|
+
const firstX = distributionX.findIndex((v) => v > 0n);
|
|
3363
|
+
if (firstX !== -1) distributionX[firstX] += PRECISION - xSum;
|
|
3364
|
+
}
|
|
3365
|
+
if (ySum > 0n && ySum !== PRECISION) {
|
|
3366
|
+
const firstY = distributionY.findIndex((v) => v > 0n);
|
|
3367
|
+
if (firstY !== -1) distributionY[firstY] += PRECISION - ySum;
|
|
3368
|
+
}
|
|
3369
|
+
return { distributionX, distributionY };
|
|
3370
|
+
}
|
|
3371
|
+
var MerchantMoeLBAdapter = class {
|
|
3372
|
+
protocolName;
|
|
3373
|
+
lbRouter;
|
|
3374
|
+
lbFactory;
|
|
3375
|
+
lbQuoter;
|
|
3376
|
+
rpcUrl;
|
|
3377
|
+
/** WMNT address (lb_mid_wmnt in config) used for MOE price routing */
|
|
3378
|
+
wmnt;
|
|
3379
|
+
/** USDT address (lb_mid_usdt in config) used for MNT/USD price routing */
|
|
3380
|
+
usdt;
|
|
3381
|
+
constructor(entry, rpcUrl) {
|
|
3382
|
+
this.protocolName = entry.name;
|
|
3383
|
+
const lbRouter = entry.contracts?.["lb_router"];
|
|
3384
|
+
if (!lbRouter) {
|
|
3385
|
+
throw new DefiError("CONTRACT_ERROR", "Missing 'lb_router' contract address");
|
|
3386
|
+
}
|
|
3387
|
+
const lbFactory = entry.contracts?.["lb_factory"];
|
|
3388
|
+
if (!lbFactory) {
|
|
3389
|
+
throw new DefiError("CONTRACT_ERROR", "Missing 'lb_factory' contract address");
|
|
3390
|
+
}
|
|
3391
|
+
this.lbRouter = lbRouter;
|
|
3392
|
+
this.lbFactory = lbFactory;
|
|
3393
|
+
this.lbQuoter = entry.contracts?.["lb_quoter"];
|
|
3394
|
+
this.wmnt = entry.contracts?.["lb_mid_wmnt"];
|
|
3395
|
+
this.usdt = entry.contracts?.["lb_mid_usdt"];
|
|
3396
|
+
this.rpcUrl = rpcUrl;
|
|
3397
|
+
}
|
|
3398
|
+
name() {
|
|
3399
|
+
return this.protocolName;
|
|
3400
|
+
}
|
|
3401
|
+
requireRpc() {
|
|
3402
|
+
if (!this.rpcUrl) {
|
|
3403
|
+
throw DefiError.rpcError(`[${this.protocolName}] RPC URL required`);
|
|
3404
|
+
}
|
|
3405
|
+
return this.rpcUrl;
|
|
3406
|
+
}
|
|
3407
|
+
/**
|
|
3408
|
+
* Build an addLiquidity transaction for a Liquidity Book pair.
|
|
3409
|
+
* Distributes tokenX/tokenY uniformly across active bin ± numBins.
|
|
3410
|
+
*/
|
|
3411
|
+
async buildAddLiquidity(params) {
|
|
3412
|
+
const numBins = params.numBins ?? 5;
|
|
3413
|
+
const deadline = params.deadline ?? BigInt("18446744073709551615");
|
|
3414
|
+
let activeIdDesired = params.activeIdDesired;
|
|
3415
|
+
if (activeIdDesired === void 0) {
|
|
3416
|
+
const rpcUrl = this.requireRpc();
|
|
3417
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3418
|
+
const activeId = await client.readContract({
|
|
3419
|
+
address: params.pool,
|
|
3420
|
+
abi: lbPairAbi,
|
|
3421
|
+
functionName: "getActiveId"
|
|
3422
|
+
});
|
|
3423
|
+
activeIdDesired = activeId;
|
|
3424
|
+
}
|
|
3425
|
+
const deltaIds = [];
|
|
3426
|
+
for (let d = -numBins; d <= numBins; d++) {
|
|
3427
|
+
deltaIds.push(d);
|
|
3428
|
+
}
|
|
3429
|
+
const { distributionX, distributionY } = buildUniformDistribution(deltaIds);
|
|
3430
|
+
const data = encodeFunctionData10({
|
|
3431
|
+
abi: lbRouterAbi,
|
|
3432
|
+
functionName: "addLiquidity",
|
|
3433
|
+
args: [
|
|
3434
|
+
{
|
|
3435
|
+
tokenX: params.tokenX,
|
|
3436
|
+
tokenY: params.tokenY,
|
|
3437
|
+
binStep: BigInt(params.binStep),
|
|
3438
|
+
amountX: params.amountX,
|
|
3439
|
+
amountY: params.amountY,
|
|
3440
|
+
amountXMin: 0n,
|
|
3441
|
+
amountYMin: 0n,
|
|
3442
|
+
activeIdDesired: BigInt(activeIdDesired),
|
|
3443
|
+
idSlippage: BigInt(numBins + 2),
|
|
3444
|
+
deltaIds: deltaIds.map(BigInt),
|
|
3445
|
+
distributionX,
|
|
3446
|
+
distributionY,
|
|
3447
|
+
to: params.recipient,
|
|
3448
|
+
refundTo: params.recipient,
|
|
3449
|
+
deadline
|
|
3450
|
+
}
|
|
3451
|
+
]
|
|
3452
|
+
});
|
|
3453
|
+
return {
|
|
3454
|
+
description: `[${this.protocolName}] LB addLiquidity ${params.amountX} tokenX + ${params.amountY} tokenY across ${deltaIds.length} bins`,
|
|
3455
|
+
to: this.lbRouter,
|
|
3456
|
+
data,
|
|
3457
|
+
value: 0n,
|
|
3458
|
+
gas_estimate: 8e5,
|
|
3459
|
+
approvals: [
|
|
3460
|
+
{ token: params.tokenX, spender: this.lbRouter, amount: params.amountX },
|
|
3461
|
+
{ token: params.tokenY, spender: this.lbRouter, amount: params.amountY }
|
|
3462
|
+
]
|
|
3463
|
+
};
|
|
3464
|
+
}
|
|
3465
|
+
/**
|
|
3466
|
+
* Build a removeLiquidity transaction for specific LB bins.
|
|
3467
|
+
*/
|
|
3468
|
+
async buildRemoveLiquidity(params) {
|
|
3469
|
+
const deadline = params.deadline ?? BigInt("18446744073709551615");
|
|
3470
|
+
const data = encodeFunctionData10({
|
|
3471
|
+
abi: lbRouterAbi,
|
|
3472
|
+
functionName: "removeLiquidity",
|
|
3473
|
+
args: [
|
|
3474
|
+
params.tokenX,
|
|
3475
|
+
params.tokenY,
|
|
3476
|
+
params.binStep,
|
|
3477
|
+
params.amountXMin ?? 0n,
|
|
3478
|
+
params.amountYMin ?? 0n,
|
|
3479
|
+
params.binIds.map(BigInt),
|
|
3480
|
+
params.amounts,
|
|
3481
|
+
params.recipient,
|
|
3482
|
+
deadline
|
|
3483
|
+
]
|
|
3484
|
+
});
|
|
3485
|
+
return {
|
|
3486
|
+
description: `[${this.protocolName}] LB removeLiquidity from ${params.binIds.length} bins`,
|
|
3487
|
+
to: this.lbRouter,
|
|
3488
|
+
data,
|
|
3489
|
+
value: 0n,
|
|
3490
|
+
gas_estimate: 6e5
|
|
3491
|
+
};
|
|
3492
|
+
}
|
|
3493
|
+
/**
|
|
3494
|
+
* Auto-detect bin IDs for a pool from the rewarder's rewarded range.
|
|
3495
|
+
* Falls back to active bin ± 50 scan if no rewarder exists.
|
|
3496
|
+
*/
|
|
3497
|
+
async autoDetectBins(pool) {
|
|
3498
|
+
const rpcUrl = this.requireRpc();
|
|
3499
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3500
|
+
const hooksParams = await client.readContract({
|
|
3501
|
+
address: pool,
|
|
3502
|
+
abi: lbPairAbi,
|
|
3503
|
+
functionName: "getLBHooksParameters"
|
|
3504
|
+
});
|
|
3505
|
+
const rewarder = extractRewarderAddress(hooksParams);
|
|
3506
|
+
if (rewarder) {
|
|
3507
|
+
const range = await client.readContract({
|
|
3508
|
+
address: rewarder,
|
|
3509
|
+
abi: lbRewarderAbi,
|
|
3510
|
+
functionName: "getRewardedRange"
|
|
3511
|
+
});
|
|
3512
|
+
const min = Number(range[0]);
|
|
3513
|
+
const max = Number(range[1]);
|
|
3514
|
+
const ids2 = [];
|
|
3515
|
+
for (let b = min; b <= max; b++) ids2.push(b);
|
|
3516
|
+
return ids2;
|
|
3517
|
+
}
|
|
3518
|
+
const activeId = await client.readContract({
|
|
3519
|
+
address: pool,
|
|
3520
|
+
abi: lbPairAbi,
|
|
3521
|
+
functionName: "getActiveId"
|
|
3522
|
+
});
|
|
3523
|
+
const ids = [];
|
|
3524
|
+
for (let b = activeId - 50; b <= activeId + 50; b++) ids.push(b);
|
|
3525
|
+
return ids;
|
|
3526
|
+
}
|
|
3527
|
+
/**
|
|
3528
|
+
* Get pending MOE rewards for a user across specified bin IDs.
|
|
3529
|
+
* If binIds is omitted, auto-detects from the rewarder's rewarded range.
|
|
3530
|
+
* Reads the rewarder address from the pool's hooks parameters.
|
|
3531
|
+
*/
|
|
3532
|
+
async getPendingRewards(user, pool, binIds) {
|
|
3533
|
+
const rpcUrl = this.requireRpc();
|
|
3534
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3535
|
+
const hooksParams = await client.readContract({
|
|
3536
|
+
address: pool,
|
|
3537
|
+
abi: lbPairAbi,
|
|
3538
|
+
functionName: "getLBHooksParameters"
|
|
3539
|
+
});
|
|
3540
|
+
const rewarder = extractRewarderAddress(hooksParams);
|
|
3541
|
+
if (!rewarder) {
|
|
3542
|
+
return [];
|
|
3543
|
+
}
|
|
3544
|
+
let resolvedBinIds = binIds;
|
|
3545
|
+
if (!resolvedBinIds || resolvedBinIds.length === 0) {
|
|
3546
|
+
const range = await client.readContract({
|
|
3547
|
+
address: rewarder,
|
|
3548
|
+
abi: lbRewarderAbi,
|
|
3549
|
+
functionName: "getRewardedRange"
|
|
3550
|
+
});
|
|
3551
|
+
const min = Number(range[0]);
|
|
3552
|
+
const max = Number(range[1]);
|
|
3553
|
+
resolvedBinIds = [];
|
|
3554
|
+
for (let b = min; b <= max; b++) resolvedBinIds.push(b);
|
|
3555
|
+
}
|
|
3556
|
+
const [pending, rewardToken] = await Promise.all([
|
|
3557
|
+
client.readContract({
|
|
3558
|
+
address: rewarder,
|
|
3559
|
+
abi: lbRewarderAbi,
|
|
3560
|
+
functionName: "getPendingRewards",
|
|
3561
|
+
args: [user, resolvedBinIds.map(BigInt)]
|
|
3562
|
+
}),
|
|
3563
|
+
client.readContract({
|
|
3564
|
+
address: rewarder,
|
|
3565
|
+
abi: lbRewarderAbi,
|
|
3566
|
+
functionName: "getRewardToken"
|
|
3567
|
+
})
|
|
3568
|
+
]);
|
|
3569
|
+
return [
|
|
3570
|
+
{
|
|
3571
|
+
token: rewardToken,
|
|
3572
|
+
symbol: "MOE",
|
|
3573
|
+
amount: pending
|
|
3574
|
+
}
|
|
3575
|
+
];
|
|
3576
|
+
}
|
|
3577
|
+
/**
|
|
3578
|
+
* Build a claim rewards transaction for specific LB bins.
|
|
3579
|
+
* If binIds is omitted, auto-detects from the rewarder's rewarded range.
|
|
3580
|
+
*/
|
|
3581
|
+
async buildClaimRewards(user, pool, binIds) {
|
|
3582
|
+
const rpcUrl = this.requireRpc();
|
|
3583
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3584
|
+
const hooksParams = await client.readContract({
|
|
3585
|
+
address: pool,
|
|
3586
|
+
abi: lbPairAbi,
|
|
3587
|
+
functionName: "getLBHooksParameters"
|
|
3588
|
+
});
|
|
3589
|
+
const rewarder = extractRewarderAddress(hooksParams);
|
|
3590
|
+
if (!rewarder) {
|
|
3591
|
+
throw new DefiError("CONTRACT_ERROR", `[${this.protocolName}] Pool ${pool} has no active rewarder`);
|
|
3592
|
+
}
|
|
3593
|
+
let resolvedBinIds = binIds;
|
|
3594
|
+
if (!resolvedBinIds || resolvedBinIds.length === 0) {
|
|
3595
|
+
const range = await client.readContract({
|
|
3596
|
+
address: rewarder,
|
|
3597
|
+
abi: lbRewarderAbi,
|
|
3598
|
+
functionName: "getRewardedRange"
|
|
3599
|
+
});
|
|
3600
|
+
const min = Number(range[0]);
|
|
3601
|
+
const max = Number(range[1]);
|
|
3602
|
+
resolvedBinIds = [];
|
|
3603
|
+
for (let b = min; b <= max; b++) resolvedBinIds.push(b);
|
|
3604
|
+
}
|
|
3605
|
+
const data = encodeFunctionData10({
|
|
3606
|
+
abi: lbRewarderAbi,
|
|
3607
|
+
functionName: "claim",
|
|
3608
|
+
args: [user, resolvedBinIds.map(BigInt)]
|
|
3609
|
+
});
|
|
3610
|
+
return {
|
|
3611
|
+
description: `[${this.protocolName}] LB claim rewards for ${resolvedBinIds.length} bins`,
|
|
3612
|
+
to: rewarder,
|
|
3613
|
+
data,
|
|
3614
|
+
value: 0n,
|
|
3615
|
+
gas_estimate: 3e5
|
|
3616
|
+
};
|
|
3617
|
+
}
|
|
3618
|
+
/**
|
|
3619
|
+
* Discover all active rewarded LB pools by iterating the factory.
|
|
3620
|
+
* Uses 7 multicall batches to minimise RPC round-trips and avoid 429s.
|
|
3621
|
+
*
|
|
3622
|
+
* Batch 1: getNumberOfLBPairs(), then getLBPairAtIndex(i) for all i
|
|
3623
|
+
* Batch 2: getLBHooksParameters() for all pairs → extract rewarder addresses
|
|
3624
|
+
* Batch 3: isStopped/getRewardedRange/getRewardToken/getPid/getMasterChef for each rewarder
|
|
3625
|
+
* Batch 4: getTokenX/getTokenY for each rewarded pair, then symbol() for unique tokens
|
|
3626
|
+
* Batch 5: Bootstrap MasterChef→VeMoe, then getMoePerSecond/getTreasuryShare/getStaticShare/getTotalWeight/getTopPoolIds
|
|
3627
|
+
* Batch 6: VeMoe.getWeight(pid) for each rewarded pool
|
|
3628
|
+
* Batch 7: Pool.getBin(binId) for all bins in rewarded range of each pool
|
|
3629
|
+
* Price: LB Quoter findBestPathFromAmountIn for MOE/WMNT and WMNT/USDT prices
|
|
3630
|
+
*/
|
|
3631
|
+
async discoverRewardedPools() {
|
|
3632
|
+
const rpcUrl = this.requireRpc();
|
|
3633
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3634
|
+
const pairCount = await client.readContract({
|
|
3635
|
+
address: this.lbFactory,
|
|
3636
|
+
abi: lbFactoryAbi,
|
|
3637
|
+
functionName: "getNumberOfLBPairs"
|
|
3638
|
+
});
|
|
3639
|
+
const count = Number(pairCount);
|
|
3640
|
+
if (count === 0) return [];
|
|
3641
|
+
const batch1Calls = Array.from({ length: count }, (_, i) => [
|
|
3642
|
+
this.lbFactory,
|
|
3643
|
+
encodeFunctionData10({ abi: lbFactoryAbi, functionName: "getLBPairAtIndex", args: [BigInt(i)] })
|
|
3644
|
+
]);
|
|
3645
|
+
const batch1Results = await multicallRead(rpcUrl, batch1Calls);
|
|
3646
|
+
const pairAddresses = batch1Results.map((r) => decodeAddressResult(r)).filter((a) => a !== null);
|
|
3647
|
+
if (pairAddresses.length === 0) return [];
|
|
3648
|
+
const batch2Calls = pairAddresses.map((pair) => [
|
|
3649
|
+
pair,
|
|
3650
|
+
encodeFunctionData10({ abi: lbPairAbi, functionName: "getLBHooksParameters" })
|
|
3651
|
+
]);
|
|
3652
|
+
const batch2Results = await multicallRead(rpcUrl, batch2Calls);
|
|
3653
|
+
const rewardedPairs = [];
|
|
3654
|
+
for (let i = 0; i < pairAddresses.length; i++) {
|
|
3655
|
+
const raw = batch2Results[i];
|
|
3656
|
+
if (!raw) continue;
|
|
3657
|
+
let hooksBytes;
|
|
3658
|
+
try {
|
|
3659
|
+
const _bytes32Abi = parseAbi10(["function f() external view returns (bytes32)"]);
|
|
3660
|
+
hooksBytes = decodeFunctionResult22({ abi: _bytes32Abi, functionName: "f", data: raw });
|
|
3661
|
+
} catch {
|
|
3662
|
+
continue;
|
|
3663
|
+
}
|
|
3664
|
+
const rewarder = extractRewarderAddress(hooksBytes);
|
|
3665
|
+
if (rewarder) {
|
|
3666
|
+
rewardedPairs.push({ pool: pairAddresses[i], rewarder });
|
|
3667
|
+
}
|
|
3668
|
+
}
|
|
3669
|
+
if (rewardedPairs.length === 0) return [];
|
|
3670
|
+
const batch3Calls = [];
|
|
3671
|
+
for (const { rewarder } of rewardedPairs) {
|
|
3672
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "isStopped" })]);
|
|
3673
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getRewardedRange" })]);
|
|
3674
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getRewardToken" })]);
|
|
3675
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getPid" })]);
|
|
3676
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getMasterChef" })]);
|
|
3677
|
+
}
|
|
3678
|
+
const batch3Results = await multicallRead(rpcUrl, batch3Calls);
|
|
3679
|
+
const batch4aCalls = [];
|
|
3680
|
+
for (const { pool } of rewardedPairs) {
|
|
3681
|
+
batch4aCalls.push([pool, encodeFunctionData10({ abi: lbPairAbi, functionName: "getTokenX" })]);
|
|
3682
|
+
batch4aCalls.push([pool, encodeFunctionData10({ abi: lbPairAbi, functionName: "getTokenY" })]);
|
|
3683
|
+
}
|
|
3684
|
+
const batch4aResults = await multicallRead(rpcUrl, batch4aCalls);
|
|
3685
|
+
const tokenXAddresses = [];
|
|
3686
|
+
const tokenYAddresses = [];
|
|
3687
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3688
|
+
tokenXAddresses.push(decodeAddressResult(batch4aResults[i * 2] ?? null));
|
|
3689
|
+
tokenYAddresses.push(decodeAddressResult(batch4aResults[i * 2 + 1] ?? null));
|
|
3690
|
+
}
|
|
3691
|
+
const uniqueTokens = Array.from(
|
|
3692
|
+
new Set([...tokenXAddresses, ...tokenYAddresses].filter((a) => a !== null))
|
|
3693
|
+
);
|
|
3694
|
+
const batch4bCalls = uniqueTokens.map((token) => [
|
|
3695
|
+
token,
|
|
3696
|
+
encodeFunctionData10({ abi: erc20Abi2, functionName: "symbol" })
|
|
3697
|
+
]);
|
|
3698
|
+
const batch4bResults = await multicallRead(rpcUrl, batch4bCalls);
|
|
3699
|
+
const symbolMap = /* @__PURE__ */ new Map();
|
|
3700
|
+
for (let i = 0; i < uniqueTokens.length; i++) {
|
|
3701
|
+
symbolMap.set(uniqueTokens[i], decodeStringResult(batch4bResults[i] ?? null));
|
|
3702
|
+
}
|
|
3703
|
+
const STRIDE3 = 5;
|
|
3704
|
+
const poolData = [];
|
|
3705
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3706
|
+
const base = i * STRIDE3;
|
|
3707
|
+
poolData.push({
|
|
3708
|
+
stopped: decodeBoolResult(batch3Results[base] ?? null) ?? false,
|
|
3709
|
+
range: decodeRangeResult(batch3Results[base + 1] ?? null),
|
|
3710
|
+
rewardToken: decodeAddressResult(batch3Results[base + 2] ?? null),
|
|
3711
|
+
pid: Number(decodeUint256Result(batch3Results[base + 3] ?? null) ?? 0n),
|
|
3712
|
+
masterChef: decodeAddressResult(batch3Results[base + 4] ?? null)
|
|
3713
|
+
});
|
|
3714
|
+
}
|
|
3715
|
+
const masterChefAddr = poolData.map((d) => d.masterChef).find((a) => a !== null) ?? null;
|
|
3716
|
+
let moePerDay = 0;
|
|
3717
|
+
let topPoolIds = /* @__PURE__ */ new Set();
|
|
3718
|
+
let totalWeightRaw = 0n;
|
|
3719
|
+
let veMoeAddr = null;
|
|
3720
|
+
if (masterChefAddr) {
|
|
3721
|
+
veMoeAddr = await client.readContract({
|
|
3722
|
+
address: masterChefAddr,
|
|
3723
|
+
abi: masterChefAbi,
|
|
3724
|
+
functionName: "getVeMoe"
|
|
3725
|
+
});
|
|
3726
|
+
const batch5Calls = [
|
|
3727
|
+
[masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getMoePerSecond" })],
|
|
3728
|
+
[masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getTreasuryShare" })],
|
|
3729
|
+
[masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getStaticShare" })],
|
|
3730
|
+
[veMoeAddr, encodeFunctionData10({ abi: veMoeAbi, functionName: "getTotalWeight" })],
|
|
3731
|
+
[veMoeAddr, encodeFunctionData10({ abi: veMoeAbi, functionName: "getTopPoolIds" })]
|
|
3732
|
+
];
|
|
3733
|
+
const batch5Results = await multicallRead(rpcUrl, batch5Calls);
|
|
3734
|
+
const moePerSecRaw = decodeUint256Result(batch5Results[0] ?? null) ?? 0n;
|
|
3735
|
+
const treasuryShareRaw = decodeUint256Result(batch5Results[1] ?? null) ?? 0n;
|
|
3736
|
+
const staticShareRaw = decodeUint256Result(batch5Results[2] ?? null) ?? 0n;
|
|
3737
|
+
totalWeightRaw = decodeUint256Result(batch5Results[3] ?? null) ?? 0n;
|
|
3738
|
+
const topPoolIdsRaw = decodeUint256ArrayResult(batch5Results[4] ?? null) ?? [];
|
|
3739
|
+
topPoolIds = new Set(topPoolIdsRaw.map(Number));
|
|
3740
|
+
const PRECISION = 10n ** 18n;
|
|
3741
|
+
const netPerSec = moePerSecRaw * (PRECISION - treasuryShareRaw) / PRECISION * (PRECISION - staticShareRaw) / PRECISION;
|
|
3742
|
+
moePerDay = Number(netPerSec * 86400n) / 1e18;
|
|
3743
|
+
}
|
|
3744
|
+
const weightByPid = /* @__PURE__ */ new Map();
|
|
3745
|
+
if (veMoeAddr && rewardedPairs.length > 0) {
|
|
3746
|
+
const batch6Calls = poolData.map((d) => [
|
|
3747
|
+
veMoeAddr,
|
|
3748
|
+
encodeFunctionData10({ abi: veMoeAbi, functionName: "getWeight", args: [BigInt(d.pid)] })
|
|
3749
|
+
]);
|
|
3750
|
+
const batch6Results = await multicallRead(rpcUrl, batch6Calls);
|
|
3751
|
+
for (let i = 0; i < poolData.length; i++) {
|
|
3752
|
+
weightByPid.set(poolData[i].pid, decodeUint256Result(batch6Results[i] ?? null) ?? 0n);
|
|
3753
|
+
}
|
|
3754
|
+
}
|
|
3755
|
+
let moePriceUsd = 0;
|
|
3756
|
+
let wmntPriceUsd = 0;
|
|
3757
|
+
const MOE_ADDR = "0x4515A45337F461A11Ff0FE8aBF3c606AE5dC00c9";
|
|
3758
|
+
if (this.lbQuoter && this.wmnt && this.usdt) {
|
|
3759
|
+
try {
|
|
3760
|
+
const [moeWmntQuote, wmntUsdtQuote] = await Promise.all([
|
|
3761
|
+
client.readContract({
|
|
3762
|
+
address: this.lbQuoter,
|
|
3763
|
+
abi: lbQuoterAbi2,
|
|
3764
|
+
functionName: "findBestPathFromAmountIn",
|
|
3765
|
+
args: [[MOE_ADDR, this.wmnt], 10n ** 18n]
|
|
3766
|
+
}),
|
|
3767
|
+
client.readContract({
|
|
3768
|
+
address: this.lbQuoter,
|
|
3769
|
+
abi: lbQuoterAbi2,
|
|
3770
|
+
functionName: "findBestPathFromAmountIn",
|
|
3771
|
+
args: [[this.wmnt, this.usdt], 10n ** 18n]
|
|
3772
|
+
})
|
|
3773
|
+
]);
|
|
3774
|
+
const moeInWmnt = Number(moeWmntQuote.amounts.at(-1) ?? 0n) / 1e18;
|
|
3775
|
+
wmntPriceUsd = Number(wmntUsdtQuote.amounts.at(-1) ?? 0n) / 1e6;
|
|
3776
|
+
moePriceUsd = moeInWmnt * wmntPriceUsd;
|
|
3777
|
+
} catch {
|
|
3778
|
+
}
|
|
3779
|
+
}
|
|
3780
|
+
const binRequests = [];
|
|
3781
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3782
|
+
const range = poolData[i].range;
|
|
3783
|
+
if (!range) continue;
|
|
3784
|
+
const minBin = Number(range[0]);
|
|
3785
|
+
const maxBin = Number(range[1]);
|
|
3786
|
+
for (let b = minBin; b <= maxBin; b++) {
|
|
3787
|
+
binRequests.push({ poolIdx: i, binId: b });
|
|
3788
|
+
}
|
|
3789
|
+
}
|
|
3790
|
+
const binReservesX = /* @__PURE__ */ new Map();
|
|
3791
|
+
const binReservesY = /* @__PURE__ */ new Map();
|
|
3792
|
+
if (binRequests.length > 0) {
|
|
3793
|
+
const batch7Calls = binRequests.map(({ poolIdx, binId }) => [
|
|
3794
|
+
rewardedPairs[poolIdx].pool,
|
|
3795
|
+
encodeFunctionData10({ abi: lbPairBinAbi, functionName: "getBin", args: [binId] })
|
|
3796
|
+
]);
|
|
3797
|
+
const batch7Results = await multicallRead(rpcUrl, batch7Calls);
|
|
3798
|
+
for (let j = 0; j < binRequests.length; j++) {
|
|
3799
|
+
const { poolIdx, binId } = binRequests[j];
|
|
3800
|
+
const decoded = decodeBinResult(batch7Results[j] ?? null);
|
|
3801
|
+
if (!decoded) continue;
|
|
3802
|
+
if (!binReservesX.has(poolIdx)) {
|
|
3803
|
+
binReservesX.set(poolIdx, /* @__PURE__ */ new Map());
|
|
3804
|
+
binReservesY.set(poolIdx, /* @__PURE__ */ new Map());
|
|
3805
|
+
}
|
|
3806
|
+
binReservesX.get(poolIdx).set(binId, decoded[0]);
|
|
3807
|
+
binReservesY.get(poolIdx).set(binId, decoded[1]);
|
|
3808
|
+
}
|
|
3809
|
+
}
|
|
3810
|
+
const stableSymbols = /* @__PURE__ */ new Set(["USDT", "USDC", "MUSD", "AUSD", "USDY", "FDUSD"]);
|
|
3811
|
+
const mntSymbols = /* @__PURE__ */ new Set(["WMNT", "MNT"]);
|
|
3812
|
+
const moeSymbols = /* @__PURE__ */ new Set(["MOE"]);
|
|
3813
|
+
const sixDecimalStables = /* @__PURE__ */ new Set(["USDT", "USDC", "FDUSD"]);
|
|
3814
|
+
const getTokenPriceUsd = (sym) => {
|
|
3815
|
+
if (stableSymbols.has(sym)) return 1;
|
|
3816
|
+
if (mntSymbols.has(sym)) return wmntPriceUsd;
|
|
3817
|
+
if (moeSymbols.has(sym)) return moePriceUsd;
|
|
3818
|
+
return 0;
|
|
3819
|
+
};
|
|
3820
|
+
const getTokenDecimals = (sym) => {
|
|
3821
|
+
return sixDecimalStables.has(sym) ? 6 : 18;
|
|
3822
|
+
};
|
|
3823
|
+
const results = [];
|
|
3824
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3825
|
+
const { pool, rewarder } = rewardedPairs[i];
|
|
3826
|
+
const data = poolData[i];
|
|
3827
|
+
const tokenX = tokenXAddresses[i] ?? "0x0000000000000000000000000000000000000000";
|
|
3828
|
+
const tokenY = tokenYAddresses[i] ?? "0x0000000000000000000000000000000000000000";
|
|
3829
|
+
const symX = symbolMap.get(tokenX) ?? "?";
|
|
3830
|
+
const symY = symbolMap.get(tokenY) ?? "?";
|
|
3831
|
+
const isTopPool = topPoolIds.has(data.pid);
|
|
3832
|
+
const weight = weightByPid.get(data.pid) ?? 0n;
|
|
3833
|
+
let poolMoePerDay = 0;
|
|
3834
|
+
if (isTopPool && totalWeightRaw > 0n && weight > 0n) {
|
|
3835
|
+
poolMoePerDay = moePerDay * (Number(weight) / Number(totalWeightRaw));
|
|
3836
|
+
}
|
|
3837
|
+
const rxMap = binReservesX.get(i);
|
|
3838
|
+
const ryMap = binReservesY.get(i);
|
|
3839
|
+
const range = data.range;
|
|
3840
|
+
let rangeTvlUsd = 0;
|
|
3841
|
+
let rewardedBins = 0;
|
|
3842
|
+
if (range) {
|
|
3843
|
+
const minBin = Number(range[0]);
|
|
3844
|
+
const maxBin = Number(range[1]);
|
|
3845
|
+
rewardedBins = maxBin - minBin + 1;
|
|
3846
|
+
if (rxMap && ryMap) {
|
|
3847
|
+
const priceX = getTokenPriceUsd(symX);
|
|
3848
|
+
const priceY = getTokenPriceUsd(symY);
|
|
3849
|
+
const decX = getTokenDecimals(symX);
|
|
3850
|
+
const decY = getTokenDecimals(symY);
|
|
3851
|
+
for (let b = minBin; b <= maxBin; b++) {
|
|
3852
|
+
const rx = rxMap.get(b) ?? 0n;
|
|
3853
|
+
const ry = ryMap.get(b) ?? 0n;
|
|
3854
|
+
rangeTvlUsd += Number(rx) / 10 ** decX * priceX;
|
|
3855
|
+
rangeTvlUsd += Number(ry) / 10 ** decY * priceY;
|
|
3856
|
+
}
|
|
3857
|
+
}
|
|
3858
|
+
}
|
|
3859
|
+
const aprPercent = rangeTvlUsd > 0 && moePriceUsd > 0 ? poolMoePerDay * moePriceUsd * 365 / rangeTvlUsd * 100 : 0;
|
|
3860
|
+
results.push({
|
|
3861
|
+
pool,
|
|
3862
|
+
rewarder,
|
|
3863
|
+
rewardToken: data.rewardToken ?? "0x0000000000000000000000000000000000000000",
|
|
3864
|
+
minBinId: range ? Number(range[0]) : 0,
|
|
3865
|
+
maxBinId: range ? Number(range[1]) : 0,
|
|
3866
|
+
pid: data.pid,
|
|
3867
|
+
stopped: data.stopped,
|
|
3868
|
+
tokenX,
|
|
3869
|
+
tokenY,
|
|
3870
|
+
symbolX: symX,
|
|
3871
|
+
symbolY: symY,
|
|
3872
|
+
isTopPool,
|
|
3873
|
+
moePerDay: poolMoePerDay,
|
|
3874
|
+
rangeTvlUsd,
|
|
3875
|
+
aprPercent,
|
|
3876
|
+
rewardedBins
|
|
3877
|
+
});
|
|
3878
|
+
}
|
|
3879
|
+
return results;
|
|
3880
|
+
}
|
|
3881
|
+
/**
|
|
3882
|
+
* Get a user's LB positions (bin balances) across a range of bin IDs.
|
|
3883
|
+
* If binIds is omitted, auto-detects from the rewarder's rewarded range (or active ± 50).
|
|
3884
|
+
*/
|
|
3885
|
+
async getUserPositions(user, pool, binIds) {
|
|
3886
|
+
const rpcUrl = this.requireRpc();
|
|
3887
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3888
|
+
const resolvedBinIds = binIds && binIds.length > 0 ? binIds : await this.autoDetectBins(pool);
|
|
3889
|
+
const accounts = resolvedBinIds.map(() => user);
|
|
3890
|
+
const ids = resolvedBinIds.map(BigInt);
|
|
3891
|
+
const balances = await client.readContract({
|
|
3892
|
+
address: pool,
|
|
3893
|
+
abi: lbPairAbi,
|
|
3894
|
+
functionName: "balanceOfBatch",
|
|
3895
|
+
args: [accounts, ids]
|
|
3896
|
+
});
|
|
3897
|
+
return resolvedBinIds.map((binId, i) => ({ binId, balance: balances[i] ?? 0n })).filter((p) => p.balance > 0n);
|
|
3898
|
+
}
|
|
3899
|
+
};
|
|
3900
|
+
var POOL_ABI = parseAbi11([
|
|
3169
3901
|
"function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
|
|
3170
3902
|
"function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
|
|
3171
3903
|
"function repay(address asset, uint256 amount, uint256 interestRateMode, address onBehalfOf) external returns (uint256)",
|
|
@@ -3173,27 +3905,27 @@ var POOL_ABI = parseAbi10([
|
|
|
3173
3905
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)",
|
|
3174
3906
|
"function getReserveData(address asset) external view returns (uint256 configuration, uint128 liquidityIndex, uint128 currentLiquidityRate, uint128 variableBorrowIndex, uint128 currentVariableBorrowRate, uint128 currentStableBorrowRate, uint40 lastUpdateTimestamp, uint16 id, address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress, address interestRateStrategyAddress, uint128 accruedToTreasury, uint128 unbacked, uint128 isolationModeTotalDebt)"
|
|
3175
3907
|
]);
|
|
3176
|
-
var ERC20_ABI2 =
|
|
3908
|
+
var ERC20_ABI2 = parseAbi11([
|
|
3177
3909
|
"function totalSupply() external view returns (uint256)"
|
|
3178
3910
|
]);
|
|
3179
|
-
var INCENTIVES_ABI =
|
|
3911
|
+
var INCENTIVES_ABI = parseAbi11([
|
|
3180
3912
|
"function getIncentivesController() external view returns (address)"
|
|
3181
3913
|
]);
|
|
3182
|
-
var REWARDS_CONTROLLER_ABI =
|
|
3914
|
+
var REWARDS_CONTROLLER_ABI = parseAbi11([
|
|
3183
3915
|
"function getRewardsByAsset(address asset) external view returns (address[])",
|
|
3184
3916
|
"function getRewardsData(address asset, address reward) external view returns (uint256 index, uint256 emissionsPerSecond, uint256 lastUpdateTimestamp, uint256 distributionEnd)"
|
|
3185
3917
|
]);
|
|
3186
|
-
var POOL_PROVIDER_ABI =
|
|
3918
|
+
var POOL_PROVIDER_ABI = parseAbi11([
|
|
3187
3919
|
"function ADDRESSES_PROVIDER() external view returns (address)"
|
|
3188
3920
|
]);
|
|
3189
|
-
var ADDRESSES_PROVIDER_ABI =
|
|
3921
|
+
var ADDRESSES_PROVIDER_ABI = parseAbi11([
|
|
3190
3922
|
"function getPriceOracle() external view returns (address)"
|
|
3191
3923
|
]);
|
|
3192
|
-
var ORACLE_ABI =
|
|
3924
|
+
var ORACLE_ABI = parseAbi11([
|
|
3193
3925
|
"function getAssetPrice(address asset) external view returns (uint256)",
|
|
3194
3926
|
"function BASE_CURRENCY_UNIT() external view returns (uint256)"
|
|
3195
3927
|
]);
|
|
3196
|
-
var ERC20_DECIMALS_ABI =
|
|
3928
|
+
var ERC20_DECIMALS_ABI = parseAbi11([
|
|
3197
3929
|
"function decimals() external view returns (uint8)"
|
|
3198
3930
|
]);
|
|
3199
3931
|
function u256ToF64(v) {
|
|
@@ -3201,6 +3933,46 @@ function u256ToF64(v) {
|
|
|
3201
3933
|
if (v > MAX_U128) return Infinity;
|
|
3202
3934
|
return Number(v);
|
|
3203
3935
|
}
|
|
3936
|
+
function decodeAddress(data) {
|
|
3937
|
+
if (!data || data.length < 66) return null;
|
|
3938
|
+
return `0x${data.slice(26, 66)}`;
|
|
3939
|
+
}
|
|
3940
|
+
function decodeAddressArray(data) {
|
|
3941
|
+
if (!data) return [];
|
|
3942
|
+
try {
|
|
3943
|
+
return decodeFunctionResult3({
|
|
3944
|
+
abi: REWARDS_CONTROLLER_ABI,
|
|
3945
|
+
functionName: "getRewardsByAsset",
|
|
3946
|
+
data
|
|
3947
|
+
});
|
|
3948
|
+
} catch {
|
|
3949
|
+
return [];
|
|
3950
|
+
}
|
|
3951
|
+
}
|
|
3952
|
+
function decodeReserveData(data) {
|
|
3953
|
+
if (!data) return null;
|
|
3954
|
+
try {
|
|
3955
|
+
return decodeFunctionResult3({
|
|
3956
|
+
abi: POOL_ABI,
|
|
3957
|
+
functionName: "getReserveData",
|
|
3958
|
+
data
|
|
3959
|
+
});
|
|
3960
|
+
} catch {
|
|
3961
|
+
return null;
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
function decodeRewardsData(data) {
|
|
3965
|
+
if (!data) return null;
|
|
3966
|
+
try {
|
|
3967
|
+
return decodeFunctionResult3({
|
|
3968
|
+
abi: REWARDS_CONTROLLER_ABI,
|
|
3969
|
+
functionName: "getRewardsData",
|
|
3970
|
+
data
|
|
3971
|
+
});
|
|
3972
|
+
} catch {
|
|
3973
|
+
return null;
|
|
3974
|
+
}
|
|
3975
|
+
}
|
|
3204
3976
|
var AaveV3Adapter = class {
|
|
3205
3977
|
protocolName;
|
|
3206
3978
|
pool;
|
|
@@ -3216,7 +3988,7 @@ var AaveV3Adapter = class {
|
|
|
3216
3988
|
return this.protocolName;
|
|
3217
3989
|
}
|
|
3218
3990
|
async buildSupply(params) {
|
|
3219
|
-
const data =
|
|
3991
|
+
const data = encodeFunctionData11({
|
|
3220
3992
|
abi: POOL_ABI,
|
|
3221
3993
|
functionName: "supply",
|
|
3222
3994
|
args: [params.asset, params.amount, params.on_behalf_of, 0]
|
|
@@ -3232,7 +4004,7 @@ var AaveV3Adapter = class {
|
|
|
3232
4004
|
}
|
|
3233
4005
|
async buildBorrow(params) {
|
|
3234
4006
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
3235
|
-
const data =
|
|
4007
|
+
const data = encodeFunctionData11({
|
|
3236
4008
|
abi: POOL_ABI,
|
|
3237
4009
|
functionName: "borrow",
|
|
3238
4010
|
args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
|
|
@@ -3247,7 +4019,7 @@ var AaveV3Adapter = class {
|
|
|
3247
4019
|
}
|
|
3248
4020
|
async buildRepay(params) {
|
|
3249
4021
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
3250
|
-
const data =
|
|
4022
|
+
const data = encodeFunctionData11({
|
|
3251
4023
|
abi: POOL_ABI,
|
|
3252
4024
|
functionName: "repay",
|
|
3253
4025
|
args: [params.asset, params.amount, rateMode, params.on_behalf_of]
|
|
@@ -3262,7 +4034,7 @@ var AaveV3Adapter = class {
|
|
|
3262
4034
|
};
|
|
3263
4035
|
}
|
|
3264
4036
|
async buildWithdraw(params) {
|
|
3265
|
-
const data =
|
|
4037
|
+
const data = encodeFunctionData11({
|
|
3266
4038
|
abi: POOL_ABI,
|
|
3267
4039
|
functionName: "withdraw",
|
|
3268
4040
|
args: [params.asset, params.amount, params.to]
|
|
@@ -3277,15 +4049,21 @@ var AaveV3Adapter = class {
|
|
|
3277
4049
|
}
|
|
3278
4050
|
async getRates(asset) {
|
|
3279
4051
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
3280
|
-
const
|
|
3281
|
-
const result = await client.readContract({
|
|
3282
|
-
address: this.pool,
|
|
4052
|
+
const reserveCallData = encodeFunctionData11({
|
|
3283
4053
|
abi: POOL_ABI,
|
|
3284
4054
|
functionName: "getReserveData",
|
|
3285
4055
|
args: [asset]
|
|
3286
|
-
})
|
|
4056
|
+
});
|
|
4057
|
+
const [reserveRaw] = await multicallRead(this.rpcUrl, [
|
|
4058
|
+
[this.pool, reserveCallData]
|
|
4059
|
+
]).catch((e) => {
|
|
3287
4060
|
throw DefiError.rpcError(`[${this.protocolName}] getReserveData failed: ${e}`);
|
|
3288
4061
|
});
|
|
4062
|
+
const reserveDecoded = decodeReserveData(reserveRaw ?? null);
|
|
4063
|
+
if (!reserveDecoded) {
|
|
4064
|
+
throw DefiError.rpcError(`[${this.protocolName}] getReserveData returned no data`);
|
|
4065
|
+
}
|
|
4066
|
+
const result = reserveDecoded;
|
|
3289
4067
|
const RAY = 1e27;
|
|
3290
4068
|
const SECONDS_PER_YEAR4 = 31536e3;
|
|
3291
4069
|
const toApy = (rayRate) => {
|
|
@@ -3297,74 +4075,56 @@ var AaveV3Adapter = class {
|
|
|
3297
4075
|
const stableRate = toApy(result[5]);
|
|
3298
4076
|
const aTokenAddress = result[8];
|
|
3299
4077
|
const variableDebtTokenAddress = result[10];
|
|
3300
|
-
const [
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
abi: ERC20_ABI2,
|
|
3304
|
-
functionName: "totalSupply"
|
|
3305
|
-
}).catch(() => 0n),
|
|
3306
|
-
client.readContract({
|
|
3307
|
-
address: variableDebtTokenAddress,
|
|
3308
|
-
abi: ERC20_ABI2,
|
|
3309
|
-
functionName: "totalSupply"
|
|
3310
|
-
}).catch(() => 0n)
|
|
4078
|
+
const [supplyRaw, borrowRaw] = await multicallRead(this.rpcUrl, [
|
|
4079
|
+
[aTokenAddress, encodeFunctionData11({ abi: ERC20_ABI2, functionName: "totalSupply" })],
|
|
4080
|
+
[variableDebtTokenAddress, encodeFunctionData11({ abi: ERC20_ABI2, functionName: "totalSupply" })]
|
|
3311
4081
|
]);
|
|
4082
|
+
const totalSupply = decodeU256(supplyRaw ?? null);
|
|
4083
|
+
const totalBorrow = decodeU256(borrowRaw ?? null);
|
|
3312
4084
|
const utilization = totalSupply > 0n ? Number(totalBorrow * 10000n / totalSupply) / 100 : 0;
|
|
3313
4085
|
const supplyRewardTokens = [];
|
|
3314
4086
|
const borrowRewardTokens = [];
|
|
3315
4087
|
const supplyEmissions = [];
|
|
3316
4088
|
const borrowEmissions = [];
|
|
3317
4089
|
try {
|
|
3318
|
-
const
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
});
|
|
4090
|
+
const [controllerRaw] = await multicallRead(this.rpcUrl, [
|
|
4091
|
+
[aTokenAddress, encodeFunctionData11({ abi: INCENTIVES_ABI, functionName: "getIncentivesController" })]
|
|
4092
|
+
]);
|
|
4093
|
+
const controllerAddr = decodeAddress(controllerRaw ?? null);
|
|
3323
4094
|
if (controllerAddr && controllerAddr !== zeroAddress5) {
|
|
3324
|
-
const [
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
abi: REWARDS_CONTROLLER_ABI,
|
|
3328
|
-
functionName: "getRewardsByAsset",
|
|
3329
|
-
args: [aTokenAddress]
|
|
3330
|
-
}).catch(() => []),
|
|
3331
|
-
client.readContract({
|
|
3332
|
-
address: controllerAddr,
|
|
3333
|
-
abi: REWARDS_CONTROLLER_ABI,
|
|
3334
|
-
functionName: "getRewardsByAsset",
|
|
3335
|
-
args: [variableDebtTokenAddress]
|
|
3336
|
-
}).catch(() => [])
|
|
4095
|
+
const [supplyRewardsRaw, borrowRewardsRaw] = await multicallRead(this.rpcUrl, [
|
|
4096
|
+
[controllerAddr, encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [aTokenAddress] })],
|
|
4097
|
+
[controllerAddr, encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [variableDebtTokenAddress] })]
|
|
3337
4098
|
]);
|
|
3338
|
-
const
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
args: [aTokenAddress, reward]
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
4099
|
+
const supplyRewards = decodeAddressArray(supplyRewardsRaw ?? null);
|
|
4100
|
+
const borrowRewards = decodeAddressArray(borrowRewardsRaw ?? null);
|
|
4101
|
+
const rewardsDataCalls = [
|
|
4102
|
+
...supplyRewards.map((reward) => [
|
|
4103
|
+
controllerAddr,
|
|
4104
|
+
encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [aTokenAddress, reward] })
|
|
4105
|
+
]),
|
|
4106
|
+
...borrowRewards.map((reward) => [
|
|
4107
|
+
controllerAddr,
|
|
4108
|
+
encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [variableDebtTokenAddress, reward] })
|
|
4109
|
+
])
|
|
4110
|
+
];
|
|
4111
|
+
if (rewardsDataCalls.length > 0) {
|
|
4112
|
+
const rewardsDataResults = await multicallRead(this.rpcUrl, rewardsDataCalls);
|
|
4113
|
+
const supplyDataResults = rewardsDataResults.slice(0, supplyRewards.length);
|
|
4114
|
+
const borrowDataResults = rewardsDataResults.slice(supplyRewards.length);
|
|
4115
|
+
for (let i = 0; i < supplyRewards.length; i++) {
|
|
4116
|
+
const data = decodeRewardsData(supplyDataResults[i] ?? null);
|
|
4117
|
+
if (data && data[1] > 0n) {
|
|
4118
|
+
supplyRewardTokens.push(supplyRewards[i]);
|
|
4119
|
+
supplyEmissions.push(data[1].toString());
|
|
4120
|
+
}
|
|
3352
4121
|
}
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
args: [variableDebtTokenAddress, reward]
|
|
3360
|
-
}).catch(() => null)
|
|
3361
|
-
);
|
|
3362
|
-
const borrowData = await Promise.all(borrowDataPromises);
|
|
3363
|
-
for (let i = 0; i < borrowRewards.length; i++) {
|
|
3364
|
-
const data = borrowData[i];
|
|
3365
|
-
if (data && data[1] > 0n) {
|
|
3366
|
-
borrowRewardTokens.push(borrowRewards[i]);
|
|
3367
|
-
borrowEmissions.push(data[1].toString());
|
|
4122
|
+
for (let i = 0; i < borrowRewards.length; i++) {
|
|
4123
|
+
const data = decodeRewardsData(borrowDataResults[i] ?? null);
|
|
4124
|
+
if (data && data[1] > 0n) {
|
|
4125
|
+
borrowRewardTokens.push(borrowRewards[i]);
|
|
4126
|
+
borrowEmissions.push(data[1].toString());
|
|
4127
|
+
}
|
|
3368
4128
|
}
|
|
3369
4129
|
}
|
|
3370
4130
|
}
|
|
@@ -3376,55 +4136,49 @@ var AaveV3Adapter = class {
|
|
|
3376
4136
|
const hasBorrowRewards = borrowRewardTokens.length > 0;
|
|
3377
4137
|
if ((hasSupplyRewards || hasBorrowRewards) && totalSupply > 0n) {
|
|
3378
4138
|
try {
|
|
3379
|
-
const
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
const
|
|
3385
|
-
|
|
3386
|
-
abi: ADDRESSES_PROVIDER_ABI,
|
|
3387
|
-
functionName: "getPriceOracle"
|
|
3388
|
-
});
|
|
3389
|
-
const [assetPrice, baseCurrencyUnit, assetDecimals] = await Promise.all([
|
|
3390
|
-
client.readContract({
|
|
3391
|
-
address: oracleAddr,
|
|
3392
|
-
abi: ORACLE_ABI,
|
|
3393
|
-
functionName: "getAssetPrice",
|
|
3394
|
-
args: [asset]
|
|
3395
|
-
}),
|
|
3396
|
-
client.readContract({
|
|
3397
|
-
address: oracleAddr,
|
|
3398
|
-
abi: ORACLE_ABI,
|
|
3399
|
-
functionName: "BASE_CURRENCY_UNIT"
|
|
3400
|
-
}),
|
|
3401
|
-
client.readContract({
|
|
3402
|
-
address: asset,
|
|
3403
|
-
abi: ERC20_DECIMALS_ABI,
|
|
3404
|
-
functionName: "decimals"
|
|
3405
|
-
}).catch(() => 18)
|
|
4139
|
+
const [providerRaw] = await multicallRead(this.rpcUrl, [
|
|
4140
|
+
[this.pool, encodeFunctionData11({ abi: POOL_PROVIDER_ABI, functionName: "ADDRESSES_PROVIDER" })]
|
|
4141
|
+
]);
|
|
4142
|
+
const providerAddr = decodeAddress(providerRaw ?? null);
|
|
4143
|
+
if (!providerAddr) throw new Error("No provider address");
|
|
4144
|
+
const [oracleRaw] = await multicallRead(this.rpcUrl, [
|
|
4145
|
+
[providerAddr, encodeFunctionData11({ abi: ADDRESSES_PROVIDER_ABI, functionName: "getPriceOracle" })]
|
|
3406
4146
|
]);
|
|
3407
|
-
const
|
|
4147
|
+
const oracleAddr = decodeAddress(oracleRaw ?? null);
|
|
4148
|
+
if (!oracleAddr) throw new Error("No oracle address");
|
|
4149
|
+
const [assetPriceRaw, baseCurrencyUnitRaw, assetDecimalsRaw] = await multicallRead(this.rpcUrl, [
|
|
4150
|
+
[oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [asset] })],
|
|
4151
|
+
[oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "BASE_CURRENCY_UNIT" })],
|
|
4152
|
+
[asset, encodeFunctionData11({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
|
|
4153
|
+
]);
|
|
4154
|
+
const assetPrice = decodeU256(assetPriceRaw ?? null);
|
|
4155
|
+
const baseCurrencyUnit = decodeU256(baseCurrencyUnitRaw ?? null);
|
|
4156
|
+
const assetDecimals = assetDecimalsRaw ? Number(decodeU256(assetDecimalsRaw)) : 18;
|
|
4157
|
+
const priceUnit = Number(baseCurrencyUnit) || 1e8;
|
|
3408
4158
|
const assetPriceF = Number(assetPrice) / priceUnit;
|
|
3409
4159
|
const assetDecimalsDivisor = 10 ** assetDecimals;
|
|
4160
|
+
const allRewardTokens = Array.from(/* @__PURE__ */ new Set([...supplyRewardTokens, ...borrowRewardTokens]));
|
|
4161
|
+
const rewardPriceCalls = allRewardTokens.flatMap((token) => [
|
|
4162
|
+
[oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [token] })],
|
|
4163
|
+
[token, encodeFunctionData11({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
|
|
4164
|
+
]);
|
|
4165
|
+
const rewardPriceResults = rewardPriceCalls.length > 0 ? await multicallRead(this.rpcUrl, rewardPriceCalls) : [];
|
|
4166
|
+
const rewardPriceMap = /* @__PURE__ */ new Map();
|
|
4167
|
+
for (let i = 0; i < allRewardTokens.length; i++) {
|
|
4168
|
+
const priceRaw = rewardPriceResults[i * 2] ?? null;
|
|
4169
|
+
const decimalsRaw = rewardPriceResults[i * 2 + 1] ?? null;
|
|
4170
|
+
const price = decodeU256(priceRaw);
|
|
4171
|
+
const decimals = decimalsRaw ? Number(decodeU256(decimalsRaw)) : 18;
|
|
4172
|
+
rewardPriceMap.set(allRewardTokens[i].toLowerCase(), { price, decimals });
|
|
4173
|
+
}
|
|
3410
4174
|
if (hasSupplyRewards) {
|
|
3411
4175
|
let totalSupplyIncentiveUsdPerYear = 0;
|
|
3412
4176
|
const totalSupplyUsd = Number(totalSupply) / assetDecimalsDivisor * assetPriceF;
|
|
3413
4177
|
for (let i = 0; i < supplyRewardTokens.length; i++) {
|
|
3414
4178
|
const emissionPerSec = BigInt(supplyEmissions[i]);
|
|
3415
|
-
const
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
abi: ORACLE_ABI,
|
|
3419
|
-
functionName: "getAssetPrice",
|
|
3420
|
-
args: [supplyRewardTokens[i]]
|
|
3421
|
-
}).catch(() => 0n),
|
|
3422
|
-
client.readContract({
|
|
3423
|
-
address: supplyRewardTokens[i],
|
|
3424
|
-
abi: ERC20_DECIMALS_ABI,
|
|
3425
|
-
functionName: "decimals"
|
|
3426
|
-
}).catch(() => 18)
|
|
3427
|
-
]);
|
|
4179
|
+
const entry = rewardPriceMap.get(supplyRewardTokens[i].toLowerCase());
|
|
4180
|
+
const rewardPrice = entry?.price ?? 0n;
|
|
4181
|
+
const rewardDecimals = entry?.decimals ?? 18;
|
|
3428
4182
|
if (rewardPrice > 0n) {
|
|
3429
4183
|
const rewardPriceF = Number(rewardPrice) / priceUnit;
|
|
3430
4184
|
const emissionPerYear = Number(emissionPerSec) / 10 ** rewardDecimals * SECONDS_PER_YEAR4;
|
|
@@ -3440,19 +4194,9 @@ var AaveV3Adapter = class {
|
|
|
3440
4194
|
const totalBorrowUsd = Number(totalBorrow) / assetDecimalsDivisor * assetPriceF;
|
|
3441
4195
|
for (let i = 0; i < borrowRewardTokens.length; i++) {
|
|
3442
4196
|
const emissionPerSec = BigInt(borrowEmissions[i]);
|
|
3443
|
-
const
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
abi: ORACLE_ABI,
|
|
3447
|
-
functionName: "getAssetPrice",
|
|
3448
|
-
args: [borrowRewardTokens[i]]
|
|
3449
|
-
}).catch(() => 0n),
|
|
3450
|
-
client.readContract({
|
|
3451
|
-
address: borrowRewardTokens[i],
|
|
3452
|
-
abi: ERC20_DECIMALS_ABI,
|
|
3453
|
-
functionName: "decimals"
|
|
3454
|
-
}).catch(() => 18)
|
|
3455
|
-
]);
|
|
4197
|
+
const entry = rewardPriceMap.get(borrowRewardTokens[i].toLowerCase());
|
|
4198
|
+
const rewardPrice = entry?.price ?? 0n;
|
|
4199
|
+
const rewardDecimals = entry?.decimals ?? 18;
|
|
3456
4200
|
if (rewardPrice > 0n) {
|
|
3457
4201
|
const rewardPriceF = Number(rewardPrice) / priceUnit;
|
|
3458
4202
|
const emissionPerYear = Number(emissionPerSec) / 10 ** rewardDecimals * SECONDS_PER_YEAR4;
|
|
@@ -3516,7 +4260,7 @@ var AaveV3Adapter = class {
|
|
|
3516
4260
|
};
|
|
3517
4261
|
}
|
|
3518
4262
|
};
|
|
3519
|
-
var POOL_ABI2 =
|
|
4263
|
+
var POOL_ABI2 = parseAbi12([
|
|
3520
4264
|
"function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
|
|
3521
4265
|
"function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
|
|
3522
4266
|
"function repay(address asset, uint256 amount, uint256 rateMode, address onBehalfOf) external returns (uint256)",
|
|
@@ -3529,7 +4273,7 @@ var POOL_ABI2 = parseAbi11([
|
|
|
3529
4273
|
// [9]=variableDebtTokenAddress, [10]=interestRateStrategyAddress, [11]=id
|
|
3530
4274
|
"function getReserveData(address asset) external view returns (uint256 configuration, uint128 liquidityIndex, uint128 variableBorrowIndex, uint128 currentLiquidityRate, uint128 currentVariableBorrowRate, uint128 currentStableBorrowRate, uint40 lastUpdateTimestamp, address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress, address interestRateStrategyAddress, uint8 id)"
|
|
3531
4275
|
]);
|
|
3532
|
-
var ERC20_ABI22 =
|
|
4276
|
+
var ERC20_ABI22 = parseAbi12([
|
|
3533
4277
|
"function totalSupply() external view returns (uint256)"
|
|
3534
4278
|
]);
|
|
3535
4279
|
function u256ToF642(v) {
|
|
@@ -3552,7 +4296,7 @@ var AaveV2Adapter = class {
|
|
|
3552
4296
|
return this.protocolName;
|
|
3553
4297
|
}
|
|
3554
4298
|
async buildSupply(params) {
|
|
3555
|
-
const data =
|
|
4299
|
+
const data = encodeFunctionData12({
|
|
3556
4300
|
abi: POOL_ABI2,
|
|
3557
4301
|
functionName: "deposit",
|
|
3558
4302
|
args: [params.asset, params.amount, params.on_behalf_of, 0]
|
|
@@ -3568,7 +4312,7 @@ var AaveV2Adapter = class {
|
|
|
3568
4312
|
}
|
|
3569
4313
|
async buildBorrow(params) {
|
|
3570
4314
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
3571
|
-
const data =
|
|
4315
|
+
const data = encodeFunctionData12({
|
|
3572
4316
|
abi: POOL_ABI2,
|
|
3573
4317
|
functionName: "borrow",
|
|
3574
4318
|
args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
|
|
@@ -3583,7 +4327,7 @@ var AaveV2Adapter = class {
|
|
|
3583
4327
|
}
|
|
3584
4328
|
async buildRepay(params) {
|
|
3585
4329
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
3586
|
-
const data =
|
|
4330
|
+
const data = encodeFunctionData12({
|
|
3587
4331
|
abi: POOL_ABI2,
|
|
3588
4332
|
functionName: "repay",
|
|
3589
4333
|
args: [params.asset, params.amount, rateMode, params.on_behalf_of]
|
|
@@ -3598,7 +4342,7 @@ var AaveV2Adapter = class {
|
|
|
3598
4342
|
};
|
|
3599
4343
|
}
|
|
3600
4344
|
async buildWithdraw(params) {
|
|
3601
|
-
const data =
|
|
4345
|
+
const data = encodeFunctionData12({
|
|
3602
4346
|
abi: POOL_ABI2,
|
|
3603
4347
|
functionName: "withdraw",
|
|
3604
4348
|
args: [params.asset, params.amount, params.to]
|
|
@@ -3686,7 +4430,7 @@ var AaveV2Adapter = class {
|
|
|
3686
4430
|
};
|
|
3687
4431
|
}
|
|
3688
4432
|
};
|
|
3689
|
-
var ORACLE_ABI2 =
|
|
4433
|
+
var ORACLE_ABI2 = parseAbi13([
|
|
3690
4434
|
"function getAssetPrice(address asset) external view returns (uint256)",
|
|
3691
4435
|
"function getAssetsPrices(address[] calldata assets) external view returns (uint256[] memory)",
|
|
3692
4436
|
"function BASE_CURRENCY_UNIT() external view returns (uint256)"
|
|
@@ -3763,7 +4507,7 @@ var AaveOracleAdapter = class {
|
|
|
3763
4507
|
});
|
|
3764
4508
|
}
|
|
3765
4509
|
};
|
|
3766
|
-
var CTOKEN_ABI =
|
|
4510
|
+
var CTOKEN_ABI = parseAbi14([
|
|
3767
4511
|
"function supplyRatePerBlock() external view returns (uint256)",
|
|
3768
4512
|
"function borrowRatePerBlock() external view returns (uint256)",
|
|
3769
4513
|
"function totalSupply() external view returns (uint256)",
|
|
@@ -3790,7 +4534,7 @@ var CompoundV2Adapter = class {
|
|
|
3790
4534
|
return this.protocolName;
|
|
3791
4535
|
}
|
|
3792
4536
|
async buildSupply(params) {
|
|
3793
|
-
const data =
|
|
4537
|
+
const data = encodeFunctionData13({
|
|
3794
4538
|
abi: CTOKEN_ABI,
|
|
3795
4539
|
functionName: "mint",
|
|
3796
4540
|
args: [params.amount]
|
|
@@ -3804,7 +4548,7 @@ var CompoundV2Adapter = class {
|
|
|
3804
4548
|
};
|
|
3805
4549
|
}
|
|
3806
4550
|
async buildBorrow(params) {
|
|
3807
|
-
const data =
|
|
4551
|
+
const data = encodeFunctionData13({
|
|
3808
4552
|
abi: CTOKEN_ABI,
|
|
3809
4553
|
functionName: "borrow",
|
|
3810
4554
|
args: [params.amount]
|
|
@@ -3818,7 +4562,7 @@ var CompoundV2Adapter = class {
|
|
|
3818
4562
|
};
|
|
3819
4563
|
}
|
|
3820
4564
|
async buildRepay(params) {
|
|
3821
|
-
const data =
|
|
4565
|
+
const data = encodeFunctionData13({
|
|
3822
4566
|
abi: CTOKEN_ABI,
|
|
3823
4567
|
functionName: "repayBorrow",
|
|
3824
4568
|
args: [params.amount]
|
|
@@ -3832,7 +4576,7 @@ var CompoundV2Adapter = class {
|
|
|
3832
4576
|
};
|
|
3833
4577
|
}
|
|
3834
4578
|
async buildWithdraw(params) {
|
|
3835
|
-
const data =
|
|
4579
|
+
const data = encodeFunctionData13({
|
|
3836
4580
|
abi: CTOKEN_ABI,
|
|
3837
4581
|
functionName: "redeem",
|
|
3838
4582
|
args: [params.amount]
|
|
@@ -3881,7 +4625,7 @@ var CompoundV2Adapter = class {
|
|
|
3881
4625
|
);
|
|
3882
4626
|
}
|
|
3883
4627
|
};
|
|
3884
|
-
var COMET_ABI =
|
|
4628
|
+
var COMET_ABI = parseAbi15([
|
|
3885
4629
|
"function getUtilization() external view returns (uint256)",
|
|
3886
4630
|
"function getSupplyRate(uint256 utilization) external view returns (uint64)",
|
|
3887
4631
|
"function getBorrowRate(uint256 utilization) external view returns (uint64)",
|
|
@@ -3907,7 +4651,7 @@ var CompoundV3Adapter = class {
|
|
|
3907
4651
|
return this.protocolName;
|
|
3908
4652
|
}
|
|
3909
4653
|
async buildSupply(params) {
|
|
3910
|
-
const data =
|
|
4654
|
+
const data = encodeFunctionData14({
|
|
3911
4655
|
abi: COMET_ABI,
|
|
3912
4656
|
functionName: "supply",
|
|
3913
4657
|
args: [params.asset, params.amount]
|
|
@@ -3921,7 +4665,7 @@ var CompoundV3Adapter = class {
|
|
|
3921
4665
|
};
|
|
3922
4666
|
}
|
|
3923
4667
|
async buildBorrow(params) {
|
|
3924
|
-
const data =
|
|
4668
|
+
const data = encodeFunctionData14({
|
|
3925
4669
|
abi: COMET_ABI,
|
|
3926
4670
|
functionName: "withdraw",
|
|
3927
4671
|
args: [params.asset, params.amount]
|
|
@@ -3935,7 +4679,7 @@ var CompoundV3Adapter = class {
|
|
|
3935
4679
|
};
|
|
3936
4680
|
}
|
|
3937
4681
|
async buildRepay(params) {
|
|
3938
|
-
const data =
|
|
4682
|
+
const data = encodeFunctionData14({
|
|
3939
4683
|
abi: COMET_ABI,
|
|
3940
4684
|
functionName: "supply",
|
|
3941
4685
|
args: [params.asset, params.amount]
|
|
@@ -3949,7 +4693,7 @@ var CompoundV3Adapter = class {
|
|
|
3949
4693
|
};
|
|
3950
4694
|
}
|
|
3951
4695
|
async buildWithdraw(params) {
|
|
3952
|
-
const data =
|
|
4696
|
+
const data = encodeFunctionData14({
|
|
3953
4697
|
abi: COMET_ABI,
|
|
3954
4698
|
functionName: "withdraw",
|
|
3955
4699
|
args: [params.asset, params.amount]
|
|
@@ -4003,7 +4747,7 @@ var CompoundV3Adapter = class {
|
|
|
4003
4747
|
);
|
|
4004
4748
|
}
|
|
4005
4749
|
};
|
|
4006
|
-
var EULER_VAULT_ABI =
|
|
4750
|
+
var EULER_VAULT_ABI = parseAbi16([
|
|
4007
4751
|
"function deposit(uint256 amount, address receiver) external returns (uint256)",
|
|
4008
4752
|
"function withdraw(uint256 amount, address receiver, address owner) external returns (uint256)",
|
|
4009
4753
|
"function borrow(uint256 amount, address receiver) external returns (uint256)",
|
|
@@ -4029,7 +4773,7 @@ var EulerV2Adapter = class {
|
|
|
4029
4773
|
return this.protocolName;
|
|
4030
4774
|
}
|
|
4031
4775
|
async buildSupply(params) {
|
|
4032
|
-
const data =
|
|
4776
|
+
const data = encodeFunctionData15({
|
|
4033
4777
|
abi: EULER_VAULT_ABI,
|
|
4034
4778
|
functionName: "deposit",
|
|
4035
4779
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -4043,7 +4787,7 @@ var EulerV2Adapter = class {
|
|
|
4043
4787
|
};
|
|
4044
4788
|
}
|
|
4045
4789
|
async buildBorrow(params) {
|
|
4046
|
-
const data =
|
|
4790
|
+
const data = encodeFunctionData15({
|
|
4047
4791
|
abi: EULER_VAULT_ABI,
|
|
4048
4792
|
functionName: "borrow",
|
|
4049
4793
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -4057,7 +4801,7 @@ var EulerV2Adapter = class {
|
|
|
4057
4801
|
};
|
|
4058
4802
|
}
|
|
4059
4803
|
async buildRepay(params) {
|
|
4060
|
-
const data =
|
|
4804
|
+
const data = encodeFunctionData15({
|
|
4061
4805
|
abi: EULER_VAULT_ABI,
|
|
4062
4806
|
functionName: "repay",
|
|
4063
4807
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -4071,7 +4815,7 @@ var EulerV2Adapter = class {
|
|
|
4071
4815
|
};
|
|
4072
4816
|
}
|
|
4073
4817
|
async buildWithdraw(params) {
|
|
4074
|
-
const data =
|
|
4818
|
+
const data = encodeFunctionData15({
|
|
4075
4819
|
abi: EULER_VAULT_ABI,
|
|
4076
4820
|
functionName: "withdraw",
|
|
4077
4821
|
args: [params.amount, params.to, params.to]
|
|
@@ -4120,7 +4864,7 @@ var EulerV2Adapter = class {
|
|
|
4120
4864
|
);
|
|
4121
4865
|
}
|
|
4122
4866
|
};
|
|
4123
|
-
var MORPHO_ABI =
|
|
4867
|
+
var MORPHO_ABI = parseAbi17([
|
|
4124
4868
|
"function market(bytes32 id) external view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)",
|
|
4125
4869
|
"function idToMarketParams(bytes32 id) external view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)",
|
|
4126
4870
|
"function supply((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, uint256 shares, address onBehalf, bytes data) external returns (uint256 assetsSupplied, uint256 sharesSupplied)",
|
|
@@ -4128,13 +4872,13 @@ var MORPHO_ABI = parseAbi16([
|
|
|
4128
4872
|
"function repay((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, uint256 shares, address onBehalf, bytes data) external returns (uint256 assetsRepaid, uint256 sharesRepaid)",
|
|
4129
4873
|
"function withdraw((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, uint256 shares, address onBehalf, address receiver) external returns (uint256 assetsWithdrawn, uint256 sharesWithdrawn)"
|
|
4130
4874
|
]);
|
|
4131
|
-
var META_MORPHO_ABI =
|
|
4875
|
+
var META_MORPHO_ABI = parseAbi17([
|
|
4132
4876
|
"function supplyQueueLength() external view returns (uint256)",
|
|
4133
4877
|
"function supplyQueue(uint256 index) external view returns (bytes32)",
|
|
4134
4878
|
"function totalAssets() external view returns (uint256)",
|
|
4135
4879
|
"function totalSupply() external view returns (uint256)"
|
|
4136
4880
|
]);
|
|
4137
|
-
var IRM_ABI =
|
|
4881
|
+
var IRM_ABI = parseAbi17([
|
|
4138
4882
|
"function borrowRateView((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee) market) external view returns (uint256)"
|
|
4139
4883
|
]);
|
|
4140
4884
|
var SECONDS_PER_YEAR3 = 365.25 * 24 * 3600;
|
|
@@ -4147,6 +4891,30 @@ function defaultMarketParams(loanToken = zeroAddress7) {
|
|
|
4147
4891
|
lltv: 0n
|
|
4148
4892
|
};
|
|
4149
4893
|
}
|
|
4894
|
+
function decodeMarket(data) {
|
|
4895
|
+
if (!data) return null;
|
|
4896
|
+
try {
|
|
4897
|
+
return decodeFunctionResult4({
|
|
4898
|
+
abi: MORPHO_ABI,
|
|
4899
|
+
functionName: "market",
|
|
4900
|
+
data
|
|
4901
|
+
});
|
|
4902
|
+
} catch {
|
|
4903
|
+
return null;
|
|
4904
|
+
}
|
|
4905
|
+
}
|
|
4906
|
+
function decodeMarketParams(data) {
|
|
4907
|
+
if (!data) return null;
|
|
4908
|
+
try {
|
|
4909
|
+
return decodeFunctionResult4({
|
|
4910
|
+
abi: MORPHO_ABI,
|
|
4911
|
+
functionName: "idToMarketParams",
|
|
4912
|
+
data
|
|
4913
|
+
});
|
|
4914
|
+
} catch {
|
|
4915
|
+
return null;
|
|
4916
|
+
}
|
|
4917
|
+
}
|
|
4150
4918
|
var MorphoBlueAdapter = class {
|
|
4151
4919
|
protocolName;
|
|
4152
4920
|
morpho;
|
|
@@ -4166,7 +4934,7 @@ var MorphoBlueAdapter = class {
|
|
|
4166
4934
|
}
|
|
4167
4935
|
async buildSupply(params) {
|
|
4168
4936
|
const market = defaultMarketParams(params.asset);
|
|
4169
|
-
const data =
|
|
4937
|
+
const data = encodeFunctionData16({
|
|
4170
4938
|
abi: MORPHO_ABI,
|
|
4171
4939
|
functionName: "supply",
|
|
4172
4940
|
args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
|
|
@@ -4181,7 +4949,7 @@ var MorphoBlueAdapter = class {
|
|
|
4181
4949
|
}
|
|
4182
4950
|
async buildBorrow(params) {
|
|
4183
4951
|
const market = defaultMarketParams(params.asset);
|
|
4184
|
-
const data =
|
|
4952
|
+
const data = encodeFunctionData16({
|
|
4185
4953
|
abi: MORPHO_ABI,
|
|
4186
4954
|
functionName: "borrow",
|
|
4187
4955
|
args: [market, params.amount, 0n, params.on_behalf_of, params.on_behalf_of]
|
|
@@ -4196,7 +4964,7 @@ var MorphoBlueAdapter = class {
|
|
|
4196
4964
|
}
|
|
4197
4965
|
async buildRepay(params) {
|
|
4198
4966
|
const market = defaultMarketParams(params.asset);
|
|
4199
|
-
const data =
|
|
4967
|
+
const data = encodeFunctionData16({
|
|
4200
4968
|
abi: MORPHO_ABI,
|
|
4201
4969
|
functionName: "repay",
|
|
4202
4970
|
args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
|
|
@@ -4211,7 +4979,7 @@ var MorphoBlueAdapter = class {
|
|
|
4211
4979
|
}
|
|
4212
4980
|
async buildWithdraw(params) {
|
|
4213
4981
|
const market = defaultMarketParams(params.asset);
|
|
4214
|
-
const data =
|
|
4982
|
+
const data = encodeFunctionData16({
|
|
4215
4983
|
abi: MORPHO_ABI,
|
|
4216
4984
|
functionName: "withdraw",
|
|
4217
4985
|
args: [market, params.amount, 0n, params.to, params.to]
|
|
@@ -4229,14 +4997,12 @@ var MorphoBlueAdapter = class {
|
|
|
4229
4997
|
if (!this.defaultVault) {
|
|
4230
4998
|
throw DefiError.contractError(`[${this.protocolName}] No MetaMorpho vault configured for rate query`);
|
|
4231
4999
|
}
|
|
4232
|
-
const
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
abi: META_MORPHO_ABI,
|
|
4236
|
-
functionName: "supplyQueueLength"
|
|
4237
|
-
}).catch((e) => {
|
|
5000
|
+
const [queueLenRaw] = await multicallRead(this.rpcUrl, [
|
|
5001
|
+
[this.defaultVault, encodeFunctionData16({ abi: META_MORPHO_ABI, functionName: "supplyQueueLength" })]
|
|
5002
|
+
]).catch((e) => {
|
|
4238
5003
|
throw DefiError.rpcError(`[${this.protocolName}] supplyQueueLength failed: ${e}`);
|
|
4239
5004
|
});
|
|
5005
|
+
const queueLen = decodeU256(queueLenRaw ?? null);
|
|
4240
5006
|
if (queueLen === 0n) {
|
|
4241
5007
|
return {
|
|
4242
5008
|
protocol: this.protocolName,
|
|
@@ -4248,45 +5014,40 @@ var MorphoBlueAdapter = class {
|
|
|
4248
5014
|
total_borrow: 0n
|
|
4249
5015
|
};
|
|
4250
5016
|
}
|
|
4251
|
-
const
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
functionName: "supplyQueue",
|
|
4255
|
-
args: [0n]
|
|
4256
|
-
}).catch((e) => {
|
|
5017
|
+
const [marketIdRaw] = await multicallRead(this.rpcUrl, [
|
|
5018
|
+
[this.defaultVault, encodeFunctionData16({ abi: META_MORPHO_ABI, functionName: "supplyQueue", args: [0n] })]
|
|
5019
|
+
]).catch((e) => {
|
|
4257
5020
|
throw DefiError.rpcError(`[${this.protocolName}] supplyQueue(0) failed: ${e}`);
|
|
4258
5021
|
});
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
5022
|
+
if (!marketIdRaw || marketIdRaw.length < 66) {
|
|
5023
|
+
throw DefiError.rpcError(`[${this.protocolName}] supplyQueue(0) returned no data`);
|
|
5024
|
+
}
|
|
5025
|
+
const marketId = marketIdRaw.slice(0, 66);
|
|
5026
|
+
const [marketRaw, paramsRaw] = await multicallRead(this.rpcUrl, [
|
|
5027
|
+
[this.morpho, encodeFunctionData16({ abi: MORPHO_ABI, functionName: "market", args: [marketId] })],
|
|
5028
|
+
[this.morpho, encodeFunctionData16({ abi: MORPHO_ABI, functionName: "idToMarketParams", args: [marketId] })]
|
|
5029
|
+
]).catch((e) => {
|
|
5030
|
+
throw DefiError.rpcError(`[${this.protocolName}] market/idToMarketParams failed: ${e}`);
|
|
4266
5031
|
});
|
|
4267
|
-
const
|
|
5032
|
+
const mktDecoded = decodeMarket(marketRaw ?? null);
|
|
5033
|
+
if (!mktDecoded) throw DefiError.rpcError(`[${this.protocolName}] market() returned no data`);
|
|
5034
|
+
const [totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee] = mktDecoded;
|
|
5035
|
+
const paramsDecoded = decodeMarketParams(paramsRaw ?? null);
|
|
5036
|
+
if (!paramsDecoded) throw DefiError.rpcError(`[${this.protocolName}] idToMarketParams returned no data`);
|
|
5037
|
+
const [loanToken, collateralToken, oracle, irm, lltv] = paramsDecoded;
|
|
4268
5038
|
const supplyF = Number(totalSupplyAssets);
|
|
4269
5039
|
const borrowF = Number(totalBorrowAssets);
|
|
4270
5040
|
const util = supplyF > 0 ? borrowF / supplyF : 0;
|
|
4271
|
-
const params2 = await client.readContract({
|
|
4272
|
-
address: this.morpho,
|
|
4273
|
-
abi: MORPHO_ABI,
|
|
4274
|
-
functionName: "idToMarketParams",
|
|
4275
|
-
args: [marketId]
|
|
4276
|
-
}).catch((e) => {
|
|
4277
|
-
throw DefiError.rpcError(`[${this.protocolName}] idToMarketParams failed: ${e}`);
|
|
4278
|
-
});
|
|
4279
|
-
const [loanToken, collateralToken, oracle, irm, lltv] = params2;
|
|
4280
5041
|
const irmMarketParams = { loanToken, collateralToken, oracle, irm, lltv };
|
|
4281
5042
|
const irmMarket = { totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee };
|
|
4282
|
-
const borrowRatePerSec = await
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
});
|
|
5043
|
+
const borrowRatePerSec = await (async () => {
|
|
5044
|
+
const [borrowRateRaw] = await multicallRead(this.rpcUrl, [
|
|
5045
|
+
[irm, encodeFunctionData16({ abi: IRM_ABI, functionName: "borrowRateView", args: [irmMarketParams, irmMarket] })]
|
|
5046
|
+
]).catch((e) => {
|
|
5047
|
+
throw DefiError.rpcError(`[${this.protocolName}] borrowRateView failed: ${e}`);
|
|
5048
|
+
});
|
|
5049
|
+
return decodeU256(borrowRateRaw ?? null);
|
|
5050
|
+
})();
|
|
4290
5051
|
const ratePerSec = Number(borrowRatePerSec) / 1e18;
|
|
4291
5052
|
const borrowApy = ratePerSec * SECONDS_PER_YEAR3 * 100;
|
|
4292
5053
|
const feePct = Number(fee) / 1e18;
|
|
@@ -4307,18 +5068,18 @@ var MorphoBlueAdapter = class {
|
|
|
4307
5068
|
);
|
|
4308
5069
|
}
|
|
4309
5070
|
};
|
|
4310
|
-
var BORROWER_OPS_ABI =
|
|
5071
|
+
var BORROWER_OPS_ABI = parseAbi18([
|
|
4311
5072
|
"function openTrove(address _owner, uint256 _ownerIndex, uint256 _collAmount, uint256 _boldAmount, uint256 _upperHint, uint256 _lowerHint, uint256 _annualInterestRate, uint256 _maxUpfrontFee, address _addManager, address _removeManager, address _receiver) external returns (uint256)",
|
|
4312
5073
|
"function adjustTrove(uint256 _troveId, uint256 _collChange, bool _isCollIncrease, uint256 _debtChange, bool _isDebtIncrease, uint256 _upperHint, uint256 _lowerHint, uint256 _maxUpfrontFee) external",
|
|
4313
5074
|
"function closeTrove(uint256 _troveId) external"
|
|
4314
5075
|
]);
|
|
4315
|
-
var TROVE_MANAGER_ABI =
|
|
5076
|
+
var TROVE_MANAGER_ABI = parseAbi18([
|
|
4316
5077
|
"function getLatestTroveData(uint256 _troveId) external view returns (uint256 entireDebt, uint256 entireColl, uint256 redistDebtGain, uint256 redistCollGain, uint256 accruedInterest, uint256 recordedDebt, uint256 annualInterestRate, uint256 accruedBatchManagementFee, uint256 weightedRecordedDebt, uint256 lastInterestRateAdjTime)"
|
|
4317
5078
|
]);
|
|
4318
|
-
var HINT_HELPERS_ABI =
|
|
5079
|
+
var HINT_HELPERS_ABI = parseAbi18([
|
|
4319
5080
|
"function getApproxHint(uint256 _collIndex, uint256 _interestRate, uint256 _numTrials, uint256 _inputRandomSeed) external view returns (uint256 hintId, uint256 diff, uint256 latestRandomSeed)"
|
|
4320
5081
|
]);
|
|
4321
|
-
var SORTED_TROVES_ABI =
|
|
5082
|
+
var SORTED_TROVES_ABI = parseAbi18([
|
|
4322
5083
|
"function findInsertPosition(uint256 _annualInterestRate, uint256 _prevId, uint256 _nextId) external view returns (uint256 prevId, uint256 nextId)"
|
|
4323
5084
|
]);
|
|
4324
5085
|
var FelixCdpAdapter = class {
|
|
@@ -4346,7 +5107,7 @@ var FelixCdpAdapter = class {
|
|
|
4346
5107
|
if (!this.hintHelpers || !this.sortedTroves || !this.rpcUrl) {
|
|
4347
5108
|
return [0n, 0n];
|
|
4348
5109
|
}
|
|
4349
|
-
const client =
|
|
5110
|
+
const client = createPublicClient13({ transport: http13(this.rpcUrl) });
|
|
4350
5111
|
const approxResult = await client.readContract({
|
|
4351
5112
|
address: this.hintHelpers,
|
|
4352
5113
|
abi: HINT_HELPERS_ABI,
|
|
@@ -4369,7 +5130,7 @@ var FelixCdpAdapter = class {
|
|
|
4369
5130
|
const interestRate = 50000000000000000n;
|
|
4370
5131
|
const [upperHint, lowerHint] = await this.getHints(interestRate);
|
|
4371
5132
|
const hasHints = upperHint !== 0n || lowerHint !== 0n;
|
|
4372
|
-
const data =
|
|
5133
|
+
const data = encodeFunctionData17({
|
|
4373
5134
|
abi: BORROWER_OPS_ABI,
|
|
4374
5135
|
functionName: "openTrove",
|
|
4375
5136
|
args: [
|
|
@@ -4398,7 +5159,7 @@ var FelixCdpAdapter = class {
|
|
|
4398
5159
|
async buildAdjust(params) {
|
|
4399
5160
|
const collChange = params.collateral_delta ?? 0n;
|
|
4400
5161
|
const debtChange = params.debt_delta ?? 0n;
|
|
4401
|
-
const data =
|
|
5162
|
+
const data = encodeFunctionData17({
|
|
4402
5163
|
abi: BORROWER_OPS_ABI,
|
|
4403
5164
|
functionName: "adjustTrove",
|
|
4404
5165
|
args: [
|
|
@@ -4421,7 +5182,7 @@ var FelixCdpAdapter = class {
|
|
|
4421
5182
|
};
|
|
4422
5183
|
}
|
|
4423
5184
|
async buildClose(params) {
|
|
4424
|
-
const data =
|
|
5185
|
+
const data = encodeFunctionData17({
|
|
4425
5186
|
abi: BORROWER_OPS_ABI,
|
|
4426
5187
|
functionName: "closeTrove",
|
|
4427
5188
|
args: [params.cdp_id]
|
|
@@ -4437,7 +5198,7 @@ var FelixCdpAdapter = class {
|
|
|
4437
5198
|
async getCdpInfo(cdpId) {
|
|
4438
5199
|
if (!this.rpcUrl) throw DefiError.rpcError(`[${this.protocolName}] getCdpInfo requires RPC \u2014 set HYPEREVM_RPC_URL`);
|
|
4439
5200
|
if (!this.troveManager) throw DefiError.contractError(`[${this.protocolName}] trove_manager contract not configured`);
|
|
4440
|
-
const client =
|
|
5201
|
+
const client = createPublicClient13({ transport: http13(this.rpcUrl) });
|
|
4441
5202
|
const data = await client.readContract({
|
|
4442
5203
|
address: this.troveManager,
|
|
4443
5204
|
abi: TROVE_MANAGER_ABI,
|
|
@@ -4470,7 +5231,7 @@ var FelixCdpAdapter = class {
|
|
|
4470
5231
|
};
|
|
4471
5232
|
}
|
|
4472
5233
|
};
|
|
4473
|
-
var PRICE_FEED_ABI =
|
|
5234
|
+
var PRICE_FEED_ABI = parseAbi19([
|
|
4474
5235
|
"function fetchPrice() external view returns (uint256 price, bool isNewOracleFailureDetected)",
|
|
4475
5236
|
"function lastGoodPrice() external view returns (uint256)"
|
|
4476
5237
|
]);
|
|
@@ -4496,7 +5257,7 @@ var FelixOracleAdapter = class {
|
|
|
4496
5257
|
if (asset !== this.asset && this.asset !== "0x0000000000000000000000000000000000000000") {
|
|
4497
5258
|
throw DefiError.unsupported(`[${this.protocolName}] Felix PriceFeed only supports asset ${this.asset}`);
|
|
4498
5259
|
}
|
|
4499
|
-
const client =
|
|
5260
|
+
const client = createPublicClient14({ transport: http14(this.rpcUrl) });
|
|
4500
5261
|
let priceVal;
|
|
4501
5262
|
try {
|
|
4502
5263
|
const result = await client.readContract({
|
|
@@ -4535,7 +5296,7 @@ var FelixOracleAdapter = class {
|
|
|
4535
5296
|
return results;
|
|
4536
5297
|
}
|
|
4537
5298
|
};
|
|
4538
|
-
var ERC4626_ABI =
|
|
5299
|
+
var ERC4626_ABI = parseAbi20([
|
|
4539
5300
|
"function asset() external view returns (address)",
|
|
4540
5301
|
"function totalAssets() external view returns (uint256)",
|
|
4541
5302
|
"function totalSupply() external view returns (uint256)",
|
|
@@ -4559,7 +5320,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4559
5320
|
return this.protocolName;
|
|
4560
5321
|
}
|
|
4561
5322
|
async buildDeposit(assets, receiver) {
|
|
4562
|
-
const data =
|
|
5323
|
+
const data = encodeFunctionData18({
|
|
4563
5324
|
abi: ERC4626_ABI,
|
|
4564
5325
|
functionName: "deposit",
|
|
4565
5326
|
args: [assets, receiver]
|
|
@@ -4573,7 +5334,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4573
5334
|
};
|
|
4574
5335
|
}
|
|
4575
5336
|
async buildWithdraw(assets, receiver, owner) {
|
|
4576
|
-
const data =
|
|
5337
|
+
const data = encodeFunctionData18({
|
|
4577
5338
|
abi: ERC4626_ABI,
|
|
4578
5339
|
functionName: "withdraw",
|
|
4579
5340
|
args: [assets, receiver, owner]
|
|
@@ -4588,7 +5349,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4588
5349
|
}
|
|
4589
5350
|
async totalAssets() {
|
|
4590
5351
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4591
|
-
const client =
|
|
5352
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4592
5353
|
return client.readContract({
|
|
4593
5354
|
address: this.vaultAddress,
|
|
4594
5355
|
abi: ERC4626_ABI,
|
|
@@ -4599,7 +5360,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4599
5360
|
}
|
|
4600
5361
|
async convertToShares(assets) {
|
|
4601
5362
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4602
|
-
const client =
|
|
5363
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4603
5364
|
return client.readContract({
|
|
4604
5365
|
address: this.vaultAddress,
|
|
4605
5366
|
abi: ERC4626_ABI,
|
|
@@ -4611,7 +5372,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4611
5372
|
}
|
|
4612
5373
|
async convertToAssets(shares) {
|
|
4613
5374
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4614
|
-
const client =
|
|
5375
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4615
5376
|
return client.readContract({
|
|
4616
5377
|
address: this.vaultAddress,
|
|
4617
5378
|
abi: ERC4626_ABI,
|
|
@@ -4623,7 +5384,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4623
5384
|
}
|
|
4624
5385
|
async getVaultInfo() {
|
|
4625
5386
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4626
|
-
const client =
|
|
5387
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4627
5388
|
const [totalAssets, totalSupply, asset] = await Promise.all([
|
|
4628
5389
|
client.readContract({ address: this.vaultAddress, abi: ERC4626_ABI, functionName: "totalAssets" }).catch((e) => {
|
|
4629
5390
|
throw DefiError.rpcError(`[${this.protocolName}] totalAssets failed: ${e}`);
|
|
@@ -4644,7 +5405,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4644
5405
|
};
|
|
4645
5406
|
}
|
|
4646
5407
|
};
|
|
4647
|
-
var GENERIC_LST_ABI =
|
|
5408
|
+
var GENERIC_LST_ABI = parseAbi21([
|
|
4648
5409
|
"function stake() external payable returns (uint256)",
|
|
4649
5410
|
"function unstake(uint256 amount) external returns (uint256)"
|
|
4650
5411
|
]);
|
|
@@ -4661,7 +5422,7 @@ var GenericLstAdapter = class {
|
|
|
4661
5422
|
return this.protocolName;
|
|
4662
5423
|
}
|
|
4663
5424
|
async buildStake(params) {
|
|
4664
|
-
const data =
|
|
5425
|
+
const data = encodeFunctionData19({ abi: GENERIC_LST_ABI, functionName: "stake" });
|
|
4665
5426
|
return {
|
|
4666
5427
|
description: `[${this.protocolName}] Stake ${params.amount} HYPE`,
|
|
4667
5428
|
to: this.staking,
|
|
@@ -4671,7 +5432,7 @@ var GenericLstAdapter = class {
|
|
|
4671
5432
|
};
|
|
4672
5433
|
}
|
|
4673
5434
|
async buildUnstake(params) {
|
|
4674
|
-
const data =
|
|
5435
|
+
const data = encodeFunctionData19({
|
|
4675
5436
|
abi: GENERIC_LST_ABI,
|
|
4676
5437
|
functionName: "unstake",
|
|
4677
5438
|
args: [params.amount]
|
|
@@ -4688,11 +5449,11 @@ var GenericLstAdapter = class {
|
|
|
4688
5449
|
throw DefiError.unsupported(`[${this.protocolName}] getInfo requires RPC`);
|
|
4689
5450
|
}
|
|
4690
5451
|
};
|
|
4691
|
-
var STHYPE_ABI =
|
|
5452
|
+
var STHYPE_ABI = parseAbi222([
|
|
4692
5453
|
"function submit(address referral) external payable returns (uint256)",
|
|
4693
5454
|
"function requestWithdrawals(uint256[] amounts, address owner) external returns (uint256[] requestIds)"
|
|
4694
5455
|
]);
|
|
4695
|
-
var ERC20_ABI3 =
|
|
5456
|
+
var ERC20_ABI3 = parseAbi222([
|
|
4696
5457
|
"function totalSupply() external view returns (uint256)"
|
|
4697
5458
|
]);
|
|
4698
5459
|
var StHypeAdapter = class {
|
|
@@ -4712,7 +5473,7 @@ var StHypeAdapter = class {
|
|
|
4712
5473
|
return this.protocolName;
|
|
4713
5474
|
}
|
|
4714
5475
|
async buildStake(params) {
|
|
4715
|
-
const data =
|
|
5476
|
+
const data = encodeFunctionData20({
|
|
4716
5477
|
abi: STHYPE_ABI,
|
|
4717
5478
|
functionName: "submit",
|
|
4718
5479
|
args: [zeroAddress9]
|
|
@@ -4726,7 +5487,7 @@ var StHypeAdapter = class {
|
|
|
4726
5487
|
};
|
|
4727
5488
|
}
|
|
4728
5489
|
async buildUnstake(params) {
|
|
4729
|
-
const data =
|
|
5490
|
+
const data = encodeFunctionData20({
|
|
4730
5491
|
abi: STHYPE_ABI,
|
|
4731
5492
|
functionName: "requestWithdrawals",
|
|
4732
5493
|
args: [[params.amount], params.recipient]
|
|
@@ -4741,7 +5502,7 @@ var StHypeAdapter = class {
|
|
|
4741
5502
|
}
|
|
4742
5503
|
async getInfo() {
|
|
4743
5504
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4744
|
-
const client =
|
|
5505
|
+
const client = createPublicClient16({ transport: http16(this.rpcUrl) });
|
|
4745
5506
|
const tokenAddr = this.sthypeToken ?? this.staking;
|
|
4746
5507
|
const totalSupply = await client.readContract({
|
|
4747
5508
|
address: tokenAddr,
|
|
@@ -4759,12 +5520,12 @@ var StHypeAdapter = class {
|
|
|
4759
5520
|
};
|
|
4760
5521
|
}
|
|
4761
5522
|
};
|
|
4762
|
-
var KINETIQ_ABI =
|
|
5523
|
+
var KINETIQ_ABI = parseAbi23([
|
|
4763
5524
|
"function stake() external payable returns (uint256)",
|
|
4764
5525
|
"function requestUnstake(uint256 amount) external returns (uint256)",
|
|
4765
5526
|
"function totalStaked() external view returns (uint256)"
|
|
4766
5527
|
]);
|
|
4767
|
-
var ORACLE_ABI3 =
|
|
5528
|
+
var ORACLE_ABI3 = parseAbi23([
|
|
4768
5529
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
4769
5530
|
]);
|
|
4770
5531
|
var WHYPE = "0x5555555555555555555555555555555555555555";
|
|
@@ -4786,7 +5547,7 @@ var KinetiqAdapter = class {
|
|
|
4786
5547
|
return this.protocolName;
|
|
4787
5548
|
}
|
|
4788
5549
|
async buildStake(params) {
|
|
4789
|
-
const data =
|
|
5550
|
+
const data = encodeFunctionData21({ abi: KINETIQ_ABI, functionName: "stake" });
|
|
4790
5551
|
return {
|
|
4791
5552
|
description: `[${this.protocolName}] Stake ${params.amount} HYPE for kHYPE`,
|
|
4792
5553
|
to: this.staking,
|
|
@@ -4796,7 +5557,7 @@ var KinetiqAdapter = class {
|
|
|
4796
5557
|
};
|
|
4797
5558
|
}
|
|
4798
5559
|
async buildUnstake(params) {
|
|
4799
|
-
const data =
|
|
5560
|
+
const data = encodeFunctionData21({
|
|
4800
5561
|
abi: KINETIQ_ABI,
|
|
4801
5562
|
functionName: "requestUnstake",
|
|
4802
5563
|
args: [params.amount]
|
|
@@ -4811,7 +5572,7 @@ var KinetiqAdapter = class {
|
|
|
4811
5572
|
}
|
|
4812
5573
|
async getInfo() {
|
|
4813
5574
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4814
|
-
const client =
|
|
5575
|
+
const client = createPublicClient17({ transport: http17(this.rpcUrl) });
|
|
4815
5576
|
const totalStaked = await client.readContract({
|
|
4816
5577
|
address: this.staking,
|
|
4817
5578
|
abi: KINETIQ_ABI,
|
|
@@ -4833,15 +5594,15 @@ var KinetiqAdapter = class {
|
|
|
4833
5594
|
};
|
|
4834
5595
|
}
|
|
4835
5596
|
};
|
|
4836
|
-
var HLP_ABI =
|
|
5597
|
+
var HLP_ABI = parseAbi24([
|
|
4837
5598
|
"function deposit(uint256 amount) external returns (uint256)",
|
|
4838
5599
|
"function withdraw(uint256 shares) external returns (uint256)"
|
|
4839
5600
|
]);
|
|
4840
|
-
var RYSK_ABI =
|
|
5601
|
+
var RYSK_ABI = parseAbi25([
|
|
4841
5602
|
"function openOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 premium)",
|
|
4842
5603
|
"function closeOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 payout)"
|
|
4843
5604
|
]);
|
|
4844
|
-
var ERC721_ABI =
|
|
5605
|
+
var ERC721_ABI = parseAbi26([
|
|
4845
5606
|
"function name() returns (string)",
|
|
4846
5607
|
"function symbol() returns (string)",
|
|
4847
5608
|
"function totalSupply() returns (uint256)",
|
|
@@ -4861,7 +5622,7 @@ var ERC721Adapter = class {
|
|
|
4861
5622
|
}
|
|
4862
5623
|
async getCollectionInfo(collection) {
|
|
4863
5624
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4864
|
-
const client =
|
|
5625
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
4865
5626
|
const [collectionName, symbol, totalSupply] = await Promise.all([
|
|
4866
5627
|
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "name" }).catch((e) => {
|
|
4867
5628
|
throw DefiError.rpcError(`[${this.protocolName}] name failed: ${e}`);
|
|
@@ -4880,7 +5641,7 @@ var ERC721Adapter = class {
|
|
|
4880
5641
|
}
|
|
4881
5642
|
async getTokenInfo(collection, tokenId) {
|
|
4882
5643
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4883
|
-
const client =
|
|
5644
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
4884
5645
|
const [owner, tokenUri] = await Promise.all([
|
|
4885
5646
|
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "ownerOf", args: [tokenId] }).catch((e) => {
|
|
4886
5647
|
throw DefiError.rpcError(`[${this.protocolName}] ownerOf failed: ${e}`);
|
|
@@ -4896,7 +5657,7 @@ var ERC721Adapter = class {
|
|
|
4896
5657
|
}
|
|
4897
5658
|
async getBalance(owner, collection) {
|
|
4898
5659
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4899
|
-
const client =
|
|
5660
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
4900
5661
|
return client.readContract({ address: collection, abi: ERC721_ABI, functionName: "balanceOf", args: [owner] }).catch((e) => {
|
|
4901
5662
|
throw DefiError.rpcError(`[${this.protocolName}] balanceOf failed: ${e}`);
|
|
4902
5663
|
});
|
|
@@ -5017,6 +5778,9 @@ function createOracleFromCdp(entry, _asset, rpcUrl) {
|
|
|
5017
5778
|
throw DefiError.unsupported(`Oracle not available for CDP interface '${entry.interface}'`);
|
|
5018
5779
|
}
|
|
5019
5780
|
}
|
|
5781
|
+
function createMerchantMoeLB(entry, rpcUrl) {
|
|
5782
|
+
return new MerchantMoeLBAdapter(entry, rpcUrl);
|
|
5783
|
+
}
|
|
5020
5784
|
var DexSpotPrice = class {
|
|
5021
5785
|
/**
|
|
5022
5786
|
* Get the spot price for `token` denominated in `quoteToken` (e.g. USDC).
|
|
@@ -6024,20 +6788,20 @@ function registerYield(parent, getOpts, makeExecutor2) {
|
|
|
6024
6788
|
}
|
|
6025
6789
|
|
|
6026
6790
|
// src/commands/portfolio.ts
|
|
6027
|
-
import { encodeFunctionData as
|
|
6791
|
+
import { encodeFunctionData as encodeFunctionData25, parseAbi as parseAbi28 } from "viem";
|
|
6028
6792
|
|
|
6029
6793
|
// src/portfolio-tracker.ts
|
|
6030
6794
|
import { mkdirSync, writeFileSync, readdirSync as readdirSync2, readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
6031
6795
|
import { homedir } from "os";
|
|
6032
6796
|
import { resolve as resolve2 } from "path";
|
|
6033
|
-
import { encodeFunctionData as
|
|
6034
|
-
var ERC20_ABI4 =
|
|
6797
|
+
import { encodeFunctionData as encodeFunctionData24, parseAbi as parseAbi27 } from "viem";
|
|
6798
|
+
var ERC20_ABI4 = parseAbi27([
|
|
6035
6799
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
6036
6800
|
]);
|
|
6037
|
-
var ORACLE_ABI4 =
|
|
6801
|
+
var ORACLE_ABI4 = parseAbi27([
|
|
6038
6802
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
6039
6803
|
]);
|
|
6040
|
-
var POOL_ABI3 =
|
|
6804
|
+
var POOL_ABI3 = parseAbi27([
|
|
6041
6805
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
6042
6806
|
]);
|
|
6043
6807
|
function decodeU256Word(data, wordOffset = 0) {
|
|
@@ -6066,7 +6830,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
6066
6830
|
tokenEntries.push({ symbol: t.symbol, address: entry.address, decimals: entry.decimals });
|
|
6067
6831
|
calls.push([
|
|
6068
6832
|
entry.address,
|
|
6069
|
-
|
|
6833
|
+
encodeFunctionData24({ abi: ERC20_ABI4, functionName: "balanceOf", args: [user] })
|
|
6070
6834
|
]);
|
|
6071
6835
|
callLabels.push(`balance:${t.symbol}`);
|
|
6072
6836
|
}
|
|
@@ -6074,7 +6838,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
6074
6838
|
for (const p of lendingProtocols) {
|
|
6075
6839
|
calls.push([
|
|
6076
6840
|
p.contracts["pool"],
|
|
6077
|
-
|
|
6841
|
+
encodeFunctionData24({ abi: POOL_ABI3, functionName: "getUserAccountData", args: [user] })
|
|
6078
6842
|
]);
|
|
6079
6843
|
callLabels.push(`lending:${p.name}`);
|
|
6080
6844
|
}
|
|
@@ -6084,7 +6848,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
6084
6848
|
if (oracleAddr) {
|
|
6085
6849
|
calls.push([
|
|
6086
6850
|
oracleAddr,
|
|
6087
|
-
|
|
6851
|
+
encodeFunctionData24({ abi: ORACLE_ABI4, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
6088
6852
|
]);
|
|
6089
6853
|
callLabels.push("price:native");
|
|
6090
6854
|
}
|
|
@@ -6222,13 +6986,13 @@ function calculatePnL(current, previous) {
|
|
|
6222
6986
|
}
|
|
6223
6987
|
|
|
6224
6988
|
// src/commands/portfolio.ts
|
|
6225
|
-
var ERC20_ABI5 =
|
|
6989
|
+
var ERC20_ABI5 = parseAbi28([
|
|
6226
6990
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
6227
6991
|
]);
|
|
6228
|
-
var POOL_ABI4 =
|
|
6992
|
+
var POOL_ABI4 = parseAbi28([
|
|
6229
6993
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
6230
6994
|
]);
|
|
6231
|
-
var ORACLE_ABI5 =
|
|
6995
|
+
var ORACLE_ABI5 = parseAbi28([
|
|
6232
6996
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
6233
6997
|
]);
|
|
6234
6998
|
function decodeU2562(data, wordOffset = 0) {
|
|
@@ -6268,7 +7032,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6268
7032
|
if (entry.address === "0x0000000000000000000000000000000000000000") continue;
|
|
6269
7033
|
calls.push([
|
|
6270
7034
|
entry.address,
|
|
6271
|
-
|
|
7035
|
+
encodeFunctionData25({ abi: ERC20_ABI5, functionName: "balanceOf", args: [user] })
|
|
6272
7036
|
]);
|
|
6273
7037
|
callLabels.push(`balance:${symbol}`);
|
|
6274
7038
|
}
|
|
@@ -6276,7 +7040,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6276
7040
|
for (const p of lendingProtocols) {
|
|
6277
7041
|
calls.push([
|
|
6278
7042
|
p.contracts["pool"],
|
|
6279
|
-
|
|
7043
|
+
encodeFunctionData25({ abi: POOL_ABI4, functionName: "getUserAccountData", args: [user] })
|
|
6280
7044
|
]);
|
|
6281
7045
|
callLabels.push(`lending:${p.name}`);
|
|
6282
7046
|
}
|
|
@@ -6286,7 +7050,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6286
7050
|
if (oracleAddr) {
|
|
6287
7051
|
calls.push([
|
|
6288
7052
|
oracleAddr,
|
|
6289
|
-
|
|
7053
|
+
encodeFunctionData25({ abi: ORACLE_ABI5, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
6290
7054
|
]);
|
|
6291
7055
|
callLabels.push("price:native");
|
|
6292
7056
|
}
|
|
@@ -6648,14 +7412,14 @@ function registerAlert(parent, getOpts) {
|
|
|
6648
7412
|
}
|
|
6649
7413
|
|
|
6650
7414
|
// src/commands/scan.ts
|
|
6651
|
-
import { encodeFunctionData as
|
|
6652
|
-
var AAVE_ORACLE_ABI =
|
|
7415
|
+
import { encodeFunctionData as encodeFunctionData26, parseAbi as parseAbi29 } from "viem";
|
|
7416
|
+
var AAVE_ORACLE_ABI = parseAbi29([
|
|
6653
7417
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
6654
7418
|
]);
|
|
6655
|
-
var UNIV2_ROUTER_ABI =
|
|
7419
|
+
var UNIV2_ROUTER_ABI = parseAbi29([
|
|
6656
7420
|
"function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory)"
|
|
6657
7421
|
]);
|
|
6658
|
-
var VTOKEN_ABI =
|
|
7422
|
+
var VTOKEN_ABI = parseAbi29([
|
|
6659
7423
|
"function exchangeRateStored() external view returns (uint256)"
|
|
6660
7424
|
]);
|
|
6661
7425
|
var STABLECOINS = /* @__PURE__ */ new Set(["USDC", "USDT", "DAI", "USDT0"]);
|
|
@@ -6765,7 +7529,7 @@ function registerScan(parent, getOpts) {
|
|
|
6765
7529
|
callTypes.push({ kind: "oracle", oracle: oracle.name, token: token.symbol, oracleDecimals: oracle.decimals });
|
|
6766
7530
|
calls.push([
|
|
6767
7531
|
oracle.addr,
|
|
6768
|
-
|
|
7532
|
+
encodeFunctionData26({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })
|
|
6769
7533
|
]);
|
|
6770
7534
|
}
|
|
6771
7535
|
}
|
|
@@ -6776,7 +7540,7 @@ function registerScan(parent, getOpts) {
|
|
|
6776
7540
|
callTypes.push({ kind: "dex", token: token.symbol, outDecimals: quoteStable.decimals });
|
|
6777
7541
|
calls.push([
|
|
6778
7542
|
dexRouter,
|
|
6779
|
-
|
|
7543
|
+
encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [amountIn, path] })
|
|
6780
7544
|
]);
|
|
6781
7545
|
}
|
|
6782
7546
|
}
|
|
@@ -6785,7 +7549,7 @@ function registerScan(parent, getOpts) {
|
|
|
6785
7549
|
callTypes.push({ kind: "stable", from: "USDC", to: "USDT", outDecimals: usdt.decimals });
|
|
6786
7550
|
calls.push([
|
|
6787
7551
|
dexRouter,
|
|
6788
|
-
|
|
7552
|
+
encodeFunctionData26({
|
|
6789
7553
|
abi: UNIV2_ROUTER_ABI,
|
|
6790
7554
|
functionName: "getAmountsOut",
|
|
6791
7555
|
args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]]
|
|
@@ -6794,7 +7558,7 @@ function registerScan(parent, getOpts) {
|
|
|
6794
7558
|
callTypes.push({ kind: "stable", from: "USDT", to: "USDC", outDecimals: usdc.decimals });
|
|
6795
7559
|
calls.push([
|
|
6796
7560
|
dexRouter,
|
|
6797
|
-
|
|
7561
|
+
encodeFunctionData26({
|
|
6798
7562
|
abi: UNIV2_ROUTER_ABI,
|
|
6799
7563
|
functionName: "getAmountsOut",
|
|
6800
7564
|
args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]]
|
|
@@ -6805,7 +7569,7 @@ function registerScan(parent, getOpts) {
|
|
|
6805
7569
|
for (const fork of compoundForks) {
|
|
6806
7570
|
for (const { key, addr } of fork.vtokens) {
|
|
6807
7571
|
callTypes.push({ kind: "exchangeRate", protocol: fork.name, vtoken: key });
|
|
6808
|
-
calls.push([addr,
|
|
7572
|
+
calls.push([addr, encodeFunctionData26({ abi: VTOKEN_ABI, functionName: "exchangeRateStored", args: [] })]);
|
|
6809
7573
|
}
|
|
6810
7574
|
}
|
|
6811
7575
|
}
|
|
@@ -7023,22 +7787,22 @@ async function runAllChains(registry, patterns, oracleThreshold, stableThreshold
|
|
|
7023
7787
|
for (const oracle of oracles) {
|
|
7024
7788
|
for (const token of scanTokens) {
|
|
7025
7789
|
cts.push({ kind: "oracle", oracle: oracle.name, token: token.symbol, dec: oracle.decimals });
|
|
7026
|
-
calls.push([oracle.addr,
|
|
7790
|
+
calls.push([oracle.addr, encodeFunctionData26({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })]);
|
|
7027
7791
|
}
|
|
7028
7792
|
}
|
|
7029
7793
|
if (dexRouter) {
|
|
7030
7794
|
for (const token of scanTokens) {
|
|
7031
7795
|
const path = wrappedNative && token.address.toLowerCase() === wrappedNative.toLowerCase() ? [token.address, quoteStable.address] : wrappedNative ? [token.address, wrappedNative, quoteStable.address] : [token.address, quoteStable.address];
|
|
7032
7796
|
cts.push({ kind: "dex", token: token.symbol, dec: quoteStable.decimals });
|
|
7033
|
-
calls.push([dexRouter,
|
|
7797
|
+
calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(token.decimals), path] })]);
|
|
7034
7798
|
}
|
|
7035
7799
|
}
|
|
7036
7800
|
}
|
|
7037
7801
|
if (doStable && usdc && usdt && dexRouter) {
|
|
7038
7802
|
cts.push({ kind: "stable", from: "USDC", to: "USDT", dec: usdt.decimals });
|
|
7039
|
-
calls.push([dexRouter,
|
|
7803
|
+
calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]] })]);
|
|
7040
7804
|
cts.push({ kind: "stable", from: "USDT", to: "USDC", dec: usdc.decimals });
|
|
7041
|
-
calls.push([dexRouter,
|
|
7805
|
+
calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]] })]);
|
|
7042
7806
|
}
|
|
7043
7807
|
if (calls.length === 0) return null;
|
|
7044
7808
|
const ct0 = Date.now();
|
|
@@ -7166,14 +7930,14 @@ function registerArb(parent, getOpts, makeExecutor2) {
|
|
|
7166
7930
|
}
|
|
7167
7931
|
|
|
7168
7932
|
// src/commands/positions.ts
|
|
7169
|
-
import { encodeFunctionData as
|
|
7170
|
-
var ERC20_ABI6 =
|
|
7933
|
+
import { encodeFunctionData as encodeFunctionData27, parseAbi as parseAbi30 } from "viem";
|
|
7934
|
+
var ERC20_ABI6 = parseAbi30([
|
|
7171
7935
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
7172
7936
|
]);
|
|
7173
|
-
var POOL_ABI5 =
|
|
7937
|
+
var POOL_ABI5 = parseAbi30([
|
|
7174
7938
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
7175
7939
|
]);
|
|
7176
|
-
var ORACLE_ABI6 =
|
|
7940
|
+
var ORACLE_ABI6 = parseAbi30([
|
|
7177
7941
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
7178
7942
|
]);
|
|
7179
7943
|
function round22(x) {
|
|
@@ -7202,7 +7966,7 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7202
7966
|
callTypes.push({ kind: "token", symbol: token.symbol, decimals: token.decimals });
|
|
7203
7967
|
calls.push([
|
|
7204
7968
|
token.address,
|
|
7205
|
-
|
|
7969
|
+
encodeFunctionData27({ abi: ERC20_ABI6, functionName: "balanceOf", args: [user] })
|
|
7206
7970
|
]);
|
|
7207
7971
|
}
|
|
7208
7972
|
}
|
|
@@ -7210,14 +7974,14 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7210
7974
|
callTypes.push({ kind: "lending", protocol: name, iface });
|
|
7211
7975
|
calls.push([
|
|
7212
7976
|
pool,
|
|
7213
|
-
|
|
7977
|
+
encodeFunctionData27({ abi: POOL_ABI5, functionName: "getUserAccountData", args: [user] })
|
|
7214
7978
|
]);
|
|
7215
7979
|
}
|
|
7216
7980
|
if (oracleAddr) {
|
|
7217
7981
|
callTypes.push({ kind: "native_price" });
|
|
7218
7982
|
calls.push([
|
|
7219
7983
|
oracleAddr,
|
|
7220
|
-
|
|
7984
|
+
encodeFunctionData27({ abi: ORACLE_ABI6, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
7221
7985
|
]);
|
|
7222
7986
|
}
|
|
7223
7987
|
if (calls.length === 0) return null;
|
|
@@ -7510,14 +8274,14 @@ function registerPrice(parent, getOpts) {
|
|
|
7510
8274
|
}
|
|
7511
8275
|
|
|
7512
8276
|
// src/commands/wallet.ts
|
|
7513
|
-
import { createPublicClient as
|
|
8277
|
+
import { createPublicClient as createPublicClient19, http as http19, formatEther } from "viem";
|
|
7514
8278
|
function registerWallet(parent, getOpts) {
|
|
7515
8279
|
const wallet = parent.command("wallet").description("Wallet management");
|
|
7516
8280
|
wallet.command("balance").description("Show native token balance").requiredOption("--address <address>", "Wallet address to query").action(async (opts) => {
|
|
7517
8281
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7518
8282
|
const registry = Registry.loadEmbedded();
|
|
7519
8283
|
const chain = registry.getChain(chainName);
|
|
7520
|
-
const client =
|
|
8284
|
+
const client = createPublicClient19({ transport: http19(chain.effectiveRpcUrl()) });
|
|
7521
8285
|
const balance = await client.getBalance({ address: opts.address });
|
|
7522
8286
|
printOutput({
|
|
7523
8287
|
chain: chain.name,
|
|
@@ -7534,14 +8298,14 @@ function registerWallet(parent, getOpts) {
|
|
|
7534
8298
|
}
|
|
7535
8299
|
|
|
7536
8300
|
// src/commands/token.ts
|
|
7537
|
-
import { createPublicClient as
|
|
8301
|
+
import { createPublicClient as createPublicClient20, http as http20, maxUint256 } from "viem";
|
|
7538
8302
|
function registerToken(parent, getOpts, makeExecutor2) {
|
|
7539
8303
|
const token = parent.command("token").description("Token operations: approve, allowance, transfer, balance");
|
|
7540
8304
|
token.command("balance").description("Query token balance for an address").requiredOption("--token <token>", "Token symbol or address").requiredOption("--owner <address>", "Wallet address to query").action(async (opts) => {
|
|
7541
8305
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7542
8306
|
const registry = Registry.loadEmbedded();
|
|
7543
8307
|
const chain = registry.getChain(chainName);
|
|
7544
|
-
const client =
|
|
8308
|
+
const client = createPublicClient20({ transport: http20(chain.effectiveRpcUrl()) });
|
|
7545
8309
|
const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
|
|
7546
8310
|
const [balance, symbol, decimals] = await Promise.all([
|
|
7547
8311
|
client.readContract({ address: tokenAddr, abi: erc20Abi, functionName: "balanceOf", args: [opts.owner] }),
|
|
@@ -7570,7 +8334,7 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
7570
8334
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7571
8335
|
const registry = Registry.loadEmbedded();
|
|
7572
8336
|
const chain = registry.getChain(chainName);
|
|
7573
|
-
const client =
|
|
8337
|
+
const client = createPublicClient20({ transport: http20(chain.effectiveRpcUrl()) });
|
|
7574
8338
|
const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
|
|
7575
8339
|
const allowance = await client.readContract({
|
|
7576
8340
|
address: tokenAddr,
|
|
@@ -7592,8 +8356,8 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
7592
8356
|
}
|
|
7593
8357
|
|
|
7594
8358
|
// src/commands/whales.ts
|
|
7595
|
-
import { encodeFunctionData as
|
|
7596
|
-
var POOL_ABI6 =
|
|
8359
|
+
import { encodeFunctionData as encodeFunctionData28, parseAbi as parseAbi31 } from "viem";
|
|
8360
|
+
var POOL_ABI6 = parseAbi31([
|
|
7597
8361
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
7598
8362
|
]);
|
|
7599
8363
|
function round24(x) {
|
|
@@ -7704,7 +8468,7 @@ function registerWhales(parent, getOpts) {
|
|
|
7704
8468
|
for (const { pool } of lendingPools) {
|
|
7705
8469
|
calls.push([
|
|
7706
8470
|
pool,
|
|
7707
|
-
|
|
8471
|
+
encodeFunctionData28({ abi: POOL_ABI6, functionName: "getUserAccountData", args: [whale.address] })
|
|
7708
8472
|
]);
|
|
7709
8473
|
}
|
|
7710
8474
|
}
|
|
@@ -8132,11 +8896,11 @@ function registerBridge(parent, getOpts) {
|
|
|
8132
8896
|
const amountUsdc = Number(BigInt(opts.amount)) / 1e6;
|
|
8133
8897
|
const { fee, maxFeeSubunits } = await getCctpFeeEstimate(srcDomain, dstDomain, amountUsdc);
|
|
8134
8898
|
const recipientPadded = `0x${"0".repeat(24)}${recipient.replace("0x", "").toLowerCase()}`;
|
|
8135
|
-
const { encodeFunctionData:
|
|
8136
|
-
const tokenMessengerAbi =
|
|
8899
|
+
const { encodeFunctionData: encodeFunctionData30, parseAbi: parseAbi34 } = await import("viem");
|
|
8900
|
+
const tokenMessengerAbi = parseAbi34([
|
|
8137
8901
|
"function depositForBurn(uint256 amount, uint32 destinationDomain, bytes32 mintRecipient, address burnToken, bytes32 destinationCaller, uint256 maxFee, uint32 minFinalityThreshold) external returns (uint64 nonce)"
|
|
8138
8902
|
]);
|
|
8139
|
-
const data =
|
|
8903
|
+
const data = encodeFunctionData30({
|
|
8140
8904
|
abi: tokenMessengerAbi,
|
|
8141
8905
|
functionName: "depositForBurn",
|
|
8142
8906
|
args: [
|
|
@@ -8473,6 +9237,107 @@ function registerSetup(program2) {
|
|
|
8473
9237
|
});
|
|
8474
9238
|
}
|
|
8475
9239
|
|
|
9240
|
+
// src/commands/lb.ts
|
|
9241
|
+
function registerLB(parent, getOpts, makeExecutor2) {
|
|
9242
|
+
const lb = parent.command("lb").description("Merchant Moe Liquidity Book: add/remove liquidity, rewards, positions");
|
|
9243
|
+
lb.command("add").description("Add liquidity to a Liquidity Book pair").requiredOption("--protocol <protocol>", "Protocol slug (e.g. merchantmoe-mantle)").requiredOption("--pool <address>", "LB pair address").requiredOption("--token-x <address>", "Token X address").requiredOption("--token-y <address>", "Token Y address").requiredOption("--bin-step <step>", "Bin step of the pair").option("--amount-x <wei>", "Amount of token X in wei", "0").option("--amount-y <wei>", "Amount of token Y in wei", "0").option("--bins <N>", "Number of bins on each side of active bin", "5").option("--active-id <id>", "Active bin id (defaults to on-chain query)").option("--recipient <address>", "Recipient address").action(async (opts) => {
|
|
9244
|
+
const executor = makeExecutor2();
|
|
9245
|
+
const registry = Registry.loadEmbedded();
|
|
9246
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9247
|
+
const chainName = parent.opts().chain;
|
|
9248
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9249
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9250
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9251
|
+
const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
|
|
9252
|
+
const tx = await adapter.buildAddLiquidity({
|
|
9253
|
+
pool: opts.pool,
|
|
9254
|
+
tokenX: opts.tokenX,
|
|
9255
|
+
tokenY: opts.tokenY,
|
|
9256
|
+
binStep: parseInt(opts.binStep),
|
|
9257
|
+
amountX: BigInt(opts.amountX),
|
|
9258
|
+
amountY: BigInt(opts.amountY),
|
|
9259
|
+
numBins: parseInt(opts.bins),
|
|
9260
|
+
activeIdDesired: opts.activeId ? parseInt(opts.activeId) : void 0,
|
|
9261
|
+
recipient
|
|
9262
|
+
});
|
|
9263
|
+
const result = await executor.execute(tx);
|
|
9264
|
+
printOutput(result, getOpts());
|
|
9265
|
+
});
|
|
9266
|
+
lb.command("remove").description("Remove liquidity from Liquidity Book bins").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--token-x <address>", "Token X address").requiredOption("--token-y <address>", "Token Y address").requiredOption("--bin-step <step>", "Bin step of the pair").requiredOption("--bins <binIds>", "Comma-separated bin IDs to remove from").requiredOption("--amounts <amounts>", "Comma-separated LB token amounts to remove per bin (wei)").option("--recipient <address>", "Recipient address").action(async (opts) => {
|
|
9267
|
+
const executor = makeExecutor2();
|
|
9268
|
+
const registry = Registry.loadEmbedded();
|
|
9269
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9270
|
+
const adapter = createMerchantMoeLB(protocol);
|
|
9271
|
+
const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
|
|
9272
|
+
const binIds = opts.bins.split(",").map((s) => parseInt(s.trim()));
|
|
9273
|
+
const amounts = opts.amounts.split(",").map((s) => BigInt(s.trim()));
|
|
9274
|
+
const tx = await adapter.buildRemoveLiquidity({
|
|
9275
|
+
tokenX: opts.tokenX,
|
|
9276
|
+
tokenY: opts.tokenY,
|
|
9277
|
+
binStep: parseInt(opts.binStep),
|
|
9278
|
+
binIds,
|
|
9279
|
+
amounts,
|
|
9280
|
+
recipient
|
|
9281
|
+
});
|
|
9282
|
+
const result = await executor.execute(tx);
|
|
9283
|
+
printOutput(result, getOpts());
|
|
9284
|
+
});
|
|
9285
|
+
lb.command("rewards").description("Show pending MOE rewards for a pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "LB pair address").option("--bins <binIds>", "Comma-separated bin IDs to check (auto-detected from rewarder range if omitted)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
|
|
9286
|
+
const registry = Registry.loadEmbedded();
|
|
9287
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9288
|
+
const chainName = parent.opts().chain;
|
|
9289
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9290
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9291
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9292
|
+
const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
|
|
9293
|
+
if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
|
|
9294
|
+
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
9295
|
+
const rewards = await adapter.getPendingRewards(user, opts.pool, binIds);
|
|
9296
|
+
printOutput(rewards, getOpts());
|
|
9297
|
+
});
|
|
9298
|
+
lb.command("claim").description("Claim pending MOE rewards from a pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "LB pair address").option("--bins <binIds>", "Comma-separated bin IDs to claim from (auto-detected from rewarder range if omitted)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
|
|
9299
|
+
const executor = makeExecutor2();
|
|
9300
|
+
const registry = Registry.loadEmbedded();
|
|
9301
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9302
|
+
const chainName = parent.opts().chain;
|
|
9303
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9304
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9305
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9306
|
+
const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
|
|
9307
|
+
if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
|
|
9308
|
+
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
9309
|
+
const tx = await adapter.buildClaimRewards(user, opts.pool, binIds);
|
|
9310
|
+
const result = await executor.execute(tx);
|
|
9311
|
+
printOutput(result, getOpts());
|
|
9312
|
+
});
|
|
9313
|
+
lb.command("discover").description("Find all rewarded LB pools on chain").requiredOption("--protocol <protocol>", "Protocol slug").option("--active-only", "Only show non-stopped pools").action(async (opts) => {
|
|
9314
|
+
const registry = Registry.loadEmbedded();
|
|
9315
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9316
|
+
const chainName = parent.opts().chain;
|
|
9317
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9318
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9319
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9320
|
+
let pools = await adapter.discoverRewardedPools();
|
|
9321
|
+
if (opts.activeOnly) {
|
|
9322
|
+
pools = pools.filter((p) => !p.stopped);
|
|
9323
|
+
}
|
|
9324
|
+
printOutput(pools, getOpts());
|
|
9325
|
+
});
|
|
9326
|
+
lb.command("positions").description("Show user positions per bin in a LB pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "LB pair address").option("--bins <binIds>", "Comma-separated bin IDs to query (auto-detected from rewarder range or active \xB1 50 if omitted)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
|
|
9327
|
+
const registry = Registry.loadEmbedded();
|
|
9328
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9329
|
+
const chainName = parent.opts().chain;
|
|
9330
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9331
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9332
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9333
|
+
const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
|
|
9334
|
+
if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
|
|
9335
|
+
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
9336
|
+
const positions = await adapter.getUserPositions(user, opts.pool, binIds);
|
|
9337
|
+
printOutput(positions, getOpts());
|
|
9338
|
+
});
|
|
9339
|
+
}
|
|
9340
|
+
|
|
8476
9341
|
// src/cli.ts
|
|
8477
9342
|
var _require = createRequire(import.meta.url);
|
|
8478
9343
|
var _pkg = _require("../package.json");
|
|
@@ -8484,7 +9349,7 @@ var BANNER = `
|
|
|
8484
9349
|
\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551
|
|
8485
9350
|
\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D
|
|
8486
9351
|
|
|
8487
|
-
2 chains \xB7
|
|
9352
|
+
2 chains \xB7 30 protocols \xB7 by HypurrQuant
|
|
8488
9353
|
|
|
8489
9354
|
Scan exploits, swap tokens, bridge assets, track whales,
|
|
8490
9355
|
compare yields \u2014 all from your terminal.
|
|
@@ -8524,6 +9389,7 @@ registerSwap(program, getOutputMode, makeExecutor);
|
|
|
8524
9389
|
registerBridge(program, getOutputMode);
|
|
8525
9390
|
registerNft(program, getOutputMode);
|
|
8526
9391
|
registerFarm(program, getOutputMode, makeExecutor);
|
|
9392
|
+
registerLB(program, getOutputMode, makeExecutor);
|
|
8527
9393
|
registerSetup(program);
|
|
8528
9394
|
program.command("agent").description("Agent mode: read JSON commands from stdin (for AI agents)").action(async () => {
|
|
8529
9395
|
const executor = makeExecutor();
|
|
@@ -8534,13 +9400,13 @@ program.command("agent").description("Agent mode: read JSON commands from stdin
|
|
|
8534
9400
|
|
|
8535
9401
|
// src/landing.ts
|
|
8536
9402
|
import pc3 from "picocolors";
|
|
8537
|
-
import { encodeFunctionData as
|
|
9403
|
+
import { encodeFunctionData as encodeFunctionData29, parseAbi as parseAbi33, formatUnits } from "viem";
|
|
8538
9404
|
var HYPEREVM_DISPLAY = ["HYPE", "WHYPE", "USDC", "USDT0", "USDe", "kHYPE", "wstHYPE"];
|
|
8539
9405
|
var MANTLE_DISPLAY = ["MNT", "WMNT", "USDC", "USDT", "WETH", "mETH"];
|
|
8540
|
-
var balanceOfAbi =
|
|
9406
|
+
var balanceOfAbi = parseAbi33([
|
|
8541
9407
|
"function balanceOf(address account) view returns (uint256)"
|
|
8542
9408
|
]);
|
|
8543
|
-
var getEthBalanceAbi =
|
|
9409
|
+
var getEthBalanceAbi = parseAbi33([
|
|
8544
9410
|
"function getEthBalance(address addr) view returns (uint256)"
|
|
8545
9411
|
]);
|
|
8546
9412
|
async function fetchBalances(rpcUrl, wallet, tokens) {
|
|
@@ -8549,7 +9415,7 @@ async function fetchBalances(rpcUrl, wallet, tokens) {
|
|
|
8549
9415
|
if (isNative) {
|
|
8550
9416
|
return [
|
|
8551
9417
|
MULTICALL3_ADDRESS,
|
|
8552
|
-
|
|
9418
|
+
encodeFunctionData29({
|
|
8553
9419
|
abi: getEthBalanceAbi,
|
|
8554
9420
|
functionName: "getEthBalance",
|
|
8555
9421
|
args: [wallet]
|
|
@@ -8558,7 +9424,7 @@ async function fetchBalances(rpcUrl, wallet, tokens) {
|
|
|
8558
9424
|
}
|
|
8559
9425
|
return [
|
|
8560
9426
|
t.address,
|
|
8561
|
-
|
|
9427
|
+
encodeFunctionData29({
|
|
8562
9428
|
abi: balanceOfAbi,
|
|
8563
9429
|
functionName: "balanceOf",
|
|
8564
9430
|
args: [wallet]
|
|
@@ -8732,6 +9598,7 @@ async function main() {
|
|
|
8732
9598
|
"bridge",
|
|
8733
9599
|
"nft",
|
|
8734
9600
|
"farm",
|
|
9601
|
+
"lb",
|
|
8735
9602
|
"agent",
|
|
8736
9603
|
"setup",
|
|
8737
9604
|
"init"
|