@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/index.js
CHANGED
|
@@ -703,6 +703,16 @@ function parse(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
|
|
|
703
703
|
|
|
704
704
|
// ../defi-core/dist/index.js
|
|
705
705
|
import { existsSync } from "fs";
|
|
706
|
+
var TxStatus = /* @__PURE__ */ ((TxStatus2) => {
|
|
707
|
+
TxStatus2["DryRun"] = "dry_run";
|
|
708
|
+
TxStatus2["Simulated"] = "simulated";
|
|
709
|
+
TxStatus2["SimulationFailed"] = "simulation_failed";
|
|
710
|
+
TxStatus2["NeedsApproval"] = "needs_approval";
|
|
711
|
+
TxStatus2["Pending"] = "pending";
|
|
712
|
+
TxStatus2["Confirmed"] = "confirmed";
|
|
713
|
+
TxStatus2["Failed"] = "failed";
|
|
714
|
+
return TxStatus2;
|
|
715
|
+
})(TxStatus || {});
|
|
706
716
|
var InterestRateMode = /* @__PURE__ */ ((InterestRateMode2) => {
|
|
707
717
|
InterestRateMode2["Variable"] = "variable";
|
|
708
718
|
InterestRateMode2["Stable"] = "stable";
|
|
@@ -864,6 +874,10 @@ async function multicallRead(rpcUrl, calls) {
|
|
|
864
874
|
});
|
|
865
875
|
return decoded.map((r) => r.success ? r.returnData : null);
|
|
866
876
|
}
|
|
877
|
+
function decodeU256(data) {
|
|
878
|
+
if (!data || data.length < 66) return 0n;
|
|
879
|
+
return BigInt(data.slice(0, 66));
|
|
880
|
+
}
|
|
867
881
|
var ChainConfig = class {
|
|
868
882
|
name;
|
|
869
883
|
chain_id;
|
|
@@ -1127,6 +1141,46 @@ var Executor = class _Executor {
|
|
|
1127
1141
|
const client = createPublicClient2({ transport: http2(rpcUrl) });
|
|
1128
1142
|
const privateKey = process.env["DEFI_PRIVATE_KEY"];
|
|
1129
1143
|
const from = privateKey ? privateKeyToAccount(privateKey).address : "0x0000000000000000000000000000000000000001";
|
|
1144
|
+
if (tx.approvals && tx.approvals.length > 0) {
|
|
1145
|
+
const pendingApprovals = [];
|
|
1146
|
+
for (const approval of tx.approvals) {
|
|
1147
|
+
try {
|
|
1148
|
+
const allowance = await client.readContract({
|
|
1149
|
+
address: approval.token,
|
|
1150
|
+
abi: ERC20_ABI,
|
|
1151
|
+
functionName: "allowance",
|
|
1152
|
+
args: [from, approval.spender]
|
|
1153
|
+
});
|
|
1154
|
+
if (allowance < approval.amount) {
|
|
1155
|
+
pendingApprovals.push({
|
|
1156
|
+
token: approval.token,
|
|
1157
|
+
spender: approval.spender,
|
|
1158
|
+
needed: approval.amount.toString(),
|
|
1159
|
+
current: allowance.toString()
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
} catch {
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
if (pendingApprovals.length > 0) {
|
|
1166
|
+
return {
|
|
1167
|
+
tx_hash: void 0,
|
|
1168
|
+
status: TxStatus.NeedsApproval,
|
|
1169
|
+
gas_used: tx.gas_estimate,
|
|
1170
|
+
description: tx.description,
|
|
1171
|
+
details: {
|
|
1172
|
+
to: tx.to,
|
|
1173
|
+
from,
|
|
1174
|
+
data: tx.data,
|
|
1175
|
+
value: tx.value.toString(),
|
|
1176
|
+
mode: "simulated",
|
|
1177
|
+
result: "needs_approval",
|
|
1178
|
+
pending_approvals: pendingApprovals,
|
|
1179
|
+
hint: "Use --broadcast to auto-approve and execute"
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1130
1184
|
try {
|
|
1131
1185
|
await client.call({ to: tx.to, data: tx.data, value: tx.value, account: from });
|
|
1132
1186
|
const gasEstimate = await this.estimateGasWithBuffer(rpcUrl, tx, from);
|
|
@@ -1792,26 +1846,33 @@ import { encodeFunctionData as encodeFunctionData22, parseAbi as parseAbi22, cre
|
|
|
1792
1846
|
import { encodeFunctionData as encodeFunctionData32, parseAbi as parseAbi32, createPublicClient as createPublicClient32, http as http32, decodeAbiParameters as decodeAbiParameters3, concatHex, zeroAddress } from "viem";
|
|
1793
1847
|
import { encodeFunctionData as encodeFunctionData42, parseAbi as parseAbi42, zeroAddress as zeroAddress2 } from "viem";
|
|
1794
1848
|
import { encodeFunctionData as encodeFunctionData5, parseAbi as parseAbi5 } from "viem";
|
|
1795
|
-
import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6,
|
|
1849
|
+
import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6, decodeAbiParameters as decodeAbiParameters4 } from "viem";
|
|
1796
1850
|
import { encodeFunctionData as encodeFunctionData7, parseAbi as parseAbi7, zeroAddress as zeroAddress3 } from "viem";
|
|
1797
|
-
import { createPublicClient as
|
|
1798
|
-
import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9, createPublicClient as
|
|
1799
|
-
import {
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
import { createPublicClient as
|
|
1807
|
-
import { createPublicClient as
|
|
1808
|
-
import { createPublicClient as
|
|
1809
|
-
import { parseAbi as
|
|
1810
|
-
import { createPublicClient as
|
|
1811
|
-
import { createPublicClient as
|
|
1812
|
-
import { parseAbi as
|
|
1851
|
+
import { createPublicClient as createPublicClient42, encodeFunctionData as encodeFunctionData8, http as http42, parseAbi as parseAbi8, zeroAddress as zeroAddress4 } from "viem";
|
|
1852
|
+
import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9, createPublicClient as createPublicClient5, http as http5 } from "viem";
|
|
1853
|
+
import {
|
|
1854
|
+
encodeFunctionData as encodeFunctionData10,
|
|
1855
|
+
decodeFunctionResult as decodeFunctionResult22,
|
|
1856
|
+
parseAbi as parseAbi10,
|
|
1857
|
+
createPublicClient as createPublicClient6,
|
|
1858
|
+
http as http6
|
|
1859
|
+
} from "viem";
|
|
1860
|
+
import { createPublicClient as createPublicClient7, http as http7, parseAbi as parseAbi11, encodeFunctionData as encodeFunctionData11, decodeFunctionResult as decodeFunctionResult3, zeroAddress as zeroAddress5 } from "viem";
|
|
1861
|
+
import { createPublicClient as createPublicClient8, http as http8, parseAbi as parseAbi12, encodeFunctionData as encodeFunctionData12, zeroAddress as zeroAddress6 } from "viem";
|
|
1862
|
+
import { createPublicClient as createPublicClient9, http as http9, parseAbi as parseAbi13 } from "viem";
|
|
1863
|
+
import { createPublicClient as createPublicClient10, http as http10, parseAbi as parseAbi14, encodeFunctionData as encodeFunctionData13 } from "viem";
|
|
1864
|
+
import { createPublicClient as createPublicClient11, http as http11, parseAbi as parseAbi15, encodeFunctionData as encodeFunctionData14 } from "viem";
|
|
1865
|
+
import { createPublicClient as createPublicClient12, http as http12, parseAbi as parseAbi16, encodeFunctionData as encodeFunctionData15 } from "viem";
|
|
1866
|
+
import { parseAbi as parseAbi17, encodeFunctionData as encodeFunctionData16, decodeFunctionResult as decodeFunctionResult4, zeroAddress as zeroAddress7 } from "viem";
|
|
1867
|
+
import { createPublicClient as createPublicClient13, http as http13, parseAbi as parseAbi18, encodeFunctionData as encodeFunctionData17, zeroAddress as zeroAddress8 } from "viem";
|
|
1868
|
+
import { createPublicClient as createPublicClient14, http as http14, parseAbi as parseAbi19 } from "viem";
|
|
1869
|
+
import { createPublicClient as createPublicClient15, http as http15, parseAbi as parseAbi20, encodeFunctionData as encodeFunctionData18 } from "viem";
|
|
1870
|
+
import { parseAbi as parseAbi21, encodeFunctionData as encodeFunctionData19 } from "viem";
|
|
1871
|
+
import { createPublicClient as createPublicClient16, http as http16, parseAbi as parseAbi222, encodeFunctionData as encodeFunctionData20, zeroAddress as zeroAddress9 } from "viem";
|
|
1872
|
+
import { createPublicClient as createPublicClient17, http as http17, parseAbi as parseAbi23, encodeFunctionData as encodeFunctionData21, zeroAddress as zeroAddress10 } from "viem";
|
|
1813
1873
|
import { parseAbi as parseAbi24, encodeFunctionData as encodeFunctionData222 } from "viem";
|
|
1814
|
-
import {
|
|
1874
|
+
import { parseAbi as parseAbi25, encodeFunctionData as encodeFunctionData23 } from "viem";
|
|
1875
|
+
import { createPublicClient as createPublicClient18, http as http18, parseAbi as parseAbi26 } from "viem";
|
|
1815
1876
|
var DEFAULT_FEE = 3e3;
|
|
1816
1877
|
var swapRouterAbi = parseAbi4([
|
|
1817
1878
|
"struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; }",
|
|
@@ -2628,15 +2689,6 @@ var SolidlyAdapter = class {
|
|
|
2628
2689
|
approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
|
|
2629
2690
|
};
|
|
2630
2691
|
}
|
|
2631
|
-
async callGetAmountsOut(client, callData) {
|
|
2632
|
-
const result = await client.call({ to: this.router, data: callData });
|
|
2633
|
-
if (!result.data) return 0n;
|
|
2634
|
-
const [amounts] = decodeAbiParameters4(
|
|
2635
|
-
[{ name: "amounts", type: "uint256[]" }],
|
|
2636
|
-
result.data
|
|
2637
|
-
);
|
|
2638
|
-
return amounts.length >= 2 ? amounts[amounts.length - 1] : 0n;
|
|
2639
|
-
}
|
|
2640
2692
|
encodeV1(params, stable) {
|
|
2641
2693
|
return encodeFunctionData6({
|
|
2642
2694
|
abi: abi4,
|
|
@@ -2653,7 +2705,6 @@ var SolidlyAdapter = class {
|
|
|
2653
2705
|
}
|
|
2654
2706
|
async quote(params) {
|
|
2655
2707
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
2656
|
-
const client = createPublicClient42({ transport: http42(this.rpcUrl) });
|
|
2657
2708
|
const candidates = [
|
|
2658
2709
|
{ callData: this.encodeV1(params, false), stable: false },
|
|
2659
2710
|
{ callData: this.encodeV1(params, true), stable: true }
|
|
@@ -2664,16 +2715,26 @@ var SolidlyAdapter = class {
|
|
|
2664
2715
|
{ callData: this.encodeV2(params, true), stable: true }
|
|
2665
2716
|
);
|
|
2666
2717
|
}
|
|
2667
|
-
const
|
|
2668
|
-
|
|
2718
|
+
const rawResults = await multicallRead(
|
|
2719
|
+
this.rpcUrl,
|
|
2720
|
+
candidates.map((c) => [this.router, c.callData])
|
|
2669
2721
|
);
|
|
2670
2722
|
let bestOut = 0n;
|
|
2671
2723
|
let bestStable = false;
|
|
2672
|
-
for (let i = 0; i <
|
|
2673
|
-
const
|
|
2674
|
-
if (
|
|
2675
|
-
|
|
2676
|
-
|
|
2724
|
+
for (let i = 0; i < rawResults.length; i++) {
|
|
2725
|
+
const raw = rawResults[i];
|
|
2726
|
+
if (!raw) continue;
|
|
2727
|
+
try {
|
|
2728
|
+
const [amounts] = decodeAbiParameters4(
|
|
2729
|
+
[{ name: "amounts", type: "uint256[]" }],
|
|
2730
|
+
raw
|
|
2731
|
+
);
|
|
2732
|
+
const out = amounts.length >= 2 ? amounts[amounts.length - 1] : 0n;
|
|
2733
|
+
if (out > bestOut) {
|
|
2734
|
+
bestOut = out;
|
|
2735
|
+
bestStable = candidates[i].stable;
|
|
2736
|
+
}
|
|
2737
|
+
} catch {
|
|
2677
2738
|
}
|
|
2678
2739
|
}
|
|
2679
2740
|
if (bestOut === 0n) {
|
|
@@ -2885,7 +2946,7 @@ var SolidlyGaugeAdapter = class {
|
|
|
2885
2946
|
async buildClaimRewards(gauge, account) {
|
|
2886
2947
|
if (account && this.rpcUrl) {
|
|
2887
2948
|
try {
|
|
2888
|
-
const client =
|
|
2949
|
+
const client = createPublicClient42({ transport: http42(this.rpcUrl) });
|
|
2889
2950
|
const listLen = await client.readContract({
|
|
2890
2951
|
address: gauge,
|
|
2891
2952
|
abi: gaugeAbi,
|
|
@@ -3143,7 +3204,7 @@ var MasterChefAdapter = class {
|
|
|
3143
3204
|
if (!this.rpcUrl) {
|
|
3144
3205
|
throw DefiError.unsupported(`[${this.protocolName}] getPendingRewards requires RPC`);
|
|
3145
3206
|
}
|
|
3146
|
-
const client =
|
|
3207
|
+
const client = createPublicClient5({ transport: http5(this.rpcUrl) });
|
|
3147
3208
|
const rewards = await client.readContract({
|
|
3148
3209
|
address: this.masterchef,
|
|
3149
3210
|
abi: masterchefAbi,
|
|
@@ -3157,7 +3218,682 @@ var MasterChefAdapter = class {
|
|
|
3157
3218
|
}));
|
|
3158
3219
|
}
|
|
3159
3220
|
};
|
|
3160
|
-
var
|
|
3221
|
+
var lbRouterAbi = parseAbi10([
|
|
3222
|
+
"struct LiquidityParameters { address tokenX; address tokenY; uint256 binStep; uint256 amountX; uint256 amountY; uint256 amountXMin; uint256 amountYMin; uint256 activeIdDesired; uint256 idSlippage; int256[] deltaIds; uint256[] distributionX; uint256[] distributionY; address to; address refundTo; uint256 deadline; }",
|
|
3223
|
+
"function addLiquidity(LiquidityParameters calldata liquidityParameters) external returns (uint256 amountXAdded, uint256 amountYAdded, uint256 amountXLeft, uint256 amountYLeft, uint256[] memory depositIds, uint256[] memory liquidityMinted)",
|
|
3224
|
+
"function removeLiquidity(address tokenX, address tokenY, uint16 binStep, uint256 amountXMin, uint256 amountYMin, uint256[] memory ids, uint256[] memory amounts, address to, uint256 deadline) external returns (uint256 amountX, uint256 amountY)"
|
|
3225
|
+
]);
|
|
3226
|
+
var lbFactoryAbi = parseAbi10([
|
|
3227
|
+
"function getNumberOfLBPairs() external view returns (uint256)",
|
|
3228
|
+
"function getLBPairAtIndex(uint256 index) external view returns (address)"
|
|
3229
|
+
]);
|
|
3230
|
+
var lbPairAbi = parseAbi10([
|
|
3231
|
+
"function getLBHooksParameters() external view returns (bytes32)",
|
|
3232
|
+
"function getActiveId() external view returns (uint24)",
|
|
3233
|
+
"function getBinStep() external view returns (uint16)",
|
|
3234
|
+
"function getTokenX() external view returns (address)",
|
|
3235
|
+
"function getTokenY() external view returns (address)",
|
|
3236
|
+
"function balanceOf(address account, uint256 id) external view returns (uint256)",
|
|
3237
|
+
"function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory)"
|
|
3238
|
+
]);
|
|
3239
|
+
var lbRewarderAbi = parseAbi10([
|
|
3240
|
+
"function getRewardToken() external view returns (address)",
|
|
3241
|
+
"function getRewardedRange() external view returns (uint256 minBinId, uint256 maxBinId)",
|
|
3242
|
+
"function getPendingRewards(address user, uint256[] calldata ids) external view returns (uint256 pendingRewards)",
|
|
3243
|
+
"function claim(address user, uint256[] calldata ids) external",
|
|
3244
|
+
"function getPid() external view returns (uint256)",
|
|
3245
|
+
"function isStopped() external view returns (bool)",
|
|
3246
|
+
"function getLBPair() external view returns (address)",
|
|
3247
|
+
"function getMasterChef() external view returns (address)"
|
|
3248
|
+
]);
|
|
3249
|
+
var masterChefAbi = parseAbi10([
|
|
3250
|
+
"function getMoePerSecond() external view returns (uint256)",
|
|
3251
|
+
"function getTreasuryShare() external view returns (uint256)",
|
|
3252
|
+
"function getStaticShare() external view returns (uint256)",
|
|
3253
|
+
"function getVeMoe() external view returns (address)"
|
|
3254
|
+
]);
|
|
3255
|
+
var veMoeAbi = parseAbi10([
|
|
3256
|
+
"function getWeight(uint256 pid) external view returns (uint256)",
|
|
3257
|
+
"function getTotalWeight() external view returns (uint256)",
|
|
3258
|
+
"function getTopPoolIds() external view returns (uint256[] memory)"
|
|
3259
|
+
]);
|
|
3260
|
+
var lbPairBinAbi = parseAbi10([
|
|
3261
|
+
"function getBin(uint24 id) external view returns (uint128 reserveX, uint128 reserveY)",
|
|
3262
|
+
"function getActiveId() external view returns (uint24)"
|
|
3263
|
+
]);
|
|
3264
|
+
var lbQuoterAbi2 = parseAbi10([
|
|
3265
|
+
"function findBestPathFromAmountIn(address[] calldata route, uint128 amountIn) external view returns ((address[] route, address[] pairs, uint256[] binSteps, uint256[] versions, uint128[] amounts, uint128[] virtualAmountsWithoutSlippage, uint128[] fees))"
|
|
3266
|
+
]);
|
|
3267
|
+
var erc20Abi2 = parseAbi10([
|
|
3268
|
+
"function symbol() external view returns (string)"
|
|
3269
|
+
]);
|
|
3270
|
+
var _addressAbi = parseAbi10(["function f() external view returns (address)"]);
|
|
3271
|
+
function decodeAddressResult(data) {
|
|
3272
|
+
if (!data) return null;
|
|
3273
|
+
try {
|
|
3274
|
+
return decodeFunctionResult22({ abi: _addressAbi, functionName: "f", data });
|
|
3275
|
+
} catch {
|
|
3276
|
+
return null;
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
3279
|
+
var _uint256Abi = parseAbi10(["function f() external view returns (uint256)"]);
|
|
3280
|
+
function decodeUint256Result(data) {
|
|
3281
|
+
if (!data) return null;
|
|
3282
|
+
try {
|
|
3283
|
+
return decodeFunctionResult22({ abi: _uint256Abi, functionName: "f", data });
|
|
3284
|
+
} catch {
|
|
3285
|
+
return null;
|
|
3286
|
+
}
|
|
3287
|
+
}
|
|
3288
|
+
var _boolAbi = parseAbi10(["function f() external view returns (bool)"]);
|
|
3289
|
+
function decodeBoolResult(data) {
|
|
3290
|
+
if (!data) return null;
|
|
3291
|
+
try {
|
|
3292
|
+
return decodeFunctionResult22({ abi: _boolAbi, functionName: "f", data });
|
|
3293
|
+
} catch {
|
|
3294
|
+
return null;
|
|
3295
|
+
}
|
|
3296
|
+
}
|
|
3297
|
+
function decodeStringResult(data) {
|
|
3298
|
+
if (!data) return "?";
|
|
3299
|
+
try {
|
|
3300
|
+
return decodeFunctionResult22({ abi: erc20Abi2, functionName: "symbol", data });
|
|
3301
|
+
} catch {
|
|
3302
|
+
return "?";
|
|
3303
|
+
}
|
|
3304
|
+
}
|
|
3305
|
+
var _rangeAbi = parseAbi10(["function f() external view returns (uint256 minBinId, uint256 maxBinId)"]);
|
|
3306
|
+
function decodeRangeResult(data) {
|
|
3307
|
+
if (!data) return null;
|
|
3308
|
+
try {
|
|
3309
|
+
return decodeFunctionResult22({ abi: _rangeAbi, functionName: "f", data });
|
|
3310
|
+
} catch {
|
|
3311
|
+
return null;
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
var _binAbi = parseAbi10(["function f() external view returns (uint128 reserveX, uint128 reserveY)"]);
|
|
3315
|
+
function decodeBinResult(data) {
|
|
3316
|
+
if (!data) return null;
|
|
3317
|
+
try {
|
|
3318
|
+
return decodeFunctionResult22({ abi: _binAbi, functionName: "f", data });
|
|
3319
|
+
} catch {
|
|
3320
|
+
return null;
|
|
3321
|
+
}
|
|
3322
|
+
}
|
|
3323
|
+
var _uint256ArrayAbi = parseAbi10(["function f() external view returns (uint256[] memory)"]);
|
|
3324
|
+
function decodeUint256ArrayResult(data) {
|
|
3325
|
+
if (!data) return null;
|
|
3326
|
+
try {
|
|
3327
|
+
return decodeFunctionResult22({ abi: _uint256ArrayAbi, functionName: "f", data });
|
|
3328
|
+
} catch {
|
|
3329
|
+
return null;
|
|
3330
|
+
}
|
|
3331
|
+
}
|
|
3332
|
+
function extractRewarderAddress(hooksParams) {
|
|
3333
|
+
if (!hooksParams || hooksParams === "0x0000000000000000000000000000000000000000000000000000000000000000") {
|
|
3334
|
+
return null;
|
|
3335
|
+
}
|
|
3336
|
+
const hex = hooksParams.slice(2);
|
|
3337
|
+
if (hex.length < 64) return null;
|
|
3338
|
+
const addrHex = hex.slice(24, 64);
|
|
3339
|
+
if (addrHex === "0000000000000000000000000000000000000000") return null;
|
|
3340
|
+
return `0x${addrHex}`;
|
|
3341
|
+
}
|
|
3342
|
+
function buildUniformDistribution(deltaIds) {
|
|
3343
|
+
const PRECISION = 10n ** 18n;
|
|
3344
|
+
const n = deltaIds.length;
|
|
3345
|
+
const xBins = deltaIds.filter((d) => d >= 0).length;
|
|
3346
|
+
const yBins = deltaIds.filter((d) => d <= 0).length;
|
|
3347
|
+
const distributionX = [];
|
|
3348
|
+
const distributionY = [];
|
|
3349
|
+
for (const delta of deltaIds) {
|
|
3350
|
+
const xShare = delta >= 0 && xBins > 0 ? PRECISION / BigInt(xBins) : 0n;
|
|
3351
|
+
const yShare = delta <= 0 && yBins > 0 ? PRECISION / BigInt(yBins) : 0n;
|
|
3352
|
+
distributionX.push(xShare);
|
|
3353
|
+
distributionY.push(yShare);
|
|
3354
|
+
}
|
|
3355
|
+
const xSum = distributionX.reduce((a, b) => a + b, 0n);
|
|
3356
|
+
const ySum = distributionY.reduce((a, b) => a + b, 0n);
|
|
3357
|
+
if (xSum > 0n && xSum !== PRECISION) {
|
|
3358
|
+
const firstX = distributionX.findIndex((v) => v > 0n);
|
|
3359
|
+
if (firstX !== -1) distributionX[firstX] += PRECISION - xSum;
|
|
3360
|
+
}
|
|
3361
|
+
if (ySum > 0n && ySum !== PRECISION) {
|
|
3362
|
+
const firstY = distributionY.findIndex((v) => v > 0n);
|
|
3363
|
+
if (firstY !== -1) distributionY[firstY] += PRECISION - ySum;
|
|
3364
|
+
}
|
|
3365
|
+
return { distributionX, distributionY };
|
|
3366
|
+
}
|
|
3367
|
+
var MerchantMoeLBAdapter = class {
|
|
3368
|
+
protocolName;
|
|
3369
|
+
lbRouter;
|
|
3370
|
+
lbFactory;
|
|
3371
|
+
lbQuoter;
|
|
3372
|
+
rpcUrl;
|
|
3373
|
+
/** WMNT address (lb_mid_wmnt in config) used for MOE price routing */
|
|
3374
|
+
wmnt;
|
|
3375
|
+
/** USDT address (lb_mid_usdt in config) used for MNT/USD price routing */
|
|
3376
|
+
usdt;
|
|
3377
|
+
constructor(entry, rpcUrl) {
|
|
3378
|
+
this.protocolName = entry.name;
|
|
3379
|
+
const lbRouter = entry.contracts?.["lb_router"];
|
|
3380
|
+
if (!lbRouter) {
|
|
3381
|
+
throw new DefiError("CONTRACT_ERROR", "Missing 'lb_router' contract address");
|
|
3382
|
+
}
|
|
3383
|
+
const lbFactory = entry.contracts?.["lb_factory"];
|
|
3384
|
+
if (!lbFactory) {
|
|
3385
|
+
throw new DefiError("CONTRACT_ERROR", "Missing 'lb_factory' contract address");
|
|
3386
|
+
}
|
|
3387
|
+
this.lbRouter = lbRouter;
|
|
3388
|
+
this.lbFactory = lbFactory;
|
|
3389
|
+
this.lbQuoter = entry.contracts?.["lb_quoter"];
|
|
3390
|
+
this.wmnt = entry.contracts?.["lb_mid_wmnt"];
|
|
3391
|
+
this.usdt = entry.contracts?.["lb_mid_usdt"];
|
|
3392
|
+
this.rpcUrl = rpcUrl;
|
|
3393
|
+
}
|
|
3394
|
+
name() {
|
|
3395
|
+
return this.protocolName;
|
|
3396
|
+
}
|
|
3397
|
+
requireRpc() {
|
|
3398
|
+
if (!this.rpcUrl) {
|
|
3399
|
+
throw DefiError.rpcError(`[${this.protocolName}] RPC URL required`);
|
|
3400
|
+
}
|
|
3401
|
+
return this.rpcUrl;
|
|
3402
|
+
}
|
|
3403
|
+
/**
|
|
3404
|
+
* Build an addLiquidity transaction for a Liquidity Book pair.
|
|
3405
|
+
* Distributes tokenX/tokenY uniformly across active bin ± numBins.
|
|
3406
|
+
*/
|
|
3407
|
+
async buildAddLiquidity(params) {
|
|
3408
|
+
const numBins = params.numBins ?? 5;
|
|
3409
|
+
const deadline = params.deadline ?? BigInt("18446744073709551615");
|
|
3410
|
+
let activeIdDesired = params.activeIdDesired;
|
|
3411
|
+
if (activeIdDesired === void 0) {
|
|
3412
|
+
const rpcUrl = this.requireRpc();
|
|
3413
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3414
|
+
const activeId = await client.readContract({
|
|
3415
|
+
address: params.pool,
|
|
3416
|
+
abi: lbPairAbi,
|
|
3417
|
+
functionName: "getActiveId"
|
|
3418
|
+
});
|
|
3419
|
+
activeIdDesired = activeId;
|
|
3420
|
+
}
|
|
3421
|
+
const deltaIds = [];
|
|
3422
|
+
for (let d = -numBins; d <= numBins; d++) {
|
|
3423
|
+
deltaIds.push(d);
|
|
3424
|
+
}
|
|
3425
|
+
const { distributionX, distributionY } = buildUniformDistribution(deltaIds);
|
|
3426
|
+
const data = encodeFunctionData10({
|
|
3427
|
+
abi: lbRouterAbi,
|
|
3428
|
+
functionName: "addLiquidity",
|
|
3429
|
+
args: [
|
|
3430
|
+
{
|
|
3431
|
+
tokenX: params.tokenX,
|
|
3432
|
+
tokenY: params.tokenY,
|
|
3433
|
+
binStep: BigInt(params.binStep),
|
|
3434
|
+
amountX: params.amountX,
|
|
3435
|
+
amountY: params.amountY,
|
|
3436
|
+
amountXMin: 0n,
|
|
3437
|
+
amountYMin: 0n,
|
|
3438
|
+
activeIdDesired: BigInt(activeIdDesired),
|
|
3439
|
+
idSlippage: BigInt(numBins + 2),
|
|
3440
|
+
deltaIds: deltaIds.map(BigInt),
|
|
3441
|
+
distributionX,
|
|
3442
|
+
distributionY,
|
|
3443
|
+
to: params.recipient,
|
|
3444
|
+
refundTo: params.recipient,
|
|
3445
|
+
deadline
|
|
3446
|
+
}
|
|
3447
|
+
]
|
|
3448
|
+
});
|
|
3449
|
+
return {
|
|
3450
|
+
description: `[${this.protocolName}] LB addLiquidity ${params.amountX} tokenX + ${params.amountY} tokenY across ${deltaIds.length} bins`,
|
|
3451
|
+
to: this.lbRouter,
|
|
3452
|
+
data,
|
|
3453
|
+
value: 0n,
|
|
3454
|
+
gas_estimate: 8e5,
|
|
3455
|
+
approvals: [
|
|
3456
|
+
{ token: params.tokenX, spender: this.lbRouter, amount: params.amountX },
|
|
3457
|
+
{ token: params.tokenY, spender: this.lbRouter, amount: params.amountY }
|
|
3458
|
+
]
|
|
3459
|
+
};
|
|
3460
|
+
}
|
|
3461
|
+
/**
|
|
3462
|
+
* Build a removeLiquidity transaction for specific LB bins.
|
|
3463
|
+
*/
|
|
3464
|
+
async buildRemoveLiquidity(params) {
|
|
3465
|
+
const deadline = params.deadline ?? BigInt("18446744073709551615");
|
|
3466
|
+
const data = encodeFunctionData10({
|
|
3467
|
+
abi: lbRouterAbi,
|
|
3468
|
+
functionName: "removeLiquidity",
|
|
3469
|
+
args: [
|
|
3470
|
+
params.tokenX,
|
|
3471
|
+
params.tokenY,
|
|
3472
|
+
params.binStep,
|
|
3473
|
+
params.amountXMin ?? 0n,
|
|
3474
|
+
params.amountYMin ?? 0n,
|
|
3475
|
+
params.binIds.map(BigInt),
|
|
3476
|
+
params.amounts,
|
|
3477
|
+
params.recipient,
|
|
3478
|
+
deadline
|
|
3479
|
+
]
|
|
3480
|
+
});
|
|
3481
|
+
return {
|
|
3482
|
+
description: `[${this.protocolName}] LB removeLiquidity from ${params.binIds.length} bins`,
|
|
3483
|
+
to: this.lbRouter,
|
|
3484
|
+
data,
|
|
3485
|
+
value: 0n,
|
|
3486
|
+
gas_estimate: 6e5
|
|
3487
|
+
};
|
|
3488
|
+
}
|
|
3489
|
+
/**
|
|
3490
|
+
* Auto-detect bin IDs for a pool from the rewarder's rewarded range.
|
|
3491
|
+
* Falls back to active bin ± 50 scan if no rewarder exists.
|
|
3492
|
+
*/
|
|
3493
|
+
async autoDetectBins(pool) {
|
|
3494
|
+
const rpcUrl = this.requireRpc();
|
|
3495
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3496
|
+
const hooksParams = await client.readContract({
|
|
3497
|
+
address: pool,
|
|
3498
|
+
abi: lbPairAbi,
|
|
3499
|
+
functionName: "getLBHooksParameters"
|
|
3500
|
+
});
|
|
3501
|
+
const rewarder = extractRewarderAddress(hooksParams);
|
|
3502
|
+
if (rewarder) {
|
|
3503
|
+
const range = await client.readContract({
|
|
3504
|
+
address: rewarder,
|
|
3505
|
+
abi: lbRewarderAbi,
|
|
3506
|
+
functionName: "getRewardedRange"
|
|
3507
|
+
});
|
|
3508
|
+
const min = Number(range[0]);
|
|
3509
|
+
const max = Number(range[1]);
|
|
3510
|
+
const ids2 = [];
|
|
3511
|
+
for (let b = min; b <= max; b++) ids2.push(b);
|
|
3512
|
+
return ids2;
|
|
3513
|
+
}
|
|
3514
|
+
const activeId = await client.readContract({
|
|
3515
|
+
address: pool,
|
|
3516
|
+
abi: lbPairAbi,
|
|
3517
|
+
functionName: "getActiveId"
|
|
3518
|
+
});
|
|
3519
|
+
const ids = [];
|
|
3520
|
+
for (let b = activeId - 50; b <= activeId + 50; b++) ids.push(b);
|
|
3521
|
+
return ids;
|
|
3522
|
+
}
|
|
3523
|
+
/**
|
|
3524
|
+
* Get pending MOE rewards for a user across specified bin IDs.
|
|
3525
|
+
* If binIds is omitted, auto-detects from the rewarder's rewarded range.
|
|
3526
|
+
* Reads the rewarder address from the pool's hooks parameters.
|
|
3527
|
+
*/
|
|
3528
|
+
async getPendingRewards(user, pool, binIds) {
|
|
3529
|
+
const rpcUrl = this.requireRpc();
|
|
3530
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3531
|
+
const hooksParams = await client.readContract({
|
|
3532
|
+
address: pool,
|
|
3533
|
+
abi: lbPairAbi,
|
|
3534
|
+
functionName: "getLBHooksParameters"
|
|
3535
|
+
});
|
|
3536
|
+
const rewarder = extractRewarderAddress(hooksParams);
|
|
3537
|
+
if (!rewarder) {
|
|
3538
|
+
return [];
|
|
3539
|
+
}
|
|
3540
|
+
let resolvedBinIds = binIds;
|
|
3541
|
+
if (!resolvedBinIds || resolvedBinIds.length === 0) {
|
|
3542
|
+
const range = await client.readContract({
|
|
3543
|
+
address: rewarder,
|
|
3544
|
+
abi: lbRewarderAbi,
|
|
3545
|
+
functionName: "getRewardedRange"
|
|
3546
|
+
});
|
|
3547
|
+
const min = Number(range[0]);
|
|
3548
|
+
const max = Number(range[1]);
|
|
3549
|
+
resolvedBinIds = [];
|
|
3550
|
+
for (let b = min; b <= max; b++) resolvedBinIds.push(b);
|
|
3551
|
+
}
|
|
3552
|
+
const [pending, rewardToken] = await Promise.all([
|
|
3553
|
+
client.readContract({
|
|
3554
|
+
address: rewarder,
|
|
3555
|
+
abi: lbRewarderAbi,
|
|
3556
|
+
functionName: "getPendingRewards",
|
|
3557
|
+
args: [user, resolvedBinIds.map(BigInt)]
|
|
3558
|
+
}),
|
|
3559
|
+
client.readContract({
|
|
3560
|
+
address: rewarder,
|
|
3561
|
+
abi: lbRewarderAbi,
|
|
3562
|
+
functionName: "getRewardToken"
|
|
3563
|
+
})
|
|
3564
|
+
]);
|
|
3565
|
+
return [
|
|
3566
|
+
{
|
|
3567
|
+
token: rewardToken,
|
|
3568
|
+
symbol: "MOE",
|
|
3569
|
+
amount: pending
|
|
3570
|
+
}
|
|
3571
|
+
];
|
|
3572
|
+
}
|
|
3573
|
+
/**
|
|
3574
|
+
* Build a claim rewards transaction for specific LB bins.
|
|
3575
|
+
* If binIds is omitted, auto-detects from the rewarder's rewarded range.
|
|
3576
|
+
*/
|
|
3577
|
+
async buildClaimRewards(user, pool, binIds) {
|
|
3578
|
+
const rpcUrl = this.requireRpc();
|
|
3579
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3580
|
+
const hooksParams = await client.readContract({
|
|
3581
|
+
address: pool,
|
|
3582
|
+
abi: lbPairAbi,
|
|
3583
|
+
functionName: "getLBHooksParameters"
|
|
3584
|
+
});
|
|
3585
|
+
const rewarder = extractRewarderAddress(hooksParams);
|
|
3586
|
+
if (!rewarder) {
|
|
3587
|
+
throw new DefiError("CONTRACT_ERROR", `[${this.protocolName}] Pool ${pool} has no active rewarder`);
|
|
3588
|
+
}
|
|
3589
|
+
let resolvedBinIds = binIds;
|
|
3590
|
+
if (!resolvedBinIds || resolvedBinIds.length === 0) {
|
|
3591
|
+
const range = await client.readContract({
|
|
3592
|
+
address: rewarder,
|
|
3593
|
+
abi: lbRewarderAbi,
|
|
3594
|
+
functionName: "getRewardedRange"
|
|
3595
|
+
});
|
|
3596
|
+
const min = Number(range[0]);
|
|
3597
|
+
const max = Number(range[1]);
|
|
3598
|
+
resolvedBinIds = [];
|
|
3599
|
+
for (let b = min; b <= max; b++) resolvedBinIds.push(b);
|
|
3600
|
+
}
|
|
3601
|
+
const data = encodeFunctionData10({
|
|
3602
|
+
abi: lbRewarderAbi,
|
|
3603
|
+
functionName: "claim",
|
|
3604
|
+
args: [user, resolvedBinIds.map(BigInt)]
|
|
3605
|
+
});
|
|
3606
|
+
return {
|
|
3607
|
+
description: `[${this.protocolName}] LB claim rewards for ${resolvedBinIds.length} bins`,
|
|
3608
|
+
to: rewarder,
|
|
3609
|
+
data,
|
|
3610
|
+
value: 0n,
|
|
3611
|
+
gas_estimate: 3e5
|
|
3612
|
+
};
|
|
3613
|
+
}
|
|
3614
|
+
/**
|
|
3615
|
+
* Discover all active rewarded LB pools by iterating the factory.
|
|
3616
|
+
* Uses 7 multicall batches to minimise RPC round-trips and avoid 429s.
|
|
3617
|
+
*
|
|
3618
|
+
* Batch 1: getNumberOfLBPairs(), then getLBPairAtIndex(i) for all i
|
|
3619
|
+
* Batch 2: getLBHooksParameters() for all pairs → extract rewarder addresses
|
|
3620
|
+
* Batch 3: isStopped/getRewardedRange/getRewardToken/getPid/getMasterChef for each rewarder
|
|
3621
|
+
* Batch 4: getTokenX/getTokenY for each rewarded pair, then symbol() for unique tokens
|
|
3622
|
+
* Batch 5: Bootstrap MasterChef→VeMoe, then getMoePerSecond/getTreasuryShare/getStaticShare/getTotalWeight/getTopPoolIds
|
|
3623
|
+
* Batch 6: VeMoe.getWeight(pid) for each rewarded pool
|
|
3624
|
+
* Batch 7: Pool.getBin(binId) for all bins in rewarded range of each pool
|
|
3625
|
+
* Price: LB Quoter findBestPathFromAmountIn for MOE/WMNT and WMNT/USDT prices
|
|
3626
|
+
*/
|
|
3627
|
+
async discoverRewardedPools() {
|
|
3628
|
+
const rpcUrl = this.requireRpc();
|
|
3629
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3630
|
+
const pairCount = await client.readContract({
|
|
3631
|
+
address: this.lbFactory,
|
|
3632
|
+
abi: lbFactoryAbi,
|
|
3633
|
+
functionName: "getNumberOfLBPairs"
|
|
3634
|
+
});
|
|
3635
|
+
const count = Number(pairCount);
|
|
3636
|
+
if (count === 0) return [];
|
|
3637
|
+
const batch1Calls = Array.from({ length: count }, (_, i) => [
|
|
3638
|
+
this.lbFactory,
|
|
3639
|
+
encodeFunctionData10({ abi: lbFactoryAbi, functionName: "getLBPairAtIndex", args: [BigInt(i)] })
|
|
3640
|
+
]);
|
|
3641
|
+
const batch1Results = await multicallRead(rpcUrl, batch1Calls);
|
|
3642
|
+
const pairAddresses = batch1Results.map((r) => decodeAddressResult(r)).filter((a) => a !== null);
|
|
3643
|
+
if (pairAddresses.length === 0) return [];
|
|
3644
|
+
const batch2Calls = pairAddresses.map((pair) => [
|
|
3645
|
+
pair,
|
|
3646
|
+
encodeFunctionData10({ abi: lbPairAbi, functionName: "getLBHooksParameters" })
|
|
3647
|
+
]);
|
|
3648
|
+
const batch2Results = await multicallRead(rpcUrl, batch2Calls);
|
|
3649
|
+
const rewardedPairs = [];
|
|
3650
|
+
for (let i = 0; i < pairAddresses.length; i++) {
|
|
3651
|
+
const raw = batch2Results[i];
|
|
3652
|
+
if (!raw) continue;
|
|
3653
|
+
let hooksBytes;
|
|
3654
|
+
try {
|
|
3655
|
+
const _bytes32Abi = parseAbi10(["function f() external view returns (bytes32)"]);
|
|
3656
|
+
hooksBytes = decodeFunctionResult22({ abi: _bytes32Abi, functionName: "f", data: raw });
|
|
3657
|
+
} catch {
|
|
3658
|
+
continue;
|
|
3659
|
+
}
|
|
3660
|
+
const rewarder = extractRewarderAddress(hooksBytes);
|
|
3661
|
+
if (rewarder) {
|
|
3662
|
+
rewardedPairs.push({ pool: pairAddresses[i], rewarder });
|
|
3663
|
+
}
|
|
3664
|
+
}
|
|
3665
|
+
if (rewardedPairs.length === 0) return [];
|
|
3666
|
+
const batch3Calls = [];
|
|
3667
|
+
for (const { rewarder } of rewardedPairs) {
|
|
3668
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "isStopped" })]);
|
|
3669
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getRewardedRange" })]);
|
|
3670
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getRewardToken" })]);
|
|
3671
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getPid" })]);
|
|
3672
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getMasterChef" })]);
|
|
3673
|
+
}
|
|
3674
|
+
const batch3Results = await multicallRead(rpcUrl, batch3Calls);
|
|
3675
|
+
const batch4aCalls = [];
|
|
3676
|
+
for (const { pool } of rewardedPairs) {
|
|
3677
|
+
batch4aCalls.push([pool, encodeFunctionData10({ abi: lbPairAbi, functionName: "getTokenX" })]);
|
|
3678
|
+
batch4aCalls.push([pool, encodeFunctionData10({ abi: lbPairAbi, functionName: "getTokenY" })]);
|
|
3679
|
+
}
|
|
3680
|
+
const batch4aResults = await multicallRead(rpcUrl, batch4aCalls);
|
|
3681
|
+
const tokenXAddresses = [];
|
|
3682
|
+
const tokenYAddresses = [];
|
|
3683
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3684
|
+
tokenXAddresses.push(decodeAddressResult(batch4aResults[i * 2] ?? null));
|
|
3685
|
+
tokenYAddresses.push(decodeAddressResult(batch4aResults[i * 2 + 1] ?? null));
|
|
3686
|
+
}
|
|
3687
|
+
const uniqueTokens = Array.from(
|
|
3688
|
+
new Set([...tokenXAddresses, ...tokenYAddresses].filter((a) => a !== null))
|
|
3689
|
+
);
|
|
3690
|
+
const batch4bCalls = uniqueTokens.map((token) => [
|
|
3691
|
+
token,
|
|
3692
|
+
encodeFunctionData10({ abi: erc20Abi2, functionName: "symbol" })
|
|
3693
|
+
]);
|
|
3694
|
+
const batch4bResults = await multicallRead(rpcUrl, batch4bCalls);
|
|
3695
|
+
const symbolMap = /* @__PURE__ */ new Map();
|
|
3696
|
+
for (let i = 0; i < uniqueTokens.length; i++) {
|
|
3697
|
+
symbolMap.set(uniqueTokens[i], decodeStringResult(batch4bResults[i] ?? null));
|
|
3698
|
+
}
|
|
3699
|
+
const STRIDE3 = 5;
|
|
3700
|
+
const poolData = [];
|
|
3701
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3702
|
+
const base = i * STRIDE3;
|
|
3703
|
+
poolData.push({
|
|
3704
|
+
stopped: decodeBoolResult(batch3Results[base] ?? null) ?? false,
|
|
3705
|
+
range: decodeRangeResult(batch3Results[base + 1] ?? null),
|
|
3706
|
+
rewardToken: decodeAddressResult(batch3Results[base + 2] ?? null),
|
|
3707
|
+
pid: Number(decodeUint256Result(batch3Results[base + 3] ?? null) ?? 0n),
|
|
3708
|
+
masterChef: decodeAddressResult(batch3Results[base + 4] ?? null)
|
|
3709
|
+
});
|
|
3710
|
+
}
|
|
3711
|
+
const masterChefAddr = poolData.map((d) => d.masterChef).find((a) => a !== null) ?? null;
|
|
3712
|
+
let moePerDay = 0;
|
|
3713
|
+
let topPoolIds = /* @__PURE__ */ new Set();
|
|
3714
|
+
let totalWeightRaw = 0n;
|
|
3715
|
+
let veMoeAddr = null;
|
|
3716
|
+
if (masterChefAddr) {
|
|
3717
|
+
veMoeAddr = await client.readContract({
|
|
3718
|
+
address: masterChefAddr,
|
|
3719
|
+
abi: masterChefAbi,
|
|
3720
|
+
functionName: "getVeMoe"
|
|
3721
|
+
});
|
|
3722
|
+
const batch5Calls = [
|
|
3723
|
+
[masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getMoePerSecond" })],
|
|
3724
|
+
[masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getTreasuryShare" })],
|
|
3725
|
+
[masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getStaticShare" })],
|
|
3726
|
+
[veMoeAddr, encodeFunctionData10({ abi: veMoeAbi, functionName: "getTotalWeight" })],
|
|
3727
|
+
[veMoeAddr, encodeFunctionData10({ abi: veMoeAbi, functionName: "getTopPoolIds" })]
|
|
3728
|
+
];
|
|
3729
|
+
const batch5Results = await multicallRead(rpcUrl, batch5Calls);
|
|
3730
|
+
const moePerSecRaw = decodeUint256Result(batch5Results[0] ?? null) ?? 0n;
|
|
3731
|
+
const treasuryShareRaw = decodeUint256Result(batch5Results[1] ?? null) ?? 0n;
|
|
3732
|
+
const staticShareRaw = decodeUint256Result(batch5Results[2] ?? null) ?? 0n;
|
|
3733
|
+
totalWeightRaw = decodeUint256Result(batch5Results[3] ?? null) ?? 0n;
|
|
3734
|
+
const topPoolIdsRaw = decodeUint256ArrayResult(batch5Results[4] ?? null) ?? [];
|
|
3735
|
+
topPoolIds = new Set(topPoolIdsRaw.map(Number));
|
|
3736
|
+
const PRECISION = 10n ** 18n;
|
|
3737
|
+
const netPerSec = moePerSecRaw * (PRECISION - treasuryShareRaw) / PRECISION * (PRECISION - staticShareRaw) / PRECISION;
|
|
3738
|
+
moePerDay = Number(netPerSec * 86400n) / 1e18;
|
|
3739
|
+
}
|
|
3740
|
+
const weightByPid = /* @__PURE__ */ new Map();
|
|
3741
|
+
if (veMoeAddr && rewardedPairs.length > 0) {
|
|
3742
|
+
const batch6Calls = poolData.map((d) => [
|
|
3743
|
+
veMoeAddr,
|
|
3744
|
+
encodeFunctionData10({ abi: veMoeAbi, functionName: "getWeight", args: [BigInt(d.pid)] })
|
|
3745
|
+
]);
|
|
3746
|
+
const batch6Results = await multicallRead(rpcUrl, batch6Calls);
|
|
3747
|
+
for (let i = 0; i < poolData.length; i++) {
|
|
3748
|
+
weightByPid.set(poolData[i].pid, decodeUint256Result(batch6Results[i] ?? null) ?? 0n);
|
|
3749
|
+
}
|
|
3750
|
+
}
|
|
3751
|
+
let moePriceUsd = 0;
|
|
3752
|
+
let wmntPriceUsd = 0;
|
|
3753
|
+
const MOE_ADDR = "0x4515A45337F461A11Ff0FE8aBF3c606AE5dC00c9";
|
|
3754
|
+
if (this.lbQuoter && this.wmnt && this.usdt) {
|
|
3755
|
+
try {
|
|
3756
|
+
const [moeWmntQuote, wmntUsdtQuote] = await Promise.all([
|
|
3757
|
+
client.readContract({
|
|
3758
|
+
address: this.lbQuoter,
|
|
3759
|
+
abi: lbQuoterAbi2,
|
|
3760
|
+
functionName: "findBestPathFromAmountIn",
|
|
3761
|
+
args: [[MOE_ADDR, this.wmnt], 10n ** 18n]
|
|
3762
|
+
}),
|
|
3763
|
+
client.readContract({
|
|
3764
|
+
address: this.lbQuoter,
|
|
3765
|
+
abi: lbQuoterAbi2,
|
|
3766
|
+
functionName: "findBestPathFromAmountIn",
|
|
3767
|
+
args: [[this.wmnt, this.usdt], 10n ** 18n]
|
|
3768
|
+
})
|
|
3769
|
+
]);
|
|
3770
|
+
const moeInWmnt = Number(moeWmntQuote.amounts.at(-1) ?? 0n) / 1e18;
|
|
3771
|
+
wmntPriceUsd = Number(wmntUsdtQuote.amounts.at(-1) ?? 0n) / 1e6;
|
|
3772
|
+
moePriceUsd = moeInWmnt * wmntPriceUsd;
|
|
3773
|
+
} catch {
|
|
3774
|
+
}
|
|
3775
|
+
}
|
|
3776
|
+
const binRequests = [];
|
|
3777
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3778
|
+
const range = poolData[i].range;
|
|
3779
|
+
if (!range) continue;
|
|
3780
|
+
const minBin = Number(range[0]);
|
|
3781
|
+
const maxBin = Number(range[1]);
|
|
3782
|
+
for (let b = minBin; b <= maxBin; b++) {
|
|
3783
|
+
binRequests.push({ poolIdx: i, binId: b });
|
|
3784
|
+
}
|
|
3785
|
+
}
|
|
3786
|
+
const binReservesX = /* @__PURE__ */ new Map();
|
|
3787
|
+
const binReservesY = /* @__PURE__ */ new Map();
|
|
3788
|
+
if (binRequests.length > 0) {
|
|
3789
|
+
const batch7Calls = binRequests.map(({ poolIdx, binId }) => [
|
|
3790
|
+
rewardedPairs[poolIdx].pool,
|
|
3791
|
+
encodeFunctionData10({ abi: lbPairBinAbi, functionName: "getBin", args: [binId] })
|
|
3792
|
+
]);
|
|
3793
|
+
const batch7Results = await multicallRead(rpcUrl, batch7Calls);
|
|
3794
|
+
for (let j = 0; j < binRequests.length; j++) {
|
|
3795
|
+
const { poolIdx, binId } = binRequests[j];
|
|
3796
|
+
const decoded = decodeBinResult(batch7Results[j] ?? null);
|
|
3797
|
+
if (!decoded) continue;
|
|
3798
|
+
if (!binReservesX.has(poolIdx)) {
|
|
3799
|
+
binReservesX.set(poolIdx, /* @__PURE__ */ new Map());
|
|
3800
|
+
binReservesY.set(poolIdx, /* @__PURE__ */ new Map());
|
|
3801
|
+
}
|
|
3802
|
+
binReservesX.get(poolIdx).set(binId, decoded[0]);
|
|
3803
|
+
binReservesY.get(poolIdx).set(binId, decoded[1]);
|
|
3804
|
+
}
|
|
3805
|
+
}
|
|
3806
|
+
const stableSymbols = /* @__PURE__ */ new Set(["USDT", "USDC", "MUSD", "AUSD", "USDY", "FDUSD"]);
|
|
3807
|
+
const mntSymbols = /* @__PURE__ */ new Set(["WMNT", "MNT"]);
|
|
3808
|
+
const moeSymbols = /* @__PURE__ */ new Set(["MOE"]);
|
|
3809
|
+
const sixDecimalStables = /* @__PURE__ */ new Set(["USDT", "USDC", "FDUSD"]);
|
|
3810
|
+
const getTokenPriceUsd = (sym) => {
|
|
3811
|
+
if (stableSymbols.has(sym)) return 1;
|
|
3812
|
+
if (mntSymbols.has(sym)) return wmntPriceUsd;
|
|
3813
|
+
if (moeSymbols.has(sym)) return moePriceUsd;
|
|
3814
|
+
return 0;
|
|
3815
|
+
};
|
|
3816
|
+
const getTokenDecimals = (sym) => {
|
|
3817
|
+
return sixDecimalStables.has(sym) ? 6 : 18;
|
|
3818
|
+
};
|
|
3819
|
+
const results = [];
|
|
3820
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3821
|
+
const { pool, rewarder } = rewardedPairs[i];
|
|
3822
|
+
const data = poolData[i];
|
|
3823
|
+
const tokenX = tokenXAddresses[i] ?? "0x0000000000000000000000000000000000000000";
|
|
3824
|
+
const tokenY = tokenYAddresses[i] ?? "0x0000000000000000000000000000000000000000";
|
|
3825
|
+
const symX = symbolMap.get(tokenX) ?? "?";
|
|
3826
|
+
const symY = symbolMap.get(tokenY) ?? "?";
|
|
3827
|
+
const isTopPool = topPoolIds.has(data.pid);
|
|
3828
|
+
const weight = weightByPid.get(data.pid) ?? 0n;
|
|
3829
|
+
let poolMoePerDay = 0;
|
|
3830
|
+
if (isTopPool && totalWeightRaw > 0n && weight > 0n) {
|
|
3831
|
+
poolMoePerDay = moePerDay * (Number(weight) / Number(totalWeightRaw));
|
|
3832
|
+
}
|
|
3833
|
+
const rxMap = binReservesX.get(i);
|
|
3834
|
+
const ryMap = binReservesY.get(i);
|
|
3835
|
+
const range = data.range;
|
|
3836
|
+
let rangeTvlUsd = 0;
|
|
3837
|
+
let rewardedBins = 0;
|
|
3838
|
+
if (range) {
|
|
3839
|
+
const minBin = Number(range[0]);
|
|
3840
|
+
const maxBin = Number(range[1]);
|
|
3841
|
+
rewardedBins = maxBin - minBin + 1;
|
|
3842
|
+
if (rxMap && ryMap) {
|
|
3843
|
+
const priceX = getTokenPriceUsd(symX);
|
|
3844
|
+
const priceY = getTokenPriceUsd(symY);
|
|
3845
|
+
const decX = getTokenDecimals(symX);
|
|
3846
|
+
const decY = getTokenDecimals(symY);
|
|
3847
|
+
for (let b = minBin; b <= maxBin; b++) {
|
|
3848
|
+
const rx = rxMap.get(b) ?? 0n;
|
|
3849
|
+
const ry = ryMap.get(b) ?? 0n;
|
|
3850
|
+
rangeTvlUsd += Number(rx) / 10 ** decX * priceX;
|
|
3851
|
+
rangeTvlUsd += Number(ry) / 10 ** decY * priceY;
|
|
3852
|
+
}
|
|
3853
|
+
}
|
|
3854
|
+
}
|
|
3855
|
+
const aprPercent = rangeTvlUsd > 0 && moePriceUsd > 0 ? poolMoePerDay * moePriceUsd * 365 / rangeTvlUsd * 100 : 0;
|
|
3856
|
+
results.push({
|
|
3857
|
+
pool,
|
|
3858
|
+
rewarder,
|
|
3859
|
+
rewardToken: data.rewardToken ?? "0x0000000000000000000000000000000000000000",
|
|
3860
|
+
minBinId: range ? Number(range[0]) : 0,
|
|
3861
|
+
maxBinId: range ? Number(range[1]) : 0,
|
|
3862
|
+
pid: data.pid,
|
|
3863
|
+
stopped: data.stopped,
|
|
3864
|
+
tokenX,
|
|
3865
|
+
tokenY,
|
|
3866
|
+
symbolX: symX,
|
|
3867
|
+
symbolY: symY,
|
|
3868
|
+
isTopPool,
|
|
3869
|
+
moePerDay: poolMoePerDay,
|
|
3870
|
+
rangeTvlUsd,
|
|
3871
|
+
aprPercent,
|
|
3872
|
+
rewardedBins
|
|
3873
|
+
});
|
|
3874
|
+
}
|
|
3875
|
+
return results;
|
|
3876
|
+
}
|
|
3877
|
+
/**
|
|
3878
|
+
* Get a user's LB positions (bin balances) across a range of bin IDs.
|
|
3879
|
+
* If binIds is omitted, auto-detects from the rewarder's rewarded range (or active ± 50).
|
|
3880
|
+
*/
|
|
3881
|
+
async getUserPositions(user, pool, binIds) {
|
|
3882
|
+
const rpcUrl = this.requireRpc();
|
|
3883
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3884
|
+
const resolvedBinIds = binIds && binIds.length > 0 ? binIds : await this.autoDetectBins(pool);
|
|
3885
|
+
const accounts = resolvedBinIds.map(() => user);
|
|
3886
|
+
const ids = resolvedBinIds.map(BigInt);
|
|
3887
|
+
const balances = await client.readContract({
|
|
3888
|
+
address: pool,
|
|
3889
|
+
abi: lbPairAbi,
|
|
3890
|
+
functionName: "balanceOfBatch",
|
|
3891
|
+
args: [accounts, ids]
|
|
3892
|
+
});
|
|
3893
|
+
return resolvedBinIds.map((binId, i) => ({ binId, balance: balances[i] ?? 0n })).filter((p) => p.balance > 0n);
|
|
3894
|
+
}
|
|
3895
|
+
};
|
|
3896
|
+
var POOL_ABI = parseAbi11([
|
|
3161
3897
|
"function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
|
|
3162
3898
|
"function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
|
|
3163
3899
|
"function repay(address asset, uint256 amount, uint256 interestRateMode, address onBehalfOf) external returns (uint256)",
|
|
@@ -3165,27 +3901,27 @@ var POOL_ABI = parseAbi10([
|
|
|
3165
3901
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)",
|
|
3166
3902
|
"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)"
|
|
3167
3903
|
]);
|
|
3168
|
-
var ERC20_ABI2 =
|
|
3904
|
+
var ERC20_ABI2 = parseAbi11([
|
|
3169
3905
|
"function totalSupply() external view returns (uint256)"
|
|
3170
3906
|
]);
|
|
3171
|
-
var INCENTIVES_ABI =
|
|
3907
|
+
var INCENTIVES_ABI = parseAbi11([
|
|
3172
3908
|
"function getIncentivesController() external view returns (address)"
|
|
3173
3909
|
]);
|
|
3174
|
-
var REWARDS_CONTROLLER_ABI =
|
|
3910
|
+
var REWARDS_CONTROLLER_ABI = parseAbi11([
|
|
3175
3911
|
"function getRewardsByAsset(address asset) external view returns (address[])",
|
|
3176
3912
|
"function getRewardsData(address asset, address reward) external view returns (uint256 index, uint256 emissionsPerSecond, uint256 lastUpdateTimestamp, uint256 distributionEnd)"
|
|
3177
3913
|
]);
|
|
3178
|
-
var POOL_PROVIDER_ABI =
|
|
3914
|
+
var POOL_PROVIDER_ABI = parseAbi11([
|
|
3179
3915
|
"function ADDRESSES_PROVIDER() external view returns (address)"
|
|
3180
3916
|
]);
|
|
3181
|
-
var ADDRESSES_PROVIDER_ABI =
|
|
3917
|
+
var ADDRESSES_PROVIDER_ABI = parseAbi11([
|
|
3182
3918
|
"function getPriceOracle() external view returns (address)"
|
|
3183
3919
|
]);
|
|
3184
|
-
var ORACLE_ABI =
|
|
3920
|
+
var ORACLE_ABI = parseAbi11([
|
|
3185
3921
|
"function getAssetPrice(address asset) external view returns (uint256)",
|
|
3186
3922
|
"function BASE_CURRENCY_UNIT() external view returns (uint256)"
|
|
3187
3923
|
]);
|
|
3188
|
-
var ERC20_DECIMALS_ABI =
|
|
3924
|
+
var ERC20_DECIMALS_ABI = parseAbi11([
|
|
3189
3925
|
"function decimals() external view returns (uint8)"
|
|
3190
3926
|
]);
|
|
3191
3927
|
function u256ToF64(v) {
|
|
@@ -3193,6 +3929,46 @@ function u256ToF64(v) {
|
|
|
3193
3929
|
if (v > MAX_U128) return Infinity;
|
|
3194
3930
|
return Number(v);
|
|
3195
3931
|
}
|
|
3932
|
+
function decodeAddress(data) {
|
|
3933
|
+
if (!data || data.length < 66) return null;
|
|
3934
|
+
return `0x${data.slice(26, 66)}`;
|
|
3935
|
+
}
|
|
3936
|
+
function decodeAddressArray(data) {
|
|
3937
|
+
if (!data) return [];
|
|
3938
|
+
try {
|
|
3939
|
+
return decodeFunctionResult3({
|
|
3940
|
+
abi: REWARDS_CONTROLLER_ABI,
|
|
3941
|
+
functionName: "getRewardsByAsset",
|
|
3942
|
+
data
|
|
3943
|
+
});
|
|
3944
|
+
} catch {
|
|
3945
|
+
return [];
|
|
3946
|
+
}
|
|
3947
|
+
}
|
|
3948
|
+
function decodeReserveData(data) {
|
|
3949
|
+
if (!data) return null;
|
|
3950
|
+
try {
|
|
3951
|
+
return decodeFunctionResult3({
|
|
3952
|
+
abi: POOL_ABI,
|
|
3953
|
+
functionName: "getReserveData",
|
|
3954
|
+
data
|
|
3955
|
+
});
|
|
3956
|
+
} catch {
|
|
3957
|
+
return null;
|
|
3958
|
+
}
|
|
3959
|
+
}
|
|
3960
|
+
function decodeRewardsData(data) {
|
|
3961
|
+
if (!data) return null;
|
|
3962
|
+
try {
|
|
3963
|
+
return decodeFunctionResult3({
|
|
3964
|
+
abi: REWARDS_CONTROLLER_ABI,
|
|
3965
|
+
functionName: "getRewardsData",
|
|
3966
|
+
data
|
|
3967
|
+
});
|
|
3968
|
+
} catch {
|
|
3969
|
+
return null;
|
|
3970
|
+
}
|
|
3971
|
+
}
|
|
3196
3972
|
var AaveV3Adapter = class {
|
|
3197
3973
|
protocolName;
|
|
3198
3974
|
pool;
|
|
@@ -3208,7 +3984,7 @@ var AaveV3Adapter = class {
|
|
|
3208
3984
|
return this.protocolName;
|
|
3209
3985
|
}
|
|
3210
3986
|
async buildSupply(params) {
|
|
3211
|
-
const data =
|
|
3987
|
+
const data = encodeFunctionData11({
|
|
3212
3988
|
abi: POOL_ABI,
|
|
3213
3989
|
functionName: "supply",
|
|
3214
3990
|
args: [params.asset, params.amount, params.on_behalf_of, 0]
|
|
@@ -3224,7 +4000,7 @@ var AaveV3Adapter = class {
|
|
|
3224
4000
|
}
|
|
3225
4001
|
async buildBorrow(params) {
|
|
3226
4002
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
3227
|
-
const data =
|
|
4003
|
+
const data = encodeFunctionData11({
|
|
3228
4004
|
abi: POOL_ABI,
|
|
3229
4005
|
functionName: "borrow",
|
|
3230
4006
|
args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
|
|
@@ -3239,7 +4015,7 @@ var AaveV3Adapter = class {
|
|
|
3239
4015
|
}
|
|
3240
4016
|
async buildRepay(params) {
|
|
3241
4017
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
3242
|
-
const data =
|
|
4018
|
+
const data = encodeFunctionData11({
|
|
3243
4019
|
abi: POOL_ABI,
|
|
3244
4020
|
functionName: "repay",
|
|
3245
4021
|
args: [params.asset, params.amount, rateMode, params.on_behalf_of]
|
|
@@ -3254,7 +4030,7 @@ var AaveV3Adapter = class {
|
|
|
3254
4030
|
};
|
|
3255
4031
|
}
|
|
3256
4032
|
async buildWithdraw(params) {
|
|
3257
|
-
const data =
|
|
4033
|
+
const data = encodeFunctionData11({
|
|
3258
4034
|
abi: POOL_ABI,
|
|
3259
4035
|
functionName: "withdraw",
|
|
3260
4036
|
args: [params.asset, params.amount, params.to]
|
|
@@ -3269,15 +4045,21 @@ var AaveV3Adapter = class {
|
|
|
3269
4045
|
}
|
|
3270
4046
|
async getRates(asset) {
|
|
3271
4047
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
3272
|
-
const
|
|
3273
|
-
const result = await client.readContract({
|
|
3274
|
-
address: this.pool,
|
|
4048
|
+
const reserveCallData = encodeFunctionData11({
|
|
3275
4049
|
abi: POOL_ABI,
|
|
3276
4050
|
functionName: "getReserveData",
|
|
3277
4051
|
args: [asset]
|
|
3278
|
-
})
|
|
4052
|
+
});
|
|
4053
|
+
const [reserveRaw] = await multicallRead(this.rpcUrl, [
|
|
4054
|
+
[this.pool, reserveCallData]
|
|
4055
|
+
]).catch((e) => {
|
|
3279
4056
|
throw DefiError.rpcError(`[${this.protocolName}] getReserveData failed: ${e}`);
|
|
3280
4057
|
});
|
|
4058
|
+
const reserveDecoded = decodeReserveData(reserveRaw ?? null);
|
|
4059
|
+
if (!reserveDecoded) {
|
|
4060
|
+
throw DefiError.rpcError(`[${this.protocolName}] getReserveData returned no data`);
|
|
4061
|
+
}
|
|
4062
|
+
const result = reserveDecoded;
|
|
3281
4063
|
const RAY = 1e27;
|
|
3282
4064
|
const SECONDS_PER_YEAR4 = 31536e3;
|
|
3283
4065
|
const toApy = (rayRate) => {
|
|
@@ -3289,74 +4071,56 @@ var AaveV3Adapter = class {
|
|
|
3289
4071
|
const stableRate = toApy(result[5]);
|
|
3290
4072
|
const aTokenAddress = result[8];
|
|
3291
4073
|
const variableDebtTokenAddress = result[10];
|
|
3292
|
-
const [
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
abi: ERC20_ABI2,
|
|
3296
|
-
functionName: "totalSupply"
|
|
3297
|
-
}).catch(() => 0n),
|
|
3298
|
-
client.readContract({
|
|
3299
|
-
address: variableDebtTokenAddress,
|
|
3300
|
-
abi: ERC20_ABI2,
|
|
3301
|
-
functionName: "totalSupply"
|
|
3302
|
-
}).catch(() => 0n)
|
|
4074
|
+
const [supplyRaw, borrowRaw] = await multicallRead(this.rpcUrl, [
|
|
4075
|
+
[aTokenAddress, encodeFunctionData11({ abi: ERC20_ABI2, functionName: "totalSupply" })],
|
|
4076
|
+
[variableDebtTokenAddress, encodeFunctionData11({ abi: ERC20_ABI2, functionName: "totalSupply" })]
|
|
3303
4077
|
]);
|
|
4078
|
+
const totalSupply = decodeU256(supplyRaw ?? null);
|
|
4079
|
+
const totalBorrow = decodeU256(borrowRaw ?? null);
|
|
3304
4080
|
const utilization = totalSupply > 0n ? Number(totalBorrow * 10000n / totalSupply) / 100 : 0;
|
|
3305
4081
|
const supplyRewardTokens = [];
|
|
3306
4082
|
const borrowRewardTokens = [];
|
|
3307
4083
|
const supplyEmissions = [];
|
|
3308
4084
|
const borrowEmissions = [];
|
|
3309
4085
|
try {
|
|
3310
|
-
const
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
});
|
|
4086
|
+
const [controllerRaw] = await multicallRead(this.rpcUrl, [
|
|
4087
|
+
[aTokenAddress, encodeFunctionData11({ abi: INCENTIVES_ABI, functionName: "getIncentivesController" })]
|
|
4088
|
+
]);
|
|
4089
|
+
const controllerAddr = decodeAddress(controllerRaw ?? null);
|
|
3315
4090
|
if (controllerAddr && controllerAddr !== zeroAddress5) {
|
|
3316
|
-
const [
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
abi: REWARDS_CONTROLLER_ABI,
|
|
3320
|
-
functionName: "getRewardsByAsset",
|
|
3321
|
-
args: [aTokenAddress]
|
|
3322
|
-
}).catch(() => []),
|
|
3323
|
-
client.readContract({
|
|
3324
|
-
address: controllerAddr,
|
|
3325
|
-
abi: REWARDS_CONTROLLER_ABI,
|
|
3326
|
-
functionName: "getRewardsByAsset",
|
|
3327
|
-
args: [variableDebtTokenAddress]
|
|
3328
|
-
}).catch(() => [])
|
|
4091
|
+
const [supplyRewardsRaw, borrowRewardsRaw] = await multicallRead(this.rpcUrl, [
|
|
4092
|
+
[controllerAddr, encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [aTokenAddress] })],
|
|
4093
|
+
[controllerAddr, encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [variableDebtTokenAddress] })]
|
|
3329
4094
|
]);
|
|
3330
|
-
const
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
args: [aTokenAddress, reward]
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
4095
|
+
const supplyRewards = decodeAddressArray(supplyRewardsRaw ?? null);
|
|
4096
|
+
const borrowRewards = decodeAddressArray(borrowRewardsRaw ?? null);
|
|
4097
|
+
const rewardsDataCalls = [
|
|
4098
|
+
...supplyRewards.map((reward) => [
|
|
4099
|
+
controllerAddr,
|
|
4100
|
+
encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [aTokenAddress, reward] })
|
|
4101
|
+
]),
|
|
4102
|
+
...borrowRewards.map((reward) => [
|
|
4103
|
+
controllerAddr,
|
|
4104
|
+
encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [variableDebtTokenAddress, reward] })
|
|
4105
|
+
])
|
|
4106
|
+
];
|
|
4107
|
+
if (rewardsDataCalls.length > 0) {
|
|
4108
|
+
const rewardsDataResults = await multicallRead(this.rpcUrl, rewardsDataCalls);
|
|
4109
|
+
const supplyDataResults = rewardsDataResults.slice(0, supplyRewards.length);
|
|
4110
|
+
const borrowDataResults = rewardsDataResults.slice(supplyRewards.length);
|
|
4111
|
+
for (let i = 0; i < supplyRewards.length; i++) {
|
|
4112
|
+
const data = decodeRewardsData(supplyDataResults[i] ?? null);
|
|
4113
|
+
if (data && data[1] > 0n) {
|
|
4114
|
+
supplyRewardTokens.push(supplyRewards[i]);
|
|
4115
|
+
supplyEmissions.push(data[1].toString());
|
|
4116
|
+
}
|
|
3344
4117
|
}
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
args: [variableDebtTokenAddress, reward]
|
|
3352
|
-
}).catch(() => null)
|
|
3353
|
-
);
|
|
3354
|
-
const borrowData = await Promise.all(borrowDataPromises);
|
|
3355
|
-
for (let i = 0; i < borrowRewards.length; i++) {
|
|
3356
|
-
const data = borrowData[i];
|
|
3357
|
-
if (data && data[1] > 0n) {
|
|
3358
|
-
borrowRewardTokens.push(borrowRewards[i]);
|
|
3359
|
-
borrowEmissions.push(data[1].toString());
|
|
4118
|
+
for (let i = 0; i < borrowRewards.length; i++) {
|
|
4119
|
+
const data = decodeRewardsData(borrowDataResults[i] ?? null);
|
|
4120
|
+
if (data && data[1] > 0n) {
|
|
4121
|
+
borrowRewardTokens.push(borrowRewards[i]);
|
|
4122
|
+
borrowEmissions.push(data[1].toString());
|
|
4123
|
+
}
|
|
3360
4124
|
}
|
|
3361
4125
|
}
|
|
3362
4126
|
}
|
|
@@ -3368,55 +4132,49 @@ var AaveV3Adapter = class {
|
|
|
3368
4132
|
const hasBorrowRewards = borrowRewardTokens.length > 0;
|
|
3369
4133
|
if ((hasSupplyRewards || hasBorrowRewards) && totalSupply > 0n) {
|
|
3370
4134
|
try {
|
|
3371
|
-
const
|
|
3372
|
-
|
|
3373
|
-
abi: POOL_PROVIDER_ABI,
|
|
3374
|
-
functionName: "ADDRESSES_PROVIDER"
|
|
3375
|
-
});
|
|
3376
|
-
const oracleAddr = await client.readContract({
|
|
3377
|
-
address: providerAddr,
|
|
3378
|
-
abi: ADDRESSES_PROVIDER_ABI,
|
|
3379
|
-
functionName: "getPriceOracle"
|
|
3380
|
-
});
|
|
3381
|
-
const [assetPrice, baseCurrencyUnit, assetDecimals] = await Promise.all([
|
|
3382
|
-
client.readContract({
|
|
3383
|
-
address: oracleAddr,
|
|
3384
|
-
abi: ORACLE_ABI,
|
|
3385
|
-
functionName: "getAssetPrice",
|
|
3386
|
-
args: [asset]
|
|
3387
|
-
}),
|
|
3388
|
-
client.readContract({
|
|
3389
|
-
address: oracleAddr,
|
|
3390
|
-
abi: ORACLE_ABI,
|
|
3391
|
-
functionName: "BASE_CURRENCY_UNIT"
|
|
3392
|
-
}),
|
|
3393
|
-
client.readContract({
|
|
3394
|
-
address: asset,
|
|
3395
|
-
abi: ERC20_DECIMALS_ABI,
|
|
3396
|
-
functionName: "decimals"
|
|
3397
|
-
}).catch(() => 18)
|
|
4135
|
+
const [providerRaw] = await multicallRead(this.rpcUrl, [
|
|
4136
|
+
[this.pool, encodeFunctionData11({ abi: POOL_PROVIDER_ABI, functionName: "ADDRESSES_PROVIDER" })]
|
|
3398
4137
|
]);
|
|
3399
|
-
const
|
|
4138
|
+
const providerAddr = decodeAddress(providerRaw ?? null);
|
|
4139
|
+
if (!providerAddr) throw new Error("No provider address");
|
|
4140
|
+
const [oracleRaw] = await multicallRead(this.rpcUrl, [
|
|
4141
|
+
[providerAddr, encodeFunctionData11({ abi: ADDRESSES_PROVIDER_ABI, functionName: "getPriceOracle" })]
|
|
4142
|
+
]);
|
|
4143
|
+
const oracleAddr = decodeAddress(oracleRaw ?? null);
|
|
4144
|
+
if (!oracleAddr) throw new Error("No oracle address");
|
|
4145
|
+
const [assetPriceRaw, baseCurrencyUnitRaw, assetDecimalsRaw] = await multicallRead(this.rpcUrl, [
|
|
4146
|
+
[oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [asset] })],
|
|
4147
|
+
[oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "BASE_CURRENCY_UNIT" })],
|
|
4148
|
+
[asset, encodeFunctionData11({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
|
|
4149
|
+
]);
|
|
4150
|
+
const assetPrice = decodeU256(assetPriceRaw ?? null);
|
|
4151
|
+
const baseCurrencyUnit = decodeU256(baseCurrencyUnitRaw ?? null);
|
|
4152
|
+
const assetDecimals = assetDecimalsRaw ? Number(decodeU256(assetDecimalsRaw)) : 18;
|
|
4153
|
+
const priceUnit = Number(baseCurrencyUnit) || 1e8;
|
|
3400
4154
|
const assetPriceF = Number(assetPrice) / priceUnit;
|
|
3401
4155
|
const assetDecimalsDivisor = 10 ** assetDecimals;
|
|
4156
|
+
const allRewardTokens = Array.from(/* @__PURE__ */ new Set([...supplyRewardTokens, ...borrowRewardTokens]));
|
|
4157
|
+
const rewardPriceCalls = allRewardTokens.flatMap((token) => [
|
|
4158
|
+
[oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [token] })],
|
|
4159
|
+
[token, encodeFunctionData11({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
|
|
4160
|
+
]);
|
|
4161
|
+
const rewardPriceResults = rewardPriceCalls.length > 0 ? await multicallRead(this.rpcUrl, rewardPriceCalls) : [];
|
|
4162
|
+
const rewardPriceMap = /* @__PURE__ */ new Map();
|
|
4163
|
+
for (let i = 0; i < allRewardTokens.length; i++) {
|
|
4164
|
+
const priceRaw = rewardPriceResults[i * 2] ?? null;
|
|
4165
|
+
const decimalsRaw = rewardPriceResults[i * 2 + 1] ?? null;
|
|
4166
|
+
const price = decodeU256(priceRaw);
|
|
4167
|
+
const decimals = decimalsRaw ? Number(decodeU256(decimalsRaw)) : 18;
|
|
4168
|
+
rewardPriceMap.set(allRewardTokens[i].toLowerCase(), { price, decimals });
|
|
4169
|
+
}
|
|
3402
4170
|
if (hasSupplyRewards) {
|
|
3403
4171
|
let totalSupplyIncentiveUsdPerYear = 0;
|
|
3404
4172
|
const totalSupplyUsd = Number(totalSupply) / assetDecimalsDivisor * assetPriceF;
|
|
3405
4173
|
for (let i = 0; i < supplyRewardTokens.length; i++) {
|
|
3406
4174
|
const emissionPerSec = BigInt(supplyEmissions[i]);
|
|
3407
|
-
const
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
abi: ORACLE_ABI,
|
|
3411
|
-
functionName: "getAssetPrice",
|
|
3412
|
-
args: [supplyRewardTokens[i]]
|
|
3413
|
-
}).catch(() => 0n),
|
|
3414
|
-
client.readContract({
|
|
3415
|
-
address: supplyRewardTokens[i],
|
|
3416
|
-
abi: ERC20_DECIMALS_ABI,
|
|
3417
|
-
functionName: "decimals"
|
|
3418
|
-
}).catch(() => 18)
|
|
3419
|
-
]);
|
|
4175
|
+
const entry = rewardPriceMap.get(supplyRewardTokens[i].toLowerCase());
|
|
4176
|
+
const rewardPrice = entry?.price ?? 0n;
|
|
4177
|
+
const rewardDecimals = entry?.decimals ?? 18;
|
|
3420
4178
|
if (rewardPrice > 0n) {
|
|
3421
4179
|
const rewardPriceF = Number(rewardPrice) / priceUnit;
|
|
3422
4180
|
const emissionPerYear = Number(emissionPerSec) / 10 ** rewardDecimals * SECONDS_PER_YEAR4;
|
|
@@ -3432,19 +4190,9 @@ var AaveV3Adapter = class {
|
|
|
3432
4190
|
const totalBorrowUsd = Number(totalBorrow) / assetDecimalsDivisor * assetPriceF;
|
|
3433
4191
|
for (let i = 0; i < borrowRewardTokens.length; i++) {
|
|
3434
4192
|
const emissionPerSec = BigInt(borrowEmissions[i]);
|
|
3435
|
-
const
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
abi: ORACLE_ABI,
|
|
3439
|
-
functionName: "getAssetPrice",
|
|
3440
|
-
args: [borrowRewardTokens[i]]
|
|
3441
|
-
}).catch(() => 0n),
|
|
3442
|
-
client.readContract({
|
|
3443
|
-
address: borrowRewardTokens[i],
|
|
3444
|
-
abi: ERC20_DECIMALS_ABI,
|
|
3445
|
-
functionName: "decimals"
|
|
3446
|
-
}).catch(() => 18)
|
|
3447
|
-
]);
|
|
4193
|
+
const entry = rewardPriceMap.get(borrowRewardTokens[i].toLowerCase());
|
|
4194
|
+
const rewardPrice = entry?.price ?? 0n;
|
|
4195
|
+
const rewardDecimals = entry?.decimals ?? 18;
|
|
3448
4196
|
if (rewardPrice > 0n) {
|
|
3449
4197
|
const rewardPriceF = Number(rewardPrice) / priceUnit;
|
|
3450
4198
|
const emissionPerYear = Number(emissionPerSec) / 10 ** rewardDecimals * SECONDS_PER_YEAR4;
|
|
@@ -3508,7 +4256,7 @@ var AaveV3Adapter = class {
|
|
|
3508
4256
|
};
|
|
3509
4257
|
}
|
|
3510
4258
|
};
|
|
3511
|
-
var POOL_ABI2 =
|
|
4259
|
+
var POOL_ABI2 = parseAbi12([
|
|
3512
4260
|
"function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
|
|
3513
4261
|
"function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
|
|
3514
4262
|
"function repay(address asset, uint256 amount, uint256 rateMode, address onBehalfOf) external returns (uint256)",
|
|
@@ -3521,7 +4269,7 @@ var POOL_ABI2 = parseAbi11([
|
|
|
3521
4269
|
// [9]=variableDebtTokenAddress, [10]=interestRateStrategyAddress, [11]=id
|
|
3522
4270
|
"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)"
|
|
3523
4271
|
]);
|
|
3524
|
-
var ERC20_ABI22 =
|
|
4272
|
+
var ERC20_ABI22 = parseAbi12([
|
|
3525
4273
|
"function totalSupply() external view returns (uint256)"
|
|
3526
4274
|
]);
|
|
3527
4275
|
function u256ToF642(v) {
|
|
@@ -3544,7 +4292,7 @@ var AaveV2Adapter = class {
|
|
|
3544
4292
|
return this.protocolName;
|
|
3545
4293
|
}
|
|
3546
4294
|
async buildSupply(params) {
|
|
3547
|
-
const data =
|
|
4295
|
+
const data = encodeFunctionData12({
|
|
3548
4296
|
abi: POOL_ABI2,
|
|
3549
4297
|
functionName: "deposit",
|
|
3550
4298
|
args: [params.asset, params.amount, params.on_behalf_of, 0]
|
|
@@ -3560,7 +4308,7 @@ var AaveV2Adapter = class {
|
|
|
3560
4308
|
}
|
|
3561
4309
|
async buildBorrow(params) {
|
|
3562
4310
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
3563
|
-
const data =
|
|
4311
|
+
const data = encodeFunctionData12({
|
|
3564
4312
|
abi: POOL_ABI2,
|
|
3565
4313
|
functionName: "borrow",
|
|
3566
4314
|
args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
|
|
@@ -3575,7 +4323,7 @@ var AaveV2Adapter = class {
|
|
|
3575
4323
|
}
|
|
3576
4324
|
async buildRepay(params) {
|
|
3577
4325
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
3578
|
-
const data =
|
|
4326
|
+
const data = encodeFunctionData12({
|
|
3579
4327
|
abi: POOL_ABI2,
|
|
3580
4328
|
functionName: "repay",
|
|
3581
4329
|
args: [params.asset, params.amount, rateMode, params.on_behalf_of]
|
|
@@ -3590,7 +4338,7 @@ var AaveV2Adapter = class {
|
|
|
3590
4338
|
};
|
|
3591
4339
|
}
|
|
3592
4340
|
async buildWithdraw(params) {
|
|
3593
|
-
const data =
|
|
4341
|
+
const data = encodeFunctionData12({
|
|
3594
4342
|
abi: POOL_ABI2,
|
|
3595
4343
|
functionName: "withdraw",
|
|
3596
4344
|
args: [params.asset, params.amount, params.to]
|
|
@@ -3678,7 +4426,7 @@ var AaveV2Adapter = class {
|
|
|
3678
4426
|
};
|
|
3679
4427
|
}
|
|
3680
4428
|
};
|
|
3681
|
-
var ORACLE_ABI2 =
|
|
4429
|
+
var ORACLE_ABI2 = parseAbi13([
|
|
3682
4430
|
"function getAssetPrice(address asset) external view returns (uint256)",
|
|
3683
4431
|
"function getAssetsPrices(address[] calldata assets) external view returns (uint256[] memory)",
|
|
3684
4432
|
"function BASE_CURRENCY_UNIT() external view returns (uint256)"
|
|
@@ -3755,7 +4503,7 @@ var AaveOracleAdapter = class {
|
|
|
3755
4503
|
});
|
|
3756
4504
|
}
|
|
3757
4505
|
};
|
|
3758
|
-
var CTOKEN_ABI =
|
|
4506
|
+
var CTOKEN_ABI = parseAbi14([
|
|
3759
4507
|
"function supplyRatePerBlock() external view returns (uint256)",
|
|
3760
4508
|
"function borrowRatePerBlock() external view returns (uint256)",
|
|
3761
4509
|
"function totalSupply() external view returns (uint256)",
|
|
@@ -3782,7 +4530,7 @@ var CompoundV2Adapter = class {
|
|
|
3782
4530
|
return this.protocolName;
|
|
3783
4531
|
}
|
|
3784
4532
|
async buildSupply(params) {
|
|
3785
|
-
const data =
|
|
4533
|
+
const data = encodeFunctionData13({
|
|
3786
4534
|
abi: CTOKEN_ABI,
|
|
3787
4535
|
functionName: "mint",
|
|
3788
4536
|
args: [params.amount]
|
|
@@ -3796,7 +4544,7 @@ var CompoundV2Adapter = class {
|
|
|
3796
4544
|
};
|
|
3797
4545
|
}
|
|
3798
4546
|
async buildBorrow(params) {
|
|
3799
|
-
const data =
|
|
4547
|
+
const data = encodeFunctionData13({
|
|
3800
4548
|
abi: CTOKEN_ABI,
|
|
3801
4549
|
functionName: "borrow",
|
|
3802
4550
|
args: [params.amount]
|
|
@@ -3810,7 +4558,7 @@ var CompoundV2Adapter = class {
|
|
|
3810
4558
|
};
|
|
3811
4559
|
}
|
|
3812
4560
|
async buildRepay(params) {
|
|
3813
|
-
const data =
|
|
4561
|
+
const data = encodeFunctionData13({
|
|
3814
4562
|
abi: CTOKEN_ABI,
|
|
3815
4563
|
functionName: "repayBorrow",
|
|
3816
4564
|
args: [params.amount]
|
|
@@ -3824,7 +4572,7 @@ var CompoundV2Adapter = class {
|
|
|
3824
4572
|
};
|
|
3825
4573
|
}
|
|
3826
4574
|
async buildWithdraw(params) {
|
|
3827
|
-
const data =
|
|
4575
|
+
const data = encodeFunctionData13({
|
|
3828
4576
|
abi: CTOKEN_ABI,
|
|
3829
4577
|
functionName: "redeem",
|
|
3830
4578
|
args: [params.amount]
|
|
@@ -3873,7 +4621,7 @@ var CompoundV2Adapter = class {
|
|
|
3873
4621
|
);
|
|
3874
4622
|
}
|
|
3875
4623
|
};
|
|
3876
|
-
var COMET_ABI =
|
|
4624
|
+
var COMET_ABI = parseAbi15([
|
|
3877
4625
|
"function getUtilization() external view returns (uint256)",
|
|
3878
4626
|
"function getSupplyRate(uint256 utilization) external view returns (uint64)",
|
|
3879
4627
|
"function getBorrowRate(uint256 utilization) external view returns (uint64)",
|
|
@@ -3899,7 +4647,7 @@ var CompoundV3Adapter = class {
|
|
|
3899
4647
|
return this.protocolName;
|
|
3900
4648
|
}
|
|
3901
4649
|
async buildSupply(params) {
|
|
3902
|
-
const data =
|
|
4650
|
+
const data = encodeFunctionData14({
|
|
3903
4651
|
abi: COMET_ABI,
|
|
3904
4652
|
functionName: "supply",
|
|
3905
4653
|
args: [params.asset, params.amount]
|
|
@@ -3913,7 +4661,7 @@ var CompoundV3Adapter = class {
|
|
|
3913
4661
|
};
|
|
3914
4662
|
}
|
|
3915
4663
|
async buildBorrow(params) {
|
|
3916
|
-
const data =
|
|
4664
|
+
const data = encodeFunctionData14({
|
|
3917
4665
|
abi: COMET_ABI,
|
|
3918
4666
|
functionName: "withdraw",
|
|
3919
4667
|
args: [params.asset, params.amount]
|
|
@@ -3927,7 +4675,7 @@ var CompoundV3Adapter = class {
|
|
|
3927
4675
|
};
|
|
3928
4676
|
}
|
|
3929
4677
|
async buildRepay(params) {
|
|
3930
|
-
const data =
|
|
4678
|
+
const data = encodeFunctionData14({
|
|
3931
4679
|
abi: COMET_ABI,
|
|
3932
4680
|
functionName: "supply",
|
|
3933
4681
|
args: [params.asset, params.amount]
|
|
@@ -3941,7 +4689,7 @@ var CompoundV3Adapter = class {
|
|
|
3941
4689
|
};
|
|
3942
4690
|
}
|
|
3943
4691
|
async buildWithdraw(params) {
|
|
3944
|
-
const data =
|
|
4692
|
+
const data = encodeFunctionData14({
|
|
3945
4693
|
abi: COMET_ABI,
|
|
3946
4694
|
functionName: "withdraw",
|
|
3947
4695
|
args: [params.asset, params.amount]
|
|
@@ -3995,7 +4743,7 @@ var CompoundV3Adapter = class {
|
|
|
3995
4743
|
);
|
|
3996
4744
|
}
|
|
3997
4745
|
};
|
|
3998
|
-
var EULER_VAULT_ABI =
|
|
4746
|
+
var EULER_VAULT_ABI = parseAbi16([
|
|
3999
4747
|
"function deposit(uint256 amount, address receiver) external returns (uint256)",
|
|
4000
4748
|
"function withdraw(uint256 amount, address receiver, address owner) external returns (uint256)",
|
|
4001
4749
|
"function borrow(uint256 amount, address receiver) external returns (uint256)",
|
|
@@ -4021,7 +4769,7 @@ var EulerV2Adapter = class {
|
|
|
4021
4769
|
return this.protocolName;
|
|
4022
4770
|
}
|
|
4023
4771
|
async buildSupply(params) {
|
|
4024
|
-
const data =
|
|
4772
|
+
const data = encodeFunctionData15({
|
|
4025
4773
|
abi: EULER_VAULT_ABI,
|
|
4026
4774
|
functionName: "deposit",
|
|
4027
4775
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -4035,7 +4783,7 @@ var EulerV2Adapter = class {
|
|
|
4035
4783
|
};
|
|
4036
4784
|
}
|
|
4037
4785
|
async buildBorrow(params) {
|
|
4038
|
-
const data =
|
|
4786
|
+
const data = encodeFunctionData15({
|
|
4039
4787
|
abi: EULER_VAULT_ABI,
|
|
4040
4788
|
functionName: "borrow",
|
|
4041
4789
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -4049,7 +4797,7 @@ var EulerV2Adapter = class {
|
|
|
4049
4797
|
};
|
|
4050
4798
|
}
|
|
4051
4799
|
async buildRepay(params) {
|
|
4052
|
-
const data =
|
|
4800
|
+
const data = encodeFunctionData15({
|
|
4053
4801
|
abi: EULER_VAULT_ABI,
|
|
4054
4802
|
functionName: "repay",
|
|
4055
4803
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -4063,7 +4811,7 @@ var EulerV2Adapter = class {
|
|
|
4063
4811
|
};
|
|
4064
4812
|
}
|
|
4065
4813
|
async buildWithdraw(params) {
|
|
4066
|
-
const data =
|
|
4814
|
+
const data = encodeFunctionData15({
|
|
4067
4815
|
abi: EULER_VAULT_ABI,
|
|
4068
4816
|
functionName: "withdraw",
|
|
4069
4817
|
args: [params.amount, params.to, params.to]
|
|
@@ -4112,7 +4860,7 @@ var EulerV2Adapter = class {
|
|
|
4112
4860
|
);
|
|
4113
4861
|
}
|
|
4114
4862
|
};
|
|
4115
|
-
var MORPHO_ABI =
|
|
4863
|
+
var MORPHO_ABI = parseAbi17([
|
|
4116
4864
|
"function market(bytes32 id) external view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)",
|
|
4117
4865
|
"function idToMarketParams(bytes32 id) external view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)",
|
|
4118
4866
|
"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)",
|
|
@@ -4120,13 +4868,13 @@ var MORPHO_ABI = parseAbi16([
|
|
|
4120
4868
|
"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)",
|
|
4121
4869
|
"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)"
|
|
4122
4870
|
]);
|
|
4123
|
-
var META_MORPHO_ABI =
|
|
4871
|
+
var META_MORPHO_ABI = parseAbi17([
|
|
4124
4872
|
"function supplyQueueLength() external view returns (uint256)",
|
|
4125
4873
|
"function supplyQueue(uint256 index) external view returns (bytes32)",
|
|
4126
4874
|
"function totalAssets() external view returns (uint256)",
|
|
4127
4875
|
"function totalSupply() external view returns (uint256)"
|
|
4128
4876
|
]);
|
|
4129
|
-
var IRM_ABI =
|
|
4877
|
+
var IRM_ABI = parseAbi17([
|
|
4130
4878
|
"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)"
|
|
4131
4879
|
]);
|
|
4132
4880
|
var SECONDS_PER_YEAR3 = 365.25 * 24 * 3600;
|
|
@@ -4139,6 +4887,30 @@ function defaultMarketParams(loanToken = zeroAddress7) {
|
|
|
4139
4887
|
lltv: 0n
|
|
4140
4888
|
};
|
|
4141
4889
|
}
|
|
4890
|
+
function decodeMarket(data) {
|
|
4891
|
+
if (!data) return null;
|
|
4892
|
+
try {
|
|
4893
|
+
return decodeFunctionResult4({
|
|
4894
|
+
abi: MORPHO_ABI,
|
|
4895
|
+
functionName: "market",
|
|
4896
|
+
data
|
|
4897
|
+
});
|
|
4898
|
+
} catch {
|
|
4899
|
+
return null;
|
|
4900
|
+
}
|
|
4901
|
+
}
|
|
4902
|
+
function decodeMarketParams(data) {
|
|
4903
|
+
if (!data) return null;
|
|
4904
|
+
try {
|
|
4905
|
+
return decodeFunctionResult4({
|
|
4906
|
+
abi: MORPHO_ABI,
|
|
4907
|
+
functionName: "idToMarketParams",
|
|
4908
|
+
data
|
|
4909
|
+
});
|
|
4910
|
+
} catch {
|
|
4911
|
+
return null;
|
|
4912
|
+
}
|
|
4913
|
+
}
|
|
4142
4914
|
var MorphoBlueAdapter = class {
|
|
4143
4915
|
protocolName;
|
|
4144
4916
|
morpho;
|
|
@@ -4158,7 +4930,7 @@ var MorphoBlueAdapter = class {
|
|
|
4158
4930
|
}
|
|
4159
4931
|
async buildSupply(params) {
|
|
4160
4932
|
const market = defaultMarketParams(params.asset);
|
|
4161
|
-
const data =
|
|
4933
|
+
const data = encodeFunctionData16({
|
|
4162
4934
|
abi: MORPHO_ABI,
|
|
4163
4935
|
functionName: "supply",
|
|
4164
4936
|
args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
|
|
@@ -4173,7 +4945,7 @@ var MorphoBlueAdapter = class {
|
|
|
4173
4945
|
}
|
|
4174
4946
|
async buildBorrow(params) {
|
|
4175
4947
|
const market = defaultMarketParams(params.asset);
|
|
4176
|
-
const data =
|
|
4948
|
+
const data = encodeFunctionData16({
|
|
4177
4949
|
abi: MORPHO_ABI,
|
|
4178
4950
|
functionName: "borrow",
|
|
4179
4951
|
args: [market, params.amount, 0n, params.on_behalf_of, params.on_behalf_of]
|
|
@@ -4188,7 +4960,7 @@ var MorphoBlueAdapter = class {
|
|
|
4188
4960
|
}
|
|
4189
4961
|
async buildRepay(params) {
|
|
4190
4962
|
const market = defaultMarketParams(params.asset);
|
|
4191
|
-
const data =
|
|
4963
|
+
const data = encodeFunctionData16({
|
|
4192
4964
|
abi: MORPHO_ABI,
|
|
4193
4965
|
functionName: "repay",
|
|
4194
4966
|
args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
|
|
@@ -4203,7 +4975,7 @@ var MorphoBlueAdapter = class {
|
|
|
4203
4975
|
}
|
|
4204
4976
|
async buildWithdraw(params) {
|
|
4205
4977
|
const market = defaultMarketParams(params.asset);
|
|
4206
|
-
const data =
|
|
4978
|
+
const data = encodeFunctionData16({
|
|
4207
4979
|
abi: MORPHO_ABI,
|
|
4208
4980
|
functionName: "withdraw",
|
|
4209
4981
|
args: [market, params.amount, 0n, params.to, params.to]
|
|
@@ -4221,14 +4993,12 @@ var MorphoBlueAdapter = class {
|
|
|
4221
4993
|
if (!this.defaultVault) {
|
|
4222
4994
|
throw DefiError.contractError(`[${this.protocolName}] No MetaMorpho vault configured for rate query`);
|
|
4223
4995
|
}
|
|
4224
|
-
const
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
abi: META_MORPHO_ABI,
|
|
4228
|
-
functionName: "supplyQueueLength"
|
|
4229
|
-
}).catch((e) => {
|
|
4996
|
+
const [queueLenRaw] = await multicallRead(this.rpcUrl, [
|
|
4997
|
+
[this.defaultVault, encodeFunctionData16({ abi: META_MORPHO_ABI, functionName: "supplyQueueLength" })]
|
|
4998
|
+
]).catch((e) => {
|
|
4230
4999
|
throw DefiError.rpcError(`[${this.protocolName}] supplyQueueLength failed: ${e}`);
|
|
4231
5000
|
});
|
|
5001
|
+
const queueLen = decodeU256(queueLenRaw ?? null);
|
|
4232
5002
|
if (queueLen === 0n) {
|
|
4233
5003
|
return {
|
|
4234
5004
|
protocol: this.protocolName,
|
|
@@ -4240,45 +5010,40 @@ var MorphoBlueAdapter = class {
|
|
|
4240
5010
|
total_borrow: 0n
|
|
4241
5011
|
};
|
|
4242
5012
|
}
|
|
4243
|
-
const
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
functionName: "supplyQueue",
|
|
4247
|
-
args: [0n]
|
|
4248
|
-
}).catch((e) => {
|
|
5013
|
+
const [marketIdRaw] = await multicallRead(this.rpcUrl, [
|
|
5014
|
+
[this.defaultVault, encodeFunctionData16({ abi: META_MORPHO_ABI, functionName: "supplyQueue", args: [0n] })]
|
|
5015
|
+
]).catch((e) => {
|
|
4249
5016
|
throw DefiError.rpcError(`[${this.protocolName}] supplyQueue(0) failed: ${e}`);
|
|
4250
5017
|
});
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
5018
|
+
if (!marketIdRaw || marketIdRaw.length < 66) {
|
|
5019
|
+
throw DefiError.rpcError(`[${this.protocolName}] supplyQueue(0) returned no data`);
|
|
5020
|
+
}
|
|
5021
|
+
const marketId = marketIdRaw.slice(0, 66);
|
|
5022
|
+
const [marketRaw, paramsRaw] = await multicallRead(this.rpcUrl, [
|
|
5023
|
+
[this.morpho, encodeFunctionData16({ abi: MORPHO_ABI, functionName: "market", args: [marketId] })],
|
|
5024
|
+
[this.morpho, encodeFunctionData16({ abi: MORPHO_ABI, functionName: "idToMarketParams", args: [marketId] })]
|
|
5025
|
+
]).catch((e) => {
|
|
5026
|
+
throw DefiError.rpcError(`[${this.protocolName}] market/idToMarketParams failed: ${e}`);
|
|
4258
5027
|
});
|
|
4259
|
-
const
|
|
5028
|
+
const mktDecoded = decodeMarket(marketRaw ?? null);
|
|
5029
|
+
if (!mktDecoded) throw DefiError.rpcError(`[${this.protocolName}] market() returned no data`);
|
|
5030
|
+
const [totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee] = mktDecoded;
|
|
5031
|
+
const paramsDecoded = decodeMarketParams(paramsRaw ?? null);
|
|
5032
|
+
if (!paramsDecoded) throw DefiError.rpcError(`[${this.protocolName}] idToMarketParams returned no data`);
|
|
5033
|
+
const [loanToken, collateralToken, oracle, irm, lltv] = paramsDecoded;
|
|
4260
5034
|
const supplyF = Number(totalSupplyAssets);
|
|
4261
5035
|
const borrowF = Number(totalBorrowAssets);
|
|
4262
5036
|
const util = supplyF > 0 ? borrowF / supplyF : 0;
|
|
4263
|
-
const params2 = await client.readContract({
|
|
4264
|
-
address: this.morpho,
|
|
4265
|
-
abi: MORPHO_ABI,
|
|
4266
|
-
functionName: "idToMarketParams",
|
|
4267
|
-
args: [marketId]
|
|
4268
|
-
}).catch((e) => {
|
|
4269
|
-
throw DefiError.rpcError(`[${this.protocolName}] idToMarketParams failed: ${e}`);
|
|
4270
|
-
});
|
|
4271
|
-
const [loanToken, collateralToken, oracle, irm, lltv] = params2;
|
|
4272
5037
|
const irmMarketParams = { loanToken, collateralToken, oracle, irm, lltv };
|
|
4273
5038
|
const irmMarket = { totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee };
|
|
4274
|
-
const borrowRatePerSec = await
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
});
|
|
5039
|
+
const borrowRatePerSec = await (async () => {
|
|
5040
|
+
const [borrowRateRaw] = await multicallRead(this.rpcUrl, [
|
|
5041
|
+
[irm, encodeFunctionData16({ abi: IRM_ABI, functionName: "borrowRateView", args: [irmMarketParams, irmMarket] })]
|
|
5042
|
+
]).catch((e) => {
|
|
5043
|
+
throw DefiError.rpcError(`[${this.protocolName}] borrowRateView failed: ${e}`);
|
|
5044
|
+
});
|
|
5045
|
+
return decodeU256(borrowRateRaw ?? null);
|
|
5046
|
+
})();
|
|
4282
5047
|
const ratePerSec = Number(borrowRatePerSec) / 1e18;
|
|
4283
5048
|
const borrowApy = ratePerSec * SECONDS_PER_YEAR3 * 100;
|
|
4284
5049
|
const feePct = Number(fee) / 1e18;
|
|
@@ -4299,18 +5064,18 @@ var MorphoBlueAdapter = class {
|
|
|
4299
5064
|
);
|
|
4300
5065
|
}
|
|
4301
5066
|
};
|
|
4302
|
-
var BORROWER_OPS_ABI =
|
|
5067
|
+
var BORROWER_OPS_ABI = parseAbi18([
|
|
4303
5068
|
"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)",
|
|
4304
5069
|
"function adjustTrove(uint256 _troveId, uint256 _collChange, bool _isCollIncrease, uint256 _debtChange, bool _isDebtIncrease, uint256 _upperHint, uint256 _lowerHint, uint256 _maxUpfrontFee) external",
|
|
4305
5070
|
"function closeTrove(uint256 _troveId) external"
|
|
4306
5071
|
]);
|
|
4307
|
-
var TROVE_MANAGER_ABI =
|
|
5072
|
+
var TROVE_MANAGER_ABI = parseAbi18([
|
|
4308
5073
|
"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)"
|
|
4309
5074
|
]);
|
|
4310
|
-
var HINT_HELPERS_ABI =
|
|
5075
|
+
var HINT_HELPERS_ABI = parseAbi18([
|
|
4311
5076
|
"function getApproxHint(uint256 _collIndex, uint256 _interestRate, uint256 _numTrials, uint256 _inputRandomSeed) external view returns (uint256 hintId, uint256 diff, uint256 latestRandomSeed)"
|
|
4312
5077
|
]);
|
|
4313
|
-
var SORTED_TROVES_ABI =
|
|
5078
|
+
var SORTED_TROVES_ABI = parseAbi18([
|
|
4314
5079
|
"function findInsertPosition(uint256 _annualInterestRate, uint256 _prevId, uint256 _nextId) external view returns (uint256 prevId, uint256 nextId)"
|
|
4315
5080
|
]);
|
|
4316
5081
|
var FelixCdpAdapter = class {
|
|
@@ -4338,7 +5103,7 @@ var FelixCdpAdapter = class {
|
|
|
4338
5103
|
if (!this.hintHelpers || !this.sortedTroves || !this.rpcUrl) {
|
|
4339
5104
|
return [0n, 0n];
|
|
4340
5105
|
}
|
|
4341
|
-
const client =
|
|
5106
|
+
const client = createPublicClient13({ transport: http13(this.rpcUrl) });
|
|
4342
5107
|
const approxResult = await client.readContract({
|
|
4343
5108
|
address: this.hintHelpers,
|
|
4344
5109
|
abi: HINT_HELPERS_ABI,
|
|
@@ -4361,7 +5126,7 @@ var FelixCdpAdapter = class {
|
|
|
4361
5126
|
const interestRate = 50000000000000000n;
|
|
4362
5127
|
const [upperHint, lowerHint] = await this.getHints(interestRate);
|
|
4363
5128
|
const hasHints = upperHint !== 0n || lowerHint !== 0n;
|
|
4364
|
-
const data =
|
|
5129
|
+
const data = encodeFunctionData17({
|
|
4365
5130
|
abi: BORROWER_OPS_ABI,
|
|
4366
5131
|
functionName: "openTrove",
|
|
4367
5132
|
args: [
|
|
@@ -4390,7 +5155,7 @@ var FelixCdpAdapter = class {
|
|
|
4390
5155
|
async buildAdjust(params) {
|
|
4391
5156
|
const collChange = params.collateral_delta ?? 0n;
|
|
4392
5157
|
const debtChange = params.debt_delta ?? 0n;
|
|
4393
|
-
const data =
|
|
5158
|
+
const data = encodeFunctionData17({
|
|
4394
5159
|
abi: BORROWER_OPS_ABI,
|
|
4395
5160
|
functionName: "adjustTrove",
|
|
4396
5161
|
args: [
|
|
@@ -4413,7 +5178,7 @@ var FelixCdpAdapter = class {
|
|
|
4413
5178
|
};
|
|
4414
5179
|
}
|
|
4415
5180
|
async buildClose(params) {
|
|
4416
|
-
const data =
|
|
5181
|
+
const data = encodeFunctionData17({
|
|
4417
5182
|
abi: BORROWER_OPS_ABI,
|
|
4418
5183
|
functionName: "closeTrove",
|
|
4419
5184
|
args: [params.cdp_id]
|
|
@@ -4429,7 +5194,7 @@ var FelixCdpAdapter = class {
|
|
|
4429
5194
|
async getCdpInfo(cdpId) {
|
|
4430
5195
|
if (!this.rpcUrl) throw DefiError.rpcError(`[${this.protocolName}] getCdpInfo requires RPC \u2014 set HYPEREVM_RPC_URL`);
|
|
4431
5196
|
if (!this.troveManager) throw DefiError.contractError(`[${this.protocolName}] trove_manager contract not configured`);
|
|
4432
|
-
const client =
|
|
5197
|
+
const client = createPublicClient13({ transport: http13(this.rpcUrl) });
|
|
4433
5198
|
const data = await client.readContract({
|
|
4434
5199
|
address: this.troveManager,
|
|
4435
5200
|
abi: TROVE_MANAGER_ABI,
|
|
@@ -4462,7 +5227,7 @@ var FelixCdpAdapter = class {
|
|
|
4462
5227
|
};
|
|
4463
5228
|
}
|
|
4464
5229
|
};
|
|
4465
|
-
var PRICE_FEED_ABI =
|
|
5230
|
+
var PRICE_FEED_ABI = parseAbi19([
|
|
4466
5231
|
"function fetchPrice() external view returns (uint256 price, bool isNewOracleFailureDetected)",
|
|
4467
5232
|
"function lastGoodPrice() external view returns (uint256)"
|
|
4468
5233
|
]);
|
|
@@ -4488,7 +5253,7 @@ var FelixOracleAdapter = class {
|
|
|
4488
5253
|
if (asset !== this.asset && this.asset !== "0x0000000000000000000000000000000000000000") {
|
|
4489
5254
|
throw DefiError.unsupported(`[${this.protocolName}] Felix PriceFeed only supports asset ${this.asset}`);
|
|
4490
5255
|
}
|
|
4491
|
-
const client =
|
|
5256
|
+
const client = createPublicClient14({ transport: http14(this.rpcUrl) });
|
|
4492
5257
|
let priceVal;
|
|
4493
5258
|
try {
|
|
4494
5259
|
const result = await client.readContract({
|
|
@@ -4527,7 +5292,7 @@ var FelixOracleAdapter = class {
|
|
|
4527
5292
|
return results;
|
|
4528
5293
|
}
|
|
4529
5294
|
};
|
|
4530
|
-
var ERC4626_ABI =
|
|
5295
|
+
var ERC4626_ABI = parseAbi20([
|
|
4531
5296
|
"function asset() external view returns (address)",
|
|
4532
5297
|
"function totalAssets() external view returns (uint256)",
|
|
4533
5298
|
"function totalSupply() external view returns (uint256)",
|
|
@@ -4551,7 +5316,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4551
5316
|
return this.protocolName;
|
|
4552
5317
|
}
|
|
4553
5318
|
async buildDeposit(assets, receiver) {
|
|
4554
|
-
const data =
|
|
5319
|
+
const data = encodeFunctionData18({
|
|
4555
5320
|
abi: ERC4626_ABI,
|
|
4556
5321
|
functionName: "deposit",
|
|
4557
5322
|
args: [assets, receiver]
|
|
@@ -4565,7 +5330,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4565
5330
|
};
|
|
4566
5331
|
}
|
|
4567
5332
|
async buildWithdraw(assets, receiver, owner) {
|
|
4568
|
-
const data =
|
|
5333
|
+
const data = encodeFunctionData18({
|
|
4569
5334
|
abi: ERC4626_ABI,
|
|
4570
5335
|
functionName: "withdraw",
|
|
4571
5336
|
args: [assets, receiver, owner]
|
|
@@ -4580,7 +5345,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4580
5345
|
}
|
|
4581
5346
|
async totalAssets() {
|
|
4582
5347
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4583
|
-
const client =
|
|
5348
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4584
5349
|
return client.readContract({
|
|
4585
5350
|
address: this.vaultAddress,
|
|
4586
5351
|
abi: ERC4626_ABI,
|
|
@@ -4591,7 +5356,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4591
5356
|
}
|
|
4592
5357
|
async convertToShares(assets) {
|
|
4593
5358
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4594
|
-
const client =
|
|
5359
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4595
5360
|
return client.readContract({
|
|
4596
5361
|
address: this.vaultAddress,
|
|
4597
5362
|
abi: ERC4626_ABI,
|
|
@@ -4603,7 +5368,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4603
5368
|
}
|
|
4604
5369
|
async convertToAssets(shares) {
|
|
4605
5370
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4606
|
-
const client =
|
|
5371
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4607
5372
|
return client.readContract({
|
|
4608
5373
|
address: this.vaultAddress,
|
|
4609
5374
|
abi: ERC4626_ABI,
|
|
@@ -4615,7 +5380,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4615
5380
|
}
|
|
4616
5381
|
async getVaultInfo() {
|
|
4617
5382
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4618
|
-
const client =
|
|
5383
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4619
5384
|
const [totalAssets, totalSupply, asset] = await Promise.all([
|
|
4620
5385
|
client.readContract({ address: this.vaultAddress, abi: ERC4626_ABI, functionName: "totalAssets" }).catch((e) => {
|
|
4621
5386
|
throw DefiError.rpcError(`[${this.protocolName}] totalAssets failed: ${e}`);
|
|
@@ -4636,7 +5401,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4636
5401
|
};
|
|
4637
5402
|
}
|
|
4638
5403
|
};
|
|
4639
|
-
var GENERIC_LST_ABI =
|
|
5404
|
+
var GENERIC_LST_ABI = parseAbi21([
|
|
4640
5405
|
"function stake() external payable returns (uint256)",
|
|
4641
5406
|
"function unstake(uint256 amount) external returns (uint256)"
|
|
4642
5407
|
]);
|
|
@@ -4653,7 +5418,7 @@ var GenericLstAdapter = class {
|
|
|
4653
5418
|
return this.protocolName;
|
|
4654
5419
|
}
|
|
4655
5420
|
async buildStake(params) {
|
|
4656
|
-
const data =
|
|
5421
|
+
const data = encodeFunctionData19({ abi: GENERIC_LST_ABI, functionName: "stake" });
|
|
4657
5422
|
return {
|
|
4658
5423
|
description: `[${this.protocolName}] Stake ${params.amount} HYPE`,
|
|
4659
5424
|
to: this.staking,
|
|
@@ -4663,7 +5428,7 @@ var GenericLstAdapter = class {
|
|
|
4663
5428
|
};
|
|
4664
5429
|
}
|
|
4665
5430
|
async buildUnstake(params) {
|
|
4666
|
-
const data =
|
|
5431
|
+
const data = encodeFunctionData19({
|
|
4667
5432
|
abi: GENERIC_LST_ABI,
|
|
4668
5433
|
functionName: "unstake",
|
|
4669
5434
|
args: [params.amount]
|
|
@@ -4680,11 +5445,11 @@ var GenericLstAdapter = class {
|
|
|
4680
5445
|
throw DefiError.unsupported(`[${this.protocolName}] getInfo requires RPC`);
|
|
4681
5446
|
}
|
|
4682
5447
|
};
|
|
4683
|
-
var STHYPE_ABI =
|
|
5448
|
+
var STHYPE_ABI = parseAbi222([
|
|
4684
5449
|
"function submit(address referral) external payable returns (uint256)",
|
|
4685
5450
|
"function requestWithdrawals(uint256[] amounts, address owner) external returns (uint256[] requestIds)"
|
|
4686
5451
|
]);
|
|
4687
|
-
var ERC20_ABI3 =
|
|
5452
|
+
var ERC20_ABI3 = parseAbi222([
|
|
4688
5453
|
"function totalSupply() external view returns (uint256)"
|
|
4689
5454
|
]);
|
|
4690
5455
|
var StHypeAdapter = class {
|
|
@@ -4704,7 +5469,7 @@ var StHypeAdapter = class {
|
|
|
4704
5469
|
return this.protocolName;
|
|
4705
5470
|
}
|
|
4706
5471
|
async buildStake(params) {
|
|
4707
|
-
const data =
|
|
5472
|
+
const data = encodeFunctionData20({
|
|
4708
5473
|
abi: STHYPE_ABI,
|
|
4709
5474
|
functionName: "submit",
|
|
4710
5475
|
args: [zeroAddress9]
|
|
@@ -4718,7 +5483,7 @@ var StHypeAdapter = class {
|
|
|
4718
5483
|
};
|
|
4719
5484
|
}
|
|
4720
5485
|
async buildUnstake(params) {
|
|
4721
|
-
const data =
|
|
5486
|
+
const data = encodeFunctionData20({
|
|
4722
5487
|
abi: STHYPE_ABI,
|
|
4723
5488
|
functionName: "requestWithdrawals",
|
|
4724
5489
|
args: [[params.amount], params.recipient]
|
|
@@ -4733,7 +5498,7 @@ var StHypeAdapter = class {
|
|
|
4733
5498
|
}
|
|
4734
5499
|
async getInfo() {
|
|
4735
5500
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4736
|
-
const client =
|
|
5501
|
+
const client = createPublicClient16({ transport: http16(this.rpcUrl) });
|
|
4737
5502
|
const tokenAddr = this.sthypeToken ?? this.staking;
|
|
4738
5503
|
const totalSupply = await client.readContract({
|
|
4739
5504
|
address: tokenAddr,
|
|
@@ -4751,12 +5516,12 @@ var StHypeAdapter = class {
|
|
|
4751
5516
|
};
|
|
4752
5517
|
}
|
|
4753
5518
|
};
|
|
4754
|
-
var KINETIQ_ABI =
|
|
5519
|
+
var KINETIQ_ABI = parseAbi23([
|
|
4755
5520
|
"function stake() external payable returns (uint256)",
|
|
4756
5521
|
"function requestUnstake(uint256 amount) external returns (uint256)",
|
|
4757
5522
|
"function totalStaked() external view returns (uint256)"
|
|
4758
5523
|
]);
|
|
4759
|
-
var ORACLE_ABI3 =
|
|
5524
|
+
var ORACLE_ABI3 = parseAbi23([
|
|
4760
5525
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
4761
5526
|
]);
|
|
4762
5527
|
var WHYPE = "0x5555555555555555555555555555555555555555";
|
|
@@ -4778,7 +5543,7 @@ var KinetiqAdapter = class {
|
|
|
4778
5543
|
return this.protocolName;
|
|
4779
5544
|
}
|
|
4780
5545
|
async buildStake(params) {
|
|
4781
|
-
const data =
|
|
5546
|
+
const data = encodeFunctionData21({ abi: KINETIQ_ABI, functionName: "stake" });
|
|
4782
5547
|
return {
|
|
4783
5548
|
description: `[${this.protocolName}] Stake ${params.amount} HYPE for kHYPE`,
|
|
4784
5549
|
to: this.staking,
|
|
@@ -4788,7 +5553,7 @@ var KinetiqAdapter = class {
|
|
|
4788
5553
|
};
|
|
4789
5554
|
}
|
|
4790
5555
|
async buildUnstake(params) {
|
|
4791
|
-
const data =
|
|
5556
|
+
const data = encodeFunctionData21({
|
|
4792
5557
|
abi: KINETIQ_ABI,
|
|
4793
5558
|
functionName: "requestUnstake",
|
|
4794
5559
|
args: [params.amount]
|
|
@@ -4803,7 +5568,7 @@ var KinetiqAdapter = class {
|
|
|
4803
5568
|
}
|
|
4804
5569
|
async getInfo() {
|
|
4805
5570
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4806
|
-
const client =
|
|
5571
|
+
const client = createPublicClient17({ transport: http17(this.rpcUrl) });
|
|
4807
5572
|
const totalStaked = await client.readContract({
|
|
4808
5573
|
address: this.staking,
|
|
4809
5574
|
abi: KINETIQ_ABI,
|
|
@@ -4825,15 +5590,15 @@ var KinetiqAdapter = class {
|
|
|
4825
5590
|
};
|
|
4826
5591
|
}
|
|
4827
5592
|
};
|
|
4828
|
-
var HLP_ABI =
|
|
5593
|
+
var HLP_ABI = parseAbi24([
|
|
4829
5594
|
"function deposit(uint256 amount) external returns (uint256)",
|
|
4830
5595
|
"function withdraw(uint256 shares) external returns (uint256)"
|
|
4831
5596
|
]);
|
|
4832
|
-
var RYSK_ABI =
|
|
5597
|
+
var RYSK_ABI = parseAbi25([
|
|
4833
5598
|
"function openOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 premium)",
|
|
4834
5599
|
"function closeOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 payout)"
|
|
4835
5600
|
]);
|
|
4836
|
-
var ERC721_ABI =
|
|
5601
|
+
var ERC721_ABI = parseAbi26([
|
|
4837
5602
|
"function name() returns (string)",
|
|
4838
5603
|
"function symbol() returns (string)",
|
|
4839
5604
|
"function totalSupply() returns (uint256)",
|
|
@@ -4853,7 +5618,7 @@ var ERC721Adapter = class {
|
|
|
4853
5618
|
}
|
|
4854
5619
|
async getCollectionInfo(collection) {
|
|
4855
5620
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4856
|
-
const client =
|
|
5621
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
4857
5622
|
const [collectionName, symbol, totalSupply] = await Promise.all([
|
|
4858
5623
|
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "name" }).catch((e) => {
|
|
4859
5624
|
throw DefiError.rpcError(`[${this.protocolName}] name failed: ${e}`);
|
|
@@ -4872,7 +5637,7 @@ var ERC721Adapter = class {
|
|
|
4872
5637
|
}
|
|
4873
5638
|
async getTokenInfo(collection, tokenId) {
|
|
4874
5639
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4875
|
-
const client =
|
|
5640
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
4876
5641
|
const [owner, tokenUri] = await Promise.all([
|
|
4877
5642
|
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "ownerOf", args: [tokenId] }).catch((e) => {
|
|
4878
5643
|
throw DefiError.rpcError(`[${this.protocolName}] ownerOf failed: ${e}`);
|
|
@@ -4888,7 +5653,7 @@ var ERC721Adapter = class {
|
|
|
4888
5653
|
}
|
|
4889
5654
|
async getBalance(owner, collection) {
|
|
4890
5655
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4891
|
-
const client =
|
|
5656
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
4892
5657
|
return client.readContract({ address: collection, abi: ERC721_ABI, functionName: "balanceOf", args: [owner] }).catch((e) => {
|
|
4893
5658
|
throw DefiError.rpcError(`[${this.protocolName}] balanceOf failed: ${e}`);
|
|
4894
5659
|
});
|
|
@@ -5009,6 +5774,9 @@ function createOracleFromCdp(entry, _asset, rpcUrl) {
|
|
|
5009
5774
|
throw DefiError.unsupported(`Oracle not available for CDP interface '${entry.interface}'`);
|
|
5010
5775
|
}
|
|
5011
5776
|
}
|
|
5777
|
+
function createMerchantMoeLB(entry, rpcUrl) {
|
|
5778
|
+
return new MerchantMoeLBAdapter(entry, rpcUrl);
|
|
5779
|
+
}
|
|
5012
5780
|
var DexSpotPrice = class {
|
|
5013
5781
|
/**
|
|
5014
5782
|
* Get the spot price for `token` denominated in `quoteToken` (e.g. USDC).
|
|
@@ -6016,20 +6784,20 @@ function registerYield(parent, getOpts, makeExecutor2) {
|
|
|
6016
6784
|
}
|
|
6017
6785
|
|
|
6018
6786
|
// src/commands/portfolio.ts
|
|
6019
|
-
import { encodeFunctionData as
|
|
6787
|
+
import { encodeFunctionData as encodeFunctionData25, parseAbi as parseAbi28 } from "viem";
|
|
6020
6788
|
|
|
6021
6789
|
// src/portfolio-tracker.ts
|
|
6022
6790
|
import { mkdirSync, writeFileSync, readdirSync as readdirSync2, readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
6023
6791
|
import { homedir } from "os";
|
|
6024
6792
|
import { resolve as resolve2 } from "path";
|
|
6025
|
-
import { encodeFunctionData as
|
|
6026
|
-
var ERC20_ABI4 =
|
|
6793
|
+
import { encodeFunctionData as encodeFunctionData24, parseAbi as parseAbi27 } from "viem";
|
|
6794
|
+
var ERC20_ABI4 = parseAbi27([
|
|
6027
6795
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
6028
6796
|
]);
|
|
6029
|
-
var ORACLE_ABI4 =
|
|
6797
|
+
var ORACLE_ABI4 = parseAbi27([
|
|
6030
6798
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
6031
6799
|
]);
|
|
6032
|
-
var POOL_ABI3 =
|
|
6800
|
+
var POOL_ABI3 = parseAbi27([
|
|
6033
6801
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
6034
6802
|
]);
|
|
6035
6803
|
function decodeU256Word(data, wordOffset = 0) {
|
|
@@ -6058,7 +6826,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
6058
6826
|
tokenEntries.push({ symbol: t.symbol, address: entry.address, decimals: entry.decimals });
|
|
6059
6827
|
calls.push([
|
|
6060
6828
|
entry.address,
|
|
6061
|
-
|
|
6829
|
+
encodeFunctionData24({ abi: ERC20_ABI4, functionName: "balanceOf", args: [user] })
|
|
6062
6830
|
]);
|
|
6063
6831
|
callLabels.push(`balance:${t.symbol}`);
|
|
6064
6832
|
}
|
|
@@ -6066,7 +6834,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
6066
6834
|
for (const p of lendingProtocols) {
|
|
6067
6835
|
calls.push([
|
|
6068
6836
|
p.contracts["pool"],
|
|
6069
|
-
|
|
6837
|
+
encodeFunctionData24({ abi: POOL_ABI3, functionName: "getUserAccountData", args: [user] })
|
|
6070
6838
|
]);
|
|
6071
6839
|
callLabels.push(`lending:${p.name}`);
|
|
6072
6840
|
}
|
|
@@ -6076,7 +6844,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
6076
6844
|
if (oracleAddr) {
|
|
6077
6845
|
calls.push([
|
|
6078
6846
|
oracleAddr,
|
|
6079
|
-
|
|
6847
|
+
encodeFunctionData24({ abi: ORACLE_ABI4, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
6080
6848
|
]);
|
|
6081
6849
|
callLabels.push("price:native");
|
|
6082
6850
|
}
|
|
@@ -6214,16 +6982,16 @@ function calculatePnL(current, previous) {
|
|
|
6214
6982
|
}
|
|
6215
6983
|
|
|
6216
6984
|
// src/commands/portfolio.ts
|
|
6217
|
-
var ERC20_ABI5 =
|
|
6985
|
+
var ERC20_ABI5 = parseAbi28([
|
|
6218
6986
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
6219
6987
|
]);
|
|
6220
|
-
var POOL_ABI4 =
|
|
6988
|
+
var POOL_ABI4 = parseAbi28([
|
|
6221
6989
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
6222
6990
|
]);
|
|
6223
|
-
var ORACLE_ABI5 =
|
|
6991
|
+
var ORACLE_ABI5 = parseAbi28([
|
|
6224
6992
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
6225
6993
|
]);
|
|
6226
|
-
function
|
|
6994
|
+
function decodeU2562(data, wordOffset = 0) {
|
|
6227
6995
|
if (!data || data.length < 2 + (wordOffset + 1) * 64) return 0n;
|
|
6228
6996
|
const hex = data.slice(2 + wordOffset * 64, 2 + wordOffset * 64 + 64);
|
|
6229
6997
|
return BigInt("0x" + hex);
|
|
@@ -6260,7 +7028,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6260
7028
|
if (entry.address === "0x0000000000000000000000000000000000000000") continue;
|
|
6261
7029
|
calls.push([
|
|
6262
7030
|
entry.address,
|
|
6263
|
-
|
|
7031
|
+
encodeFunctionData25({ abi: ERC20_ABI5, functionName: "balanceOf", args: [user] })
|
|
6264
7032
|
]);
|
|
6265
7033
|
callLabels.push(`balance:${symbol}`);
|
|
6266
7034
|
}
|
|
@@ -6268,7 +7036,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6268
7036
|
for (const p of lendingProtocols) {
|
|
6269
7037
|
calls.push([
|
|
6270
7038
|
p.contracts["pool"],
|
|
6271
|
-
|
|
7039
|
+
encodeFunctionData25({ abi: POOL_ABI4, functionName: "getUserAccountData", args: [user] })
|
|
6272
7040
|
]);
|
|
6273
7041
|
callLabels.push(`lending:${p.name}`);
|
|
6274
7042
|
}
|
|
@@ -6278,7 +7046,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6278
7046
|
if (oracleAddr) {
|
|
6279
7047
|
calls.push([
|
|
6280
7048
|
oracleAddr,
|
|
6281
|
-
|
|
7049
|
+
encodeFunctionData25({ abi: ORACLE_ABI5, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
6282
7050
|
]);
|
|
6283
7051
|
callLabels.push("price:native");
|
|
6284
7052
|
}
|
|
@@ -6303,7 +7071,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6303
7071
|
let nativePriceUsd = 0;
|
|
6304
7072
|
if (oracleAddr) {
|
|
6305
7073
|
const priceData = results[results.length - 1] ?? null;
|
|
6306
|
-
nativePriceUsd = Number(
|
|
7074
|
+
nativePriceUsd = Number(decodeU2562(priceData)) / 1e8;
|
|
6307
7075
|
}
|
|
6308
7076
|
let totalValueUsd = 0;
|
|
6309
7077
|
let idx = 0;
|
|
@@ -6317,7 +7085,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6317
7085
|
}
|
|
6318
7086
|
if (entry.address === "0x0000000000000000000000000000000000000000") continue;
|
|
6319
7087
|
if (idx >= results.length) break;
|
|
6320
|
-
const balance =
|
|
7088
|
+
const balance = decodeU2562(results[idx] ?? null);
|
|
6321
7089
|
if (balance > 0n) {
|
|
6322
7090
|
const decimals = entry.decimals;
|
|
6323
7091
|
const balF64 = Number(balance) / 10 ** decimals;
|
|
@@ -6337,9 +7105,9 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6337
7105
|
if (idx >= results.length) break;
|
|
6338
7106
|
const data = results[idx] ?? null;
|
|
6339
7107
|
if (data && data.length >= 2 + 192 * 2) {
|
|
6340
|
-
const collateral = Number(
|
|
6341
|
-
const debt = Number(
|
|
6342
|
-
const hfRaw =
|
|
7108
|
+
const collateral = Number(decodeU2562(data, 0)) / 1e8;
|
|
7109
|
+
const debt = Number(decodeU2562(data, 1)) / 1e8;
|
|
7110
|
+
const hfRaw = decodeU2562(data, 5);
|
|
6343
7111
|
let hf = null;
|
|
6344
7112
|
if (hfRaw <= BigInt("0xffffffffffffffffffffffffffffffff")) {
|
|
6345
7113
|
const v = Number(hfRaw) / 1e18;
|
|
@@ -6640,14 +7408,14 @@ function registerAlert(parent, getOpts) {
|
|
|
6640
7408
|
}
|
|
6641
7409
|
|
|
6642
7410
|
// src/commands/scan.ts
|
|
6643
|
-
import { encodeFunctionData as
|
|
6644
|
-
var AAVE_ORACLE_ABI =
|
|
7411
|
+
import { encodeFunctionData as encodeFunctionData26, parseAbi as parseAbi29 } from "viem";
|
|
7412
|
+
var AAVE_ORACLE_ABI = parseAbi29([
|
|
6645
7413
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
6646
7414
|
]);
|
|
6647
|
-
var UNIV2_ROUTER_ABI =
|
|
7415
|
+
var UNIV2_ROUTER_ABI = parseAbi29([
|
|
6648
7416
|
"function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory)"
|
|
6649
7417
|
]);
|
|
6650
|
-
var VTOKEN_ABI =
|
|
7418
|
+
var VTOKEN_ABI = parseAbi29([
|
|
6651
7419
|
"function exchangeRateStored() external view returns (uint256)"
|
|
6652
7420
|
]);
|
|
6653
7421
|
var STABLECOINS = /* @__PURE__ */ new Set(["USDC", "USDT", "DAI", "USDT0"]);
|
|
@@ -6757,7 +7525,7 @@ function registerScan(parent, getOpts) {
|
|
|
6757
7525
|
callTypes.push({ kind: "oracle", oracle: oracle.name, token: token.symbol, oracleDecimals: oracle.decimals });
|
|
6758
7526
|
calls.push([
|
|
6759
7527
|
oracle.addr,
|
|
6760
|
-
|
|
7528
|
+
encodeFunctionData26({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })
|
|
6761
7529
|
]);
|
|
6762
7530
|
}
|
|
6763
7531
|
}
|
|
@@ -6768,7 +7536,7 @@ function registerScan(parent, getOpts) {
|
|
|
6768
7536
|
callTypes.push({ kind: "dex", token: token.symbol, outDecimals: quoteStable.decimals });
|
|
6769
7537
|
calls.push([
|
|
6770
7538
|
dexRouter,
|
|
6771
|
-
|
|
7539
|
+
encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [amountIn, path] })
|
|
6772
7540
|
]);
|
|
6773
7541
|
}
|
|
6774
7542
|
}
|
|
@@ -6777,7 +7545,7 @@ function registerScan(parent, getOpts) {
|
|
|
6777
7545
|
callTypes.push({ kind: "stable", from: "USDC", to: "USDT", outDecimals: usdt.decimals });
|
|
6778
7546
|
calls.push([
|
|
6779
7547
|
dexRouter,
|
|
6780
|
-
|
|
7548
|
+
encodeFunctionData26({
|
|
6781
7549
|
abi: UNIV2_ROUTER_ABI,
|
|
6782
7550
|
functionName: "getAmountsOut",
|
|
6783
7551
|
args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]]
|
|
@@ -6786,7 +7554,7 @@ function registerScan(parent, getOpts) {
|
|
|
6786
7554
|
callTypes.push({ kind: "stable", from: "USDT", to: "USDC", outDecimals: usdc.decimals });
|
|
6787
7555
|
calls.push([
|
|
6788
7556
|
dexRouter,
|
|
6789
|
-
|
|
7557
|
+
encodeFunctionData26({
|
|
6790
7558
|
abi: UNIV2_ROUTER_ABI,
|
|
6791
7559
|
functionName: "getAmountsOut",
|
|
6792
7560
|
args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]]
|
|
@@ -6797,7 +7565,7 @@ function registerScan(parent, getOpts) {
|
|
|
6797
7565
|
for (const fork of compoundForks) {
|
|
6798
7566
|
for (const { key, addr } of fork.vtokens) {
|
|
6799
7567
|
callTypes.push({ kind: "exchangeRate", protocol: fork.name, vtoken: key });
|
|
6800
|
-
calls.push([addr,
|
|
7568
|
+
calls.push([addr, encodeFunctionData26({ abi: VTOKEN_ABI, functionName: "exchangeRateStored", args: [] })]);
|
|
6801
7569
|
}
|
|
6802
7570
|
}
|
|
6803
7571
|
}
|
|
@@ -7015,22 +7783,22 @@ async function runAllChains(registry, patterns, oracleThreshold, stableThreshold
|
|
|
7015
7783
|
for (const oracle of oracles) {
|
|
7016
7784
|
for (const token of scanTokens) {
|
|
7017
7785
|
cts.push({ kind: "oracle", oracle: oracle.name, token: token.symbol, dec: oracle.decimals });
|
|
7018
|
-
calls.push([oracle.addr,
|
|
7786
|
+
calls.push([oracle.addr, encodeFunctionData26({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })]);
|
|
7019
7787
|
}
|
|
7020
7788
|
}
|
|
7021
7789
|
if (dexRouter) {
|
|
7022
7790
|
for (const token of scanTokens) {
|
|
7023
7791
|
const path = wrappedNative && token.address.toLowerCase() === wrappedNative.toLowerCase() ? [token.address, quoteStable.address] : wrappedNative ? [token.address, wrappedNative, quoteStable.address] : [token.address, quoteStable.address];
|
|
7024
7792
|
cts.push({ kind: "dex", token: token.symbol, dec: quoteStable.decimals });
|
|
7025
|
-
calls.push([dexRouter,
|
|
7793
|
+
calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(token.decimals), path] })]);
|
|
7026
7794
|
}
|
|
7027
7795
|
}
|
|
7028
7796
|
}
|
|
7029
7797
|
if (doStable && usdc && usdt && dexRouter) {
|
|
7030
7798
|
cts.push({ kind: "stable", from: "USDC", to: "USDT", dec: usdt.decimals });
|
|
7031
|
-
calls.push([dexRouter,
|
|
7799
|
+
calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]] })]);
|
|
7032
7800
|
cts.push({ kind: "stable", from: "USDT", to: "USDC", dec: usdc.decimals });
|
|
7033
|
-
calls.push([dexRouter,
|
|
7801
|
+
calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]] })]);
|
|
7034
7802
|
}
|
|
7035
7803
|
if (calls.length === 0) return null;
|
|
7036
7804
|
const ct0 = Date.now();
|
|
@@ -7158,14 +7926,14 @@ function registerArb(parent, getOpts, makeExecutor2) {
|
|
|
7158
7926
|
}
|
|
7159
7927
|
|
|
7160
7928
|
// src/commands/positions.ts
|
|
7161
|
-
import { encodeFunctionData as
|
|
7162
|
-
var ERC20_ABI6 =
|
|
7929
|
+
import { encodeFunctionData as encodeFunctionData27, parseAbi as parseAbi30 } from "viem";
|
|
7930
|
+
var ERC20_ABI6 = parseAbi30([
|
|
7163
7931
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
7164
7932
|
]);
|
|
7165
|
-
var POOL_ABI5 =
|
|
7933
|
+
var POOL_ABI5 = parseAbi30([
|
|
7166
7934
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
7167
7935
|
]);
|
|
7168
|
-
var ORACLE_ABI6 =
|
|
7936
|
+
var ORACLE_ABI6 = parseAbi30([
|
|
7169
7937
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
7170
7938
|
]);
|
|
7171
7939
|
function round22(x) {
|
|
@@ -7181,7 +7949,7 @@ function estimateTokenValue(symbol, balance, nativePrice) {
|
|
|
7181
7949
|
if (["WETH", "ETH", "METH", "CBETH", "WSTETH"].includes(s)) return balance * 2350;
|
|
7182
7950
|
return balance * nativePrice;
|
|
7183
7951
|
}
|
|
7184
|
-
function
|
|
7952
|
+
function decodeU2563(data, offset = 0) {
|
|
7185
7953
|
if (!data || data.length < 2 + (offset + 32) * 2) return 0n;
|
|
7186
7954
|
const hex = data.slice(2 + offset * 64, 2 + offset * 64 + 64);
|
|
7187
7955
|
return BigInt("0x" + hex);
|
|
@@ -7194,7 +7962,7 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7194
7962
|
callTypes.push({ kind: "token", symbol: token.symbol, decimals: token.decimals });
|
|
7195
7963
|
calls.push([
|
|
7196
7964
|
token.address,
|
|
7197
|
-
|
|
7965
|
+
encodeFunctionData27({ abi: ERC20_ABI6, functionName: "balanceOf", args: [user] })
|
|
7198
7966
|
]);
|
|
7199
7967
|
}
|
|
7200
7968
|
}
|
|
@@ -7202,14 +7970,14 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7202
7970
|
callTypes.push({ kind: "lending", protocol: name, iface });
|
|
7203
7971
|
calls.push([
|
|
7204
7972
|
pool,
|
|
7205
|
-
|
|
7973
|
+
encodeFunctionData27({ abi: POOL_ABI5, functionName: "getUserAccountData", args: [user] })
|
|
7206
7974
|
]);
|
|
7207
7975
|
}
|
|
7208
7976
|
if (oracleAddr) {
|
|
7209
7977
|
callTypes.push({ kind: "native_price" });
|
|
7210
7978
|
calls.push([
|
|
7211
7979
|
oracleAddr,
|
|
7212
|
-
|
|
7980
|
+
encodeFunctionData27({ abi: ORACLE_ABI6, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
7213
7981
|
]);
|
|
7214
7982
|
}
|
|
7215
7983
|
if (calls.length === 0) return null;
|
|
@@ -7219,7 +7987,7 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7219
7987
|
} catch {
|
|
7220
7988
|
return null;
|
|
7221
7989
|
}
|
|
7222
|
-
const nativePrice = oracleAddr ? Number(
|
|
7990
|
+
const nativePrice = oracleAddr ? Number(decodeU2563(results[results.length - 1])) / 1e8 : 0;
|
|
7223
7991
|
const tokenBalances = [];
|
|
7224
7992
|
const lendingPositions = [];
|
|
7225
7993
|
let chainValue = 0;
|
|
@@ -7229,7 +7997,7 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7229
7997
|
const ct = callTypes[i];
|
|
7230
7998
|
const data = results[i] ?? null;
|
|
7231
7999
|
if (ct.kind === "token") {
|
|
7232
|
-
const balance =
|
|
8000
|
+
const balance = decodeU2563(data);
|
|
7233
8001
|
if (balance > 0n) {
|
|
7234
8002
|
const balF64 = Number(balance) / 10 ** ct.decimals;
|
|
7235
8003
|
const valueUsd = estimateTokenValue(ct.symbol, balF64, nativePrice);
|
|
@@ -7246,9 +8014,9 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7246
8014
|
if (data && data.length >= 2 + 192 * 2) {
|
|
7247
8015
|
const priceDecimals = ct.iface === "aave_v2" ? 18 : 8;
|
|
7248
8016
|
const divisor = 10 ** priceDecimals;
|
|
7249
|
-
const collateral = Number(
|
|
7250
|
-
const debt = Number(
|
|
7251
|
-
const hfRaw =
|
|
8017
|
+
const collateral = Number(decodeU2563(data, 0)) / divisor;
|
|
8018
|
+
const debt = Number(decodeU2563(data, 1)) / divisor;
|
|
8019
|
+
const hfRaw = decodeU2563(data, 5);
|
|
7252
8020
|
let hf = null;
|
|
7253
8021
|
if (hfRaw <= BigInt("0xffffffffffffffffffffffffffffffff")) {
|
|
7254
8022
|
const v = Number(hfRaw) / 1e18;
|
|
@@ -7502,14 +8270,14 @@ function registerPrice(parent, getOpts) {
|
|
|
7502
8270
|
}
|
|
7503
8271
|
|
|
7504
8272
|
// src/commands/wallet.ts
|
|
7505
|
-
import { createPublicClient as
|
|
8273
|
+
import { createPublicClient as createPublicClient19, http as http19, formatEther } from "viem";
|
|
7506
8274
|
function registerWallet(parent, getOpts) {
|
|
7507
8275
|
const wallet = parent.command("wallet").description("Wallet management");
|
|
7508
8276
|
wallet.command("balance").description("Show native token balance").requiredOption("--address <address>", "Wallet address to query").action(async (opts) => {
|
|
7509
8277
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7510
8278
|
const registry = Registry.loadEmbedded();
|
|
7511
8279
|
const chain = registry.getChain(chainName);
|
|
7512
|
-
const client =
|
|
8280
|
+
const client = createPublicClient19({ transport: http19(chain.effectiveRpcUrl()) });
|
|
7513
8281
|
const balance = await client.getBalance({ address: opts.address });
|
|
7514
8282
|
printOutput({
|
|
7515
8283
|
chain: chain.name,
|
|
@@ -7526,14 +8294,14 @@ function registerWallet(parent, getOpts) {
|
|
|
7526
8294
|
}
|
|
7527
8295
|
|
|
7528
8296
|
// src/commands/token.ts
|
|
7529
|
-
import { createPublicClient as
|
|
8297
|
+
import { createPublicClient as createPublicClient20, http as http20, maxUint256 } from "viem";
|
|
7530
8298
|
function registerToken(parent, getOpts, makeExecutor2) {
|
|
7531
8299
|
const token = parent.command("token").description("Token operations: approve, allowance, transfer, balance");
|
|
7532
8300
|
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) => {
|
|
7533
8301
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7534
8302
|
const registry = Registry.loadEmbedded();
|
|
7535
8303
|
const chain = registry.getChain(chainName);
|
|
7536
|
-
const client =
|
|
8304
|
+
const client = createPublicClient20({ transport: http20(chain.effectiveRpcUrl()) });
|
|
7537
8305
|
const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
|
|
7538
8306
|
const [balance, symbol, decimals] = await Promise.all([
|
|
7539
8307
|
client.readContract({ address: tokenAddr, abi: erc20Abi, functionName: "balanceOf", args: [opts.owner] }),
|
|
@@ -7562,7 +8330,7 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
7562
8330
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7563
8331
|
const registry = Registry.loadEmbedded();
|
|
7564
8332
|
const chain = registry.getChain(chainName);
|
|
7565
|
-
const client =
|
|
8333
|
+
const client = createPublicClient20({ transport: http20(chain.effectiveRpcUrl()) });
|
|
7566
8334
|
const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
|
|
7567
8335
|
const allowance = await client.readContract({
|
|
7568
8336
|
address: tokenAddr,
|
|
@@ -7584,8 +8352,8 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
7584
8352
|
}
|
|
7585
8353
|
|
|
7586
8354
|
// src/commands/whales.ts
|
|
7587
|
-
import { encodeFunctionData as
|
|
7588
|
-
var POOL_ABI6 =
|
|
8355
|
+
import { encodeFunctionData as encodeFunctionData28, parseAbi as parseAbi31 } from "viem";
|
|
8356
|
+
var POOL_ABI6 = parseAbi31([
|
|
7589
8357
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
7590
8358
|
]);
|
|
7591
8359
|
function round24(x) {
|
|
@@ -7594,7 +8362,7 @@ function round24(x) {
|
|
|
7594
8362
|
function round43(x) {
|
|
7595
8363
|
return Math.round(x * 1e4) / 1e4;
|
|
7596
8364
|
}
|
|
7597
|
-
function
|
|
8365
|
+
function decodeU2564(data, wordOffset = 0) {
|
|
7598
8366
|
if (!data || data.length < 2 + (wordOffset + 1) * 64) return 0n;
|
|
7599
8367
|
const hex = data.slice(2 + wordOffset * 64, 2 + wordOffset * 64 + 64);
|
|
7600
8368
|
return BigInt("0x" + hex);
|
|
@@ -7696,7 +8464,7 @@ function registerWhales(parent, getOpts) {
|
|
|
7696
8464
|
for (const { pool } of lendingPools) {
|
|
7697
8465
|
calls.push([
|
|
7698
8466
|
pool,
|
|
7699
|
-
|
|
8467
|
+
encodeFunctionData28({ abi: POOL_ABI6, functionName: "getUserAccountData", args: [whale.address] })
|
|
7700
8468
|
]);
|
|
7701
8469
|
}
|
|
7702
8470
|
}
|
|
@@ -7719,9 +8487,9 @@ function registerWhales(parent, getOpts) {
|
|
|
7719
8487
|
if (data && data.length >= 2 + 192 * 2) {
|
|
7720
8488
|
const dec = iface === "aave_v2" ? 18 : 8;
|
|
7721
8489
|
const divisor = 10 ** dec;
|
|
7722
|
-
const collateral = Number(
|
|
7723
|
-
const debt = Number(
|
|
7724
|
-
const hfRaw =
|
|
8490
|
+
const collateral = Number(decodeU2564(data, 0)) / divisor;
|
|
8491
|
+
const debt = Number(decodeU2564(data, 1)) / divisor;
|
|
8492
|
+
const hfRaw = decodeU2564(data, 5);
|
|
7725
8493
|
let hf = null;
|
|
7726
8494
|
if (hfRaw <= BigInt("0xffffffffffffffffffffffffffffffff")) {
|
|
7727
8495
|
const v = Number(hfRaw) / 1e18;
|
|
@@ -8124,11 +8892,11 @@ function registerBridge(parent, getOpts) {
|
|
|
8124
8892
|
const amountUsdc = Number(BigInt(opts.amount)) / 1e6;
|
|
8125
8893
|
const { fee, maxFeeSubunits } = await getCctpFeeEstimate(srcDomain, dstDomain, amountUsdc);
|
|
8126
8894
|
const recipientPadded = `0x${"0".repeat(24)}${recipient.replace("0x", "").toLowerCase()}`;
|
|
8127
|
-
const { encodeFunctionData:
|
|
8128
|
-
const tokenMessengerAbi =
|
|
8895
|
+
const { encodeFunctionData: encodeFunctionData29, parseAbi: parseAbi33 } = await import("viem");
|
|
8896
|
+
const tokenMessengerAbi = parseAbi33([
|
|
8129
8897
|
"function depositForBurn(uint256 amount, uint32 destinationDomain, bytes32 mintRecipient, address burnToken, bytes32 destinationCaller, uint256 maxFee, uint32 minFinalityThreshold) external returns (uint64 nonce)"
|
|
8130
8898
|
]);
|
|
8131
|
-
const data =
|
|
8899
|
+
const data = encodeFunctionData29({
|
|
8132
8900
|
abi: tokenMessengerAbi,
|
|
8133
8901
|
functionName: "depositForBurn",
|
|
8134
8902
|
args: [
|
|
@@ -8465,6 +9233,107 @@ function registerSetup(program2) {
|
|
|
8465
9233
|
});
|
|
8466
9234
|
}
|
|
8467
9235
|
|
|
9236
|
+
// src/commands/lb.ts
|
|
9237
|
+
function registerLB(parent, getOpts, makeExecutor2) {
|
|
9238
|
+
const lb = parent.command("lb").description("Merchant Moe Liquidity Book: add/remove liquidity, rewards, positions");
|
|
9239
|
+
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) => {
|
|
9240
|
+
const executor = makeExecutor2();
|
|
9241
|
+
const registry = Registry.loadEmbedded();
|
|
9242
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9243
|
+
const chainName = parent.opts().chain;
|
|
9244
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9245
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9246
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9247
|
+
const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
|
|
9248
|
+
const tx = await adapter.buildAddLiquidity({
|
|
9249
|
+
pool: opts.pool,
|
|
9250
|
+
tokenX: opts.tokenX,
|
|
9251
|
+
tokenY: opts.tokenY,
|
|
9252
|
+
binStep: parseInt(opts.binStep),
|
|
9253
|
+
amountX: BigInt(opts.amountX),
|
|
9254
|
+
amountY: BigInt(opts.amountY),
|
|
9255
|
+
numBins: parseInt(opts.bins),
|
|
9256
|
+
activeIdDesired: opts.activeId ? parseInt(opts.activeId) : void 0,
|
|
9257
|
+
recipient
|
|
9258
|
+
});
|
|
9259
|
+
const result = await executor.execute(tx);
|
|
9260
|
+
printOutput(result, getOpts());
|
|
9261
|
+
});
|
|
9262
|
+
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) => {
|
|
9263
|
+
const executor = makeExecutor2();
|
|
9264
|
+
const registry = Registry.loadEmbedded();
|
|
9265
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9266
|
+
const adapter = createMerchantMoeLB(protocol);
|
|
9267
|
+
const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
|
|
9268
|
+
const binIds = opts.bins.split(",").map((s) => parseInt(s.trim()));
|
|
9269
|
+
const amounts = opts.amounts.split(",").map((s) => BigInt(s.trim()));
|
|
9270
|
+
const tx = await adapter.buildRemoveLiquidity({
|
|
9271
|
+
tokenX: opts.tokenX,
|
|
9272
|
+
tokenY: opts.tokenY,
|
|
9273
|
+
binStep: parseInt(opts.binStep),
|
|
9274
|
+
binIds,
|
|
9275
|
+
amounts,
|
|
9276
|
+
recipient
|
|
9277
|
+
});
|
|
9278
|
+
const result = await executor.execute(tx);
|
|
9279
|
+
printOutput(result, getOpts());
|
|
9280
|
+
});
|
|
9281
|
+
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) => {
|
|
9282
|
+
const registry = Registry.loadEmbedded();
|
|
9283
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9284
|
+
const chainName = parent.opts().chain;
|
|
9285
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9286
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9287
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9288
|
+
const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
|
|
9289
|
+
if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
|
|
9290
|
+
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
9291
|
+
const rewards = await adapter.getPendingRewards(user, opts.pool, binIds);
|
|
9292
|
+
printOutput(rewards, getOpts());
|
|
9293
|
+
});
|
|
9294
|
+
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) => {
|
|
9295
|
+
const executor = makeExecutor2();
|
|
9296
|
+
const registry = Registry.loadEmbedded();
|
|
9297
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9298
|
+
const chainName = parent.opts().chain;
|
|
9299
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9300
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9301
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9302
|
+
const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
|
|
9303
|
+
if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
|
|
9304
|
+
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
9305
|
+
const tx = await adapter.buildClaimRewards(user, opts.pool, binIds);
|
|
9306
|
+
const result = await executor.execute(tx);
|
|
9307
|
+
printOutput(result, getOpts());
|
|
9308
|
+
});
|
|
9309
|
+
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) => {
|
|
9310
|
+
const registry = Registry.loadEmbedded();
|
|
9311
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9312
|
+
const chainName = parent.opts().chain;
|
|
9313
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9314
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9315
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9316
|
+
let pools = await adapter.discoverRewardedPools();
|
|
9317
|
+
if (opts.activeOnly) {
|
|
9318
|
+
pools = pools.filter((p) => !p.stopped);
|
|
9319
|
+
}
|
|
9320
|
+
printOutput(pools, getOpts());
|
|
9321
|
+
});
|
|
9322
|
+
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) => {
|
|
9323
|
+
const registry = Registry.loadEmbedded();
|
|
9324
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9325
|
+
const chainName = parent.opts().chain;
|
|
9326
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9327
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9328
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9329
|
+
const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
|
|
9330
|
+
if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
|
|
9331
|
+
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
9332
|
+
const positions = await adapter.getUserPositions(user, opts.pool, binIds);
|
|
9333
|
+
printOutput(positions, getOpts());
|
|
9334
|
+
});
|
|
9335
|
+
}
|
|
9336
|
+
|
|
8468
9337
|
// src/cli.ts
|
|
8469
9338
|
var _require = createRequire(import.meta.url);
|
|
8470
9339
|
var _pkg = _require("../package.json");
|
|
@@ -8476,7 +9345,7 @@ var BANNER = `
|
|
|
8476
9345
|
\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
|
|
8477
9346
|
\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
|
|
8478
9347
|
|
|
8479
|
-
2 chains \xB7
|
|
9348
|
+
2 chains \xB7 30 protocols \xB7 by HypurrQuant
|
|
8480
9349
|
|
|
8481
9350
|
Scan exploits, swap tokens, bridge assets, track whales,
|
|
8482
9351
|
compare yields \u2014 all from your terminal.
|
|
@@ -8516,6 +9385,7 @@ registerSwap(program, getOutputMode, makeExecutor);
|
|
|
8516
9385
|
registerBridge(program, getOutputMode);
|
|
8517
9386
|
registerNft(program, getOutputMode);
|
|
8518
9387
|
registerFarm(program, getOutputMode, makeExecutor);
|
|
9388
|
+
registerLB(program, getOutputMode, makeExecutor);
|
|
8519
9389
|
registerSetup(program);
|
|
8520
9390
|
program.command("agent").description("Agent mode: read JSON commands from stdin (for AI agents)").action(async () => {
|
|
8521
9391
|
const executor = makeExecutor();
|