@hypurrquant/defi-cli 0.2.4 → 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/config/tokens/hyperevm.toml +1 -1
- package/dist/index.js +1335 -363
- package/dist/index.js.map +1 -1
- package/dist/main.js +1321 -352
- package/dist/main.js.map +1 -1
- package/dist/mcp-server.js +1160 -299
- package/dist/mcp-server.js.map +1 -1
- package/package.json +1 -1
- package/config/protocols/liquid_staking/kinetiq.toml +0 -12
- package/config/protocols/liquid_staking/sthype.toml +0 -13
package/dist/main.js
CHANGED
|
@@ -9,7 +9,7 @@ import { Command } from "commander";
|
|
|
9
9
|
import { createRequire } from "module";
|
|
10
10
|
|
|
11
11
|
// src/executor.ts
|
|
12
|
-
import { createPublicClient as createPublicClient2, createWalletClient, http as http2 } from "viem";
|
|
12
|
+
import { createPublicClient as createPublicClient2, createWalletClient, http as http2, parseAbi as parseAbi3, encodeFunctionData as encodeFunctionData3 } from "viem";
|
|
13
13
|
import { privateKeyToAccount } from "viem/accounts";
|
|
14
14
|
|
|
15
15
|
// ../defi-core/dist/index.js
|
|
@@ -707,6 +707,16 @@ function parse(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
|
|
|
707
707
|
|
|
708
708
|
// ../defi-core/dist/index.js
|
|
709
709
|
import { existsSync } from "fs";
|
|
710
|
+
var TxStatus = /* @__PURE__ */ ((TxStatus2) => {
|
|
711
|
+
TxStatus2["DryRun"] = "dry_run";
|
|
712
|
+
TxStatus2["Simulated"] = "simulated";
|
|
713
|
+
TxStatus2["SimulationFailed"] = "simulation_failed";
|
|
714
|
+
TxStatus2["NeedsApproval"] = "needs_approval";
|
|
715
|
+
TxStatus2["Pending"] = "pending";
|
|
716
|
+
TxStatus2["Confirmed"] = "confirmed";
|
|
717
|
+
TxStatus2["Failed"] = "failed";
|
|
718
|
+
return TxStatus2;
|
|
719
|
+
})(TxStatus || {});
|
|
710
720
|
var InterestRateMode = /* @__PURE__ */ ((InterestRateMode2) => {
|
|
711
721
|
InterestRateMode2["Variable"] = "variable";
|
|
712
722
|
InterestRateMode2["Stable"] = "stable";
|
|
@@ -1016,8 +1026,13 @@ var Registry = class _Registry {
|
|
|
1016
1026
|
};
|
|
1017
1027
|
|
|
1018
1028
|
// src/executor.ts
|
|
1029
|
+
var ERC20_ABI = parseAbi3([
|
|
1030
|
+
"function allowance(address owner, address spender) external view returns (uint256)",
|
|
1031
|
+
"function approve(address spender, uint256 amount) external returns (bool)"
|
|
1032
|
+
]);
|
|
1019
1033
|
var GAS_BUFFER_BPS = 12000n;
|
|
1020
|
-
var DEFAULT_PRIORITY_FEE_WEI =
|
|
1034
|
+
var DEFAULT_PRIORITY_FEE_WEI = 20000000000n;
|
|
1035
|
+
var MAX_GAS_LIMIT = 5000000000n;
|
|
1021
1036
|
var Executor = class _Executor {
|
|
1022
1037
|
dryRun;
|
|
1023
1038
|
rpcUrl;
|
|
@@ -1031,6 +1046,62 @@ var Executor = class _Executor {
|
|
|
1031
1046
|
static applyGasBuffer(gas) {
|
|
1032
1047
|
return gas * GAS_BUFFER_BPS / 10000n;
|
|
1033
1048
|
}
|
|
1049
|
+
/**
|
|
1050
|
+
* Check allowance for a single token/spender pair and send an approve tx if needed.
|
|
1051
|
+
* Only called in broadcast mode (not dry-run).
|
|
1052
|
+
*/
|
|
1053
|
+
async checkAndApprove(token, spender, amount, owner, publicClient, walletClient) {
|
|
1054
|
+
const allowance = await publicClient.readContract({
|
|
1055
|
+
address: token,
|
|
1056
|
+
abi: ERC20_ABI,
|
|
1057
|
+
functionName: "allowance",
|
|
1058
|
+
args: [owner, spender]
|
|
1059
|
+
});
|
|
1060
|
+
if (allowance >= amount) return;
|
|
1061
|
+
process.stderr.write(
|
|
1062
|
+
` Approving ${amount} of ${token} for ${spender}...
|
|
1063
|
+
`
|
|
1064
|
+
);
|
|
1065
|
+
const approveData = encodeFunctionData3({
|
|
1066
|
+
abi: ERC20_ABI,
|
|
1067
|
+
functionName: "approve",
|
|
1068
|
+
args: [spender, amount]
|
|
1069
|
+
});
|
|
1070
|
+
const rpcUrl = this.rpcUrl;
|
|
1071
|
+
const gasLimit = await (async () => {
|
|
1072
|
+
try {
|
|
1073
|
+
const estimated = await publicClient.estimateGas({
|
|
1074
|
+
to: token,
|
|
1075
|
+
data: approveData,
|
|
1076
|
+
account: owner
|
|
1077
|
+
});
|
|
1078
|
+
const buffered = _Executor.applyGasBuffer(estimated);
|
|
1079
|
+
return buffered > MAX_GAS_LIMIT ? MAX_GAS_LIMIT : buffered;
|
|
1080
|
+
} catch {
|
|
1081
|
+
return 80000n;
|
|
1082
|
+
}
|
|
1083
|
+
})();
|
|
1084
|
+
const [maxFeePerGas, maxPriorityFeePerGas] = await this.fetchEip1559Fees(rpcUrl);
|
|
1085
|
+
const approveTxHash = await walletClient.sendTransaction({
|
|
1086
|
+
chain: null,
|
|
1087
|
+
account: walletClient.account,
|
|
1088
|
+
to: token,
|
|
1089
|
+
data: approveData,
|
|
1090
|
+
gas: gasLimit > 0n ? gasLimit : void 0,
|
|
1091
|
+
maxFeePerGas: maxFeePerGas > 0n ? maxFeePerGas : void 0,
|
|
1092
|
+
maxPriorityFeePerGas: maxPriorityFeePerGas > 0n ? maxPriorityFeePerGas : void 0
|
|
1093
|
+
});
|
|
1094
|
+
const approveTxUrl = this.explorerUrl ? `${this.explorerUrl}/tx/${approveTxHash}` : void 0;
|
|
1095
|
+
process.stderr.write(` Approve tx: ${approveTxHash}
|
|
1096
|
+
`);
|
|
1097
|
+
if (approveTxUrl) process.stderr.write(` Explorer: ${approveTxUrl}
|
|
1098
|
+
`);
|
|
1099
|
+
await publicClient.waitForTransactionReceipt({ hash: approveTxHash });
|
|
1100
|
+
process.stderr.write(
|
|
1101
|
+
` Approved ${amount} of ${token} for ${spender}
|
|
1102
|
+
`
|
|
1103
|
+
);
|
|
1104
|
+
}
|
|
1034
1105
|
/** Fetch EIP-1559 fee params from the network. Returns [maxFeePerGas, maxPriorityFeePerGas]. */
|
|
1035
1106
|
async fetchEip1559Fees(rpcUrl) {
|
|
1036
1107
|
try {
|
|
@@ -1057,7 +1128,10 @@ var Executor = class _Executor {
|
|
|
1057
1128
|
value: tx.value,
|
|
1058
1129
|
account: from
|
|
1059
1130
|
});
|
|
1060
|
-
if (estimated > 0n)
|
|
1131
|
+
if (estimated > 0n) {
|
|
1132
|
+
const buffered = _Executor.applyGasBuffer(estimated);
|
|
1133
|
+
return buffered > MAX_GAS_LIMIT ? MAX_GAS_LIMIT : buffered;
|
|
1134
|
+
}
|
|
1061
1135
|
} catch {
|
|
1062
1136
|
}
|
|
1063
1137
|
return tx.gas_estimate ? BigInt(tx.gas_estimate) : 0n;
|
|
@@ -1071,6 +1145,46 @@ var Executor = class _Executor {
|
|
|
1071
1145
|
const client = createPublicClient2({ transport: http2(rpcUrl) });
|
|
1072
1146
|
const privateKey = process.env["DEFI_PRIVATE_KEY"];
|
|
1073
1147
|
const from = privateKey ? privateKeyToAccount(privateKey).address : "0x0000000000000000000000000000000000000001";
|
|
1148
|
+
if (tx.approvals && tx.approvals.length > 0) {
|
|
1149
|
+
const pendingApprovals = [];
|
|
1150
|
+
for (const approval of tx.approvals) {
|
|
1151
|
+
try {
|
|
1152
|
+
const allowance = await client.readContract({
|
|
1153
|
+
address: approval.token,
|
|
1154
|
+
abi: ERC20_ABI,
|
|
1155
|
+
functionName: "allowance",
|
|
1156
|
+
args: [from, approval.spender]
|
|
1157
|
+
});
|
|
1158
|
+
if (allowance < approval.amount) {
|
|
1159
|
+
pendingApprovals.push({
|
|
1160
|
+
token: approval.token,
|
|
1161
|
+
spender: approval.spender,
|
|
1162
|
+
needed: approval.amount.toString(),
|
|
1163
|
+
current: allowance.toString()
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
} catch {
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
if (pendingApprovals.length > 0) {
|
|
1170
|
+
return {
|
|
1171
|
+
tx_hash: void 0,
|
|
1172
|
+
status: TxStatus.NeedsApproval,
|
|
1173
|
+
gas_used: tx.gas_estimate,
|
|
1174
|
+
description: tx.description,
|
|
1175
|
+
details: {
|
|
1176
|
+
to: tx.to,
|
|
1177
|
+
from,
|
|
1178
|
+
data: tx.data,
|
|
1179
|
+
value: tx.value.toString(),
|
|
1180
|
+
mode: "simulated",
|
|
1181
|
+
result: "needs_approval",
|
|
1182
|
+
pending_approvals: pendingApprovals,
|
|
1183
|
+
hint: "Use --broadcast to auto-approve and execute"
|
|
1184
|
+
}
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1074
1188
|
try {
|
|
1075
1189
|
await client.call({ to: tx.to, data: tx.data, value: tx.value, account: from });
|
|
1076
1190
|
const gasEstimate = await this.estimateGasWithBuffer(rpcUrl, tx, from);
|
|
@@ -1143,6 +1257,18 @@ var Executor = class _Executor {
|
|
|
1143
1257
|
}
|
|
1144
1258
|
const publicClient = createPublicClient2({ transport: http2(rpcUrl) });
|
|
1145
1259
|
const walletClient = createWalletClient({ account, transport: http2(rpcUrl) });
|
|
1260
|
+
if (tx.approvals && tx.approvals.length > 0) {
|
|
1261
|
+
for (const approval of tx.approvals) {
|
|
1262
|
+
await this.checkAndApprove(
|
|
1263
|
+
approval.token,
|
|
1264
|
+
approval.spender,
|
|
1265
|
+
approval.amount,
|
|
1266
|
+
account.address,
|
|
1267
|
+
publicClient,
|
|
1268
|
+
walletClient
|
|
1269
|
+
);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1146
1272
|
const gasLimit = await this.estimateGasWithBuffer(rpcUrl, tx, account.address);
|
|
1147
1273
|
const [maxFeePerGas, maxPriorityFeePerGas] = await this.fetchEip1559Fees(rpcUrl);
|
|
1148
1274
|
process.stderr.write(`Broadcasting transaction to ${rpcUrl}...
|
|
@@ -1719,45 +1845,52 @@ function registerSchema(parent, getOpts) {
|
|
|
1719
1845
|
}
|
|
1720
1846
|
|
|
1721
1847
|
// ../defi-protocols/dist/index.js
|
|
1722
|
-
import { encodeFunctionData as
|
|
1848
|
+
import { encodeFunctionData as encodeFunctionData4, parseAbi as parseAbi4, createPublicClient as createPublicClient4, http as http4, decodeAbiParameters } from "viem";
|
|
1723
1849
|
import { encodeFunctionData as encodeFunctionData22, parseAbi as parseAbi22, createPublicClient as createPublicClient22, http as http22, decodeFunctionResult as decodeFunctionResult2, decodeAbiParameters as decodeAbiParameters2 } from "viem";
|
|
1724
1850
|
import { encodeFunctionData as encodeFunctionData32, parseAbi as parseAbi32, createPublicClient as createPublicClient32, http as http32, decodeAbiParameters as decodeAbiParameters3, concatHex, zeroAddress } from "viem";
|
|
1725
|
-
import { encodeFunctionData as
|
|
1851
|
+
import { encodeFunctionData as encodeFunctionData42, parseAbi as parseAbi42, zeroAddress as zeroAddress2 } from "viem";
|
|
1726
1852
|
import { encodeFunctionData as encodeFunctionData5, parseAbi as parseAbi5 } from "viem";
|
|
1727
|
-
import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6,
|
|
1853
|
+
import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6, decodeAbiParameters as decodeAbiParameters4 } from "viem";
|
|
1728
1854
|
import { encodeFunctionData as encodeFunctionData7, parseAbi as parseAbi7, zeroAddress as zeroAddress3 } from "viem";
|
|
1729
|
-
import { createPublicClient as
|
|
1730
|
-
import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9, createPublicClient as
|
|
1731
|
-
import {
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
import { createPublicClient as
|
|
1739
|
-
import { createPublicClient as
|
|
1740
|
-
import { createPublicClient as
|
|
1741
|
-
import { parseAbi as
|
|
1742
|
-
import { createPublicClient as
|
|
1743
|
-
import { createPublicClient as
|
|
1744
|
-
import { parseAbi as
|
|
1855
|
+
import { createPublicClient as createPublicClient42, encodeFunctionData as encodeFunctionData8, http as http42, parseAbi as parseAbi8, zeroAddress as zeroAddress4 } from "viem";
|
|
1856
|
+
import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9, createPublicClient as createPublicClient5, http as http5 } from "viem";
|
|
1857
|
+
import {
|
|
1858
|
+
encodeFunctionData as encodeFunctionData10,
|
|
1859
|
+
decodeFunctionResult as decodeFunctionResult22,
|
|
1860
|
+
parseAbi as parseAbi10,
|
|
1861
|
+
createPublicClient as createPublicClient6,
|
|
1862
|
+
http as http6
|
|
1863
|
+
} from "viem";
|
|
1864
|
+
import { createPublicClient as createPublicClient7, http as http7, parseAbi as parseAbi11, encodeFunctionData as encodeFunctionData11, decodeFunctionResult as decodeFunctionResult3, zeroAddress as zeroAddress5 } from "viem";
|
|
1865
|
+
import { createPublicClient as createPublicClient8, http as http8, parseAbi as parseAbi12, encodeFunctionData as encodeFunctionData12, zeroAddress as zeroAddress6 } from "viem";
|
|
1866
|
+
import { createPublicClient as createPublicClient9, http as http9, parseAbi as parseAbi13 } from "viem";
|
|
1867
|
+
import { createPublicClient as createPublicClient10, http as http10, parseAbi as parseAbi14, encodeFunctionData as encodeFunctionData13 } from "viem";
|
|
1868
|
+
import { createPublicClient as createPublicClient11, http as http11, parseAbi as parseAbi15, encodeFunctionData as encodeFunctionData14 } from "viem";
|
|
1869
|
+
import { createPublicClient as createPublicClient12, http as http12, parseAbi as parseAbi16, encodeFunctionData as encodeFunctionData15 } from "viem";
|
|
1870
|
+
import { parseAbi as parseAbi17, encodeFunctionData as encodeFunctionData16, decodeFunctionResult as decodeFunctionResult4, zeroAddress as zeroAddress7 } from "viem";
|
|
1871
|
+
import { createPublicClient as createPublicClient13, http as http13, parseAbi as parseAbi18, encodeFunctionData as encodeFunctionData17, zeroAddress as zeroAddress8 } from "viem";
|
|
1872
|
+
import { createPublicClient as createPublicClient14, http as http14, parseAbi as parseAbi19 } from "viem";
|
|
1873
|
+
import { createPublicClient as createPublicClient15, http as http15, parseAbi as parseAbi20, encodeFunctionData as encodeFunctionData18 } from "viem";
|
|
1874
|
+
import { parseAbi as parseAbi21, encodeFunctionData as encodeFunctionData19 } from "viem";
|
|
1875
|
+
import { createPublicClient as createPublicClient16, http as http16, parseAbi as parseAbi222, encodeFunctionData as encodeFunctionData20, zeroAddress as zeroAddress9 } from "viem";
|
|
1876
|
+
import { createPublicClient as createPublicClient17, http as http17, parseAbi as parseAbi23, encodeFunctionData as encodeFunctionData21, zeroAddress as zeroAddress10 } from "viem";
|
|
1745
1877
|
import { parseAbi as parseAbi24, encodeFunctionData as encodeFunctionData222 } from "viem";
|
|
1746
|
-
import {
|
|
1878
|
+
import { parseAbi as parseAbi25, encodeFunctionData as encodeFunctionData23 } from "viem";
|
|
1879
|
+
import { createPublicClient as createPublicClient18, http as http18, parseAbi as parseAbi26 } from "viem";
|
|
1747
1880
|
var DEFAULT_FEE = 3e3;
|
|
1748
|
-
var swapRouterAbi =
|
|
1881
|
+
var swapRouterAbi = parseAbi4([
|
|
1749
1882
|
"struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; }",
|
|
1750
1883
|
"function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut)"
|
|
1751
1884
|
]);
|
|
1752
|
-
var quoterAbi =
|
|
1885
|
+
var quoterAbi = parseAbi4([
|
|
1753
1886
|
"struct QuoteExactInputSingleParams { address tokenIn; address tokenOut; uint256 amountIn; uint24 fee; uint160 sqrtPriceLimitX96; }",
|
|
1754
1887
|
"function quoteExactInputSingle(QuoteExactInputSingleParams memory params) external returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)"
|
|
1755
1888
|
]);
|
|
1756
|
-
var ramsesQuoterAbi =
|
|
1889
|
+
var ramsesQuoterAbi = parseAbi4([
|
|
1757
1890
|
"struct QuoteExactInputSingleParams { address tokenIn; address tokenOut; uint256 amountIn; int24 tickSpacing; uint160 sqrtPriceLimitX96; }",
|
|
1758
1891
|
"function quoteExactInputSingle(QuoteExactInputSingleParams memory params) external returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)"
|
|
1759
1892
|
]);
|
|
1760
|
-
var positionManagerAbi =
|
|
1893
|
+
var positionManagerAbi = parseAbi4([
|
|
1761
1894
|
"struct MintParams { address token0; address token1; uint24 fee; int24 tickLower; int24 tickUpper; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; address recipient; uint256 deadline; }",
|
|
1762
1895
|
"function mint(MintParams calldata params) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1)"
|
|
1763
1896
|
]);
|
|
@@ -1790,7 +1923,7 @@ var UniswapV3Adapter = class {
|
|
|
1790
1923
|
async buildSwap(params) {
|
|
1791
1924
|
const deadline = BigInt(params.deadline ?? 18446744073709551615n);
|
|
1792
1925
|
const amountOutMinimum = 0n;
|
|
1793
|
-
const data =
|
|
1926
|
+
const data = encodeFunctionData4({
|
|
1794
1927
|
abi: swapRouterAbi,
|
|
1795
1928
|
functionName: "exactInputSingle",
|
|
1796
1929
|
args: [
|
|
@@ -1811,7 +1944,8 @@ var UniswapV3Adapter = class {
|
|
|
1811
1944
|
to: this.router,
|
|
1812
1945
|
data,
|
|
1813
1946
|
value: 0n,
|
|
1814
|
-
gas_estimate: 2e5
|
|
1947
|
+
gas_estimate: 2e5,
|
|
1948
|
+
approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
|
|
1815
1949
|
};
|
|
1816
1950
|
}
|
|
1817
1951
|
async quote(params) {
|
|
@@ -1826,7 +1960,7 @@ var UniswapV3Adapter = class {
|
|
|
1826
1960
|
tickSpacings.map(async (ts) => {
|
|
1827
1961
|
const result = await client2.call({
|
|
1828
1962
|
to: this.quoter,
|
|
1829
|
-
data:
|
|
1963
|
+
data: encodeFunctionData4({
|
|
1830
1964
|
abi: ramsesQuoterAbi,
|
|
1831
1965
|
functionName: "quoteExactInputSingle",
|
|
1832
1966
|
args: [
|
|
@@ -1872,7 +2006,7 @@ var UniswapV3Adapter = class {
|
|
|
1872
2006
|
feeTiers.map(async (fee) => {
|
|
1873
2007
|
const result = await client2.call({
|
|
1874
2008
|
to: this.quoter,
|
|
1875
|
-
data:
|
|
2009
|
+
data: encodeFunctionData4({
|
|
1876
2010
|
abi: quoterAbi,
|
|
1877
2011
|
functionName: "quoteExactInputSingle",
|
|
1878
2012
|
args: [
|
|
@@ -1911,7 +2045,7 @@ var UniswapV3Adapter = class {
|
|
|
1911
2045
|
}
|
|
1912
2046
|
}
|
|
1913
2047
|
const client = createPublicClient4({ transport: http4(this.rpcUrl) });
|
|
1914
|
-
const callData =
|
|
2048
|
+
const callData = encodeFunctionData4({
|
|
1915
2049
|
abi: swapRouterAbi,
|
|
1916
2050
|
functionName: "exactInputSingle",
|
|
1917
2051
|
args: [
|
|
@@ -1957,7 +2091,7 @@ var UniswapV3Adapter = class {
|
|
|
1957
2091
|
const [token0, token1, rawAmount0, rawAmount1] = params.token_a.toLowerCase() < params.token_b.toLowerCase() ? [params.token_a, params.token_b, params.amount_a, params.amount_b] : [params.token_b, params.token_a, params.amount_b, params.amount_a];
|
|
1958
2092
|
const amount0 = rawAmount0 === 0n && rawAmount1 > 0n ? 1n : rawAmount0;
|
|
1959
2093
|
const amount1 = rawAmount1 === 0n && rawAmount0 > 0n ? 1n : rawAmount1;
|
|
1960
|
-
const data =
|
|
2094
|
+
const data = encodeFunctionData4({
|
|
1961
2095
|
abi: positionManagerAbi,
|
|
1962
2096
|
functionName: "mint",
|
|
1963
2097
|
args: [
|
|
@@ -1981,7 +2115,11 @@ var UniswapV3Adapter = class {
|
|
|
1981
2115
|
to: pm,
|
|
1982
2116
|
data,
|
|
1983
2117
|
value: 0n,
|
|
1984
|
-
gas_estimate: 5e5
|
|
2118
|
+
gas_estimate: 5e5,
|
|
2119
|
+
approvals: [
|
|
2120
|
+
{ token: token0, spender: pm, amount: amount0 },
|
|
2121
|
+
{ token: token1, spender: pm, amount: amount1 }
|
|
2122
|
+
]
|
|
1985
2123
|
};
|
|
1986
2124
|
}
|
|
1987
2125
|
async buildRemoveLiquidity(_params) {
|
|
@@ -2040,7 +2178,8 @@ var UniswapV2Adapter = class {
|
|
|
2040
2178
|
to: this.router,
|
|
2041
2179
|
data,
|
|
2042
2180
|
value: 0n,
|
|
2043
|
-
gas_estimate: 15e4
|
|
2181
|
+
gas_estimate: 15e4,
|
|
2182
|
+
approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
|
|
2044
2183
|
};
|
|
2045
2184
|
}
|
|
2046
2185
|
async quote(params) {
|
|
@@ -2159,7 +2298,11 @@ var UniswapV2Adapter = class {
|
|
|
2159
2298
|
to: this.router,
|
|
2160
2299
|
data,
|
|
2161
2300
|
value: 0n,
|
|
2162
|
-
gas_estimate: 3e5
|
|
2301
|
+
gas_estimate: 3e5,
|
|
2302
|
+
approvals: [
|
|
2303
|
+
{ token: params.token_a, spender: this.router, amount: params.amount_a },
|
|
2304
|
+
{ token: params.token_b, spender: this.router, amount: params.amount_b }
|
|
2305
|
+
]
|
|
2163
2306
|
};
|
|
2164
2307
|
}
|
|
2165
2308
|
async buildRemoveLiquidity(params) {
|
|
@@ -2246,7 +2389,8 @@ var AlgebraV3Adapter = class {
|
|
|
2246
2389
|
to: this.router,
|
|
2247
2390
|
data,
|
|
2248
2391
|
value: 0n,
|
|
2249
|
-
gas_estimate: 25e4
|
|
2392
|
+
gas_estimate: 25e4,
|
|
2393
|
+
approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
|
|
2250
2394
|
};
|
|
2251
2395
|
}
|
|
2252
2396
|
async quote(params) {
|
|
@@ -2364,7 +2508,11 @@ var AlgebraV3Adapter = class {
|
|
|
2364
2508
|
to: pm,
|
|
2365
2509
|
data,
|
|
2366
2510
|
value: 0n,
|
|
2367
|
-
gas_estimate: 5e5
|
|
2511
|
+
gas_estimate: 5e5,
|
|
2512
|
+
approvals: [
|
|
2513
|
+
{ token: token0, spender: pm, amount: amount0 },
|
|
2514
|
+
{ token: token1, spender: pm, amount: amount1 }
|
|
2515
|
+
]
|
|
2368
2516
|
};
|
|
2369
2517
|
}
|
|
2370
2518
|
async buildRemoveLiquidity(_params) {
|
|
@@ -2373,7 +2521,7 @@ var AlgebraV3Adapter = class {
|
|
|
2373
2521
|
);
|
|
2374
2522
|
}
|
|
2375
2523
|
};
|
|
2376
|
-
var abi3 =
|
|
2524
|
+
var abi3 = parseAbi42([
|
|
2377
2525
|
"function swapSingleTokenExactIn(address pool, address tokenIn, address tokenOut, uint256 exactAmountIn, uint256 minAmountOut, uint256 deadline, bool wethIsEth, bytes calldata userData) external returns (uint256 amountOut)"
|
|
2378
2526
|
]);
|
|
2379
2527
|
var BalancerV3Adapter = class {
|
|
@@ -2393,7 +2541,7 @@ var BalancerV3Adapter = class {
|
|
|
2393
2541
|
async buildSwap(params) {
|
|
2394
2542
|
const minAmountOut = 0n;
|
|
2395
2543
|
const deadline = BigInt(params.deadline ?? 18446744073709551615n);
|
|
2396
|
-
const data =
|
|
2544
|
+
const data = encodeFunctionData42({
|
|
2397
2545
|
abi: abi3,
|
|
2398
2546
|
functionName: "swapSingleTokenExactIn",
|
|
2399
2547
|
args: [
|
|
@@ -2541,18 +2689,10 @@ var SolidlyAdapter = class {
|
|
|
2541
2689
|
to: this.router,
|
|
2542
2690
|
data,
|
|
2543
2691
|
value: 0n,
|
|
2544
|
-
gas_estimate: 2e5
|
|
2692
|
+
gas_estimate: 2e5,
|
|
2693
|
+
approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
|
|
2545
2694
|
};
|
|
2546
2695
|
}
|
|
2547
|
-
async callGetAmountsOut(client, callData) {
|
|
2548
|
-
const result = await client.call({ to: this.router, data: callData });
|
|
2549
|
-
if (!result.data) return 0n;
|
|
2550
|
-
const [amounts] = decodeAbiParameters4(
|
|
2551
|
-
[{ name: "amounts", type: "uint256[]" }],
|
|
2552
|
-
result.data
|
|
2553
|
-
);
|
|
2554
|
-
return amounts.length >= 2 ? amounts[amounts.length - 1] : 0n;
|
|
2555
|
-
}
|
|
2556
2696
|
encodeV1(params, stable) {
|
|
2557
2697
|
return encodeFunctionData6({
|
|
2558
2698
|
abi: abi4,
|
|
@@ -2569,7 +2709,6 @@ var SolidlyAdapter = class {
|
|
|
2569
2709
|
}
|
|
2570
2710
|
async quote(params) {
|
|
2571
2711
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
2572
|
-
const client = createPublicClient42({ transport: http42(this.rpcUrl) });
|
|
2573
2712
|
const candidates = [
|
|
2574
2713
|
{ callData: this.encodeV1(params, false), stable: false },
|
|
2575
2714
|
{ callData: this.encodeV1(params, true), stable: true }
|
|
@@ -2580,16 +2719,26 @@ var SolidlyAdapter = class {
|
|
|
2580
2719
|
{ callData: this.encodeV2(params, true), stable: true }
|
|
2581
2720
|
);
|
|
2582
2721
|
}
|
|
2583
|
-
const
|
|
2584
|
-
|
|
2722
|
+
const rawResults = await multicallRead(
|
|
2723
|
+
this.rpcUrl,
|
|
2724
|
+
candidates.map((c) => [this.router, c.callData])
|
|
2585
2725
|
);
|
|
2586
2726
|
let bestOut = 0n;
|
|
2587
2727
|
let bestStable = false;
|
|
2588
|
-
for (let i = 0; i <
|
|
2589
|
-
const
|
|
2590
|
-
if (
|
|
2591
|
-
|
|
2592
|
-
|
|
2728
|
+
for (let i = 0; i < rawResults.length; i++) {
|
|
2729
|
+
const raw = rawResults[i];
|
|
2730
|
+
if (!raw) continue;
|
|
2731
|
+
try {
|
|
2732
|
+
const [amounts] = decodeAbiParameters4(
|
|
2733
|
+
[{ name: "amounts", type: "uint256[]" }],
|
|
2734
|
+
raw
|
|
2735
|
+
);
|
|
2736
|
+
const out = amounts.length >= 2 ? amounts[amounts.length - 1] : 0n;
|
|
2737
|
+
if (out > bestOut) {
|
|
2738
|
+
bestOut = out;
|
|
2739
|
+
bestStable = candidates[i].stable;
|
|
2740
|
+
}
|
|
2741
|
+
} catch {
|
|
2593
2742
|
}
|
|
2594
2743
|
}
|
|
2595
2744
|
if (bestOut === 0n) {
|
|
@@ -2624,7 +2773,11 @@ var SolidlyAdapter = class {
|
|
|
2624
2773
|
to: this.router,
|
|
2625
2774
|
data,
|
|
2626
2775
|
value: 0n,
|
|
2627
|
-
gas_estimate: 35e4
|
|
2776
|
+
gas_estimate: 35e4,
|
|
2777
|
+
approvals: [
|
|
2778
|
+
{ token: params.token_a, spender: this.router, amount: params.amount_a },
|
|
2779
|
+
{ token: params.token_b, spender: this.router, amount: params.amount_b }
|
|
2780
|
+
]
|
|
2628
2781
|
};
|
|
2629
2782
|
}
|
|
2630
2783
|
async buildRemoveLiquidity(params) {
|
|
@@ -2750,7 +2903,7 @@ var SolidlyGaugeAdapter = class {
|
|
|
2750
2903
|
return this.protocolName;
|
|
2751
2904
|
}
|
|
2752
2905
|
// IGauge
|
|
2753
|
-
async buildDeposit(gauge, amount, tokenId) {
|
|
2906
|
+
async buildDeposit(gauge, amount, tokenId, lpToken) {
|
|
2754
2907
|
if (tokenId !== void 0) {
|
|
2755
2908
|
const data2 = encodeFunctionData8({
|
|
2756
2909
|
abi: gaugeAbi,
|
|
@@ -2762,7 +2915,8 @@ var SolidlyGaugeAdapter = class {
|
|
|
2762
2915
|
to: gauge,
|
|
2763
2916
|
data: data2,
|
|
2764
2917
|
value: 0n,
|
|
2765
|
-
gas_estimate: 2e5
|
|
2918
|
+
gas_estimate: 2e5,
|
|
2919
|
+
approvals: lpToken ? [{ token: lpToken, spender: gauge, amount }] : void 0
|
|
2766
2920
|
};
|
|
2767
2921
|
}
|
|
2768
2922
|
const data = encodeFunctionData8({
|
|
@@ -2775,7 +2929,8 @@ var SolidlyGaugeAdapter = class {
|
|
|
2775
2929
|
to: gauge,
|
|
2776
2930
|
data,
|
|
2777
2931
|
value: 0n,
|
|
2778
|
-
gas_estimate: 2e5
|
|
2932
|
+
gas_estimate: 2e5,
|
|
2933
|
+
approvals: lpToken ? [{ token: lpToken, spender: gauge, amount }] : void 0
|
|
2779
2934
|
};
|
|
2780
2935
|
}
|
|
2781
2936
|
async buildWithdraw(gauge, amount) {
|
|
@@ -2795,7 +2950,7 @@ var SolidlyGaugeAdapter = class {
|
|
|
2795
2950
|
async buildClaimRewards(gauge, account) {
|
|
2796
2951
|
if (account && this.rpcUrl) {
|
|
2797
2952
|
try {
|
|
2798
|
-
const client =
|
|
2953
|
+
const client = createPublicClient42({ transport: http42(this.rpcUrl) });
|
|
2799
2954
|
const listLen = await client.readContract({
|
|
2800
2955
|
address: gauge,
|
|
2801
2956
|
abi: gaugeAbi,
|
|
@@ -3053,7 +3208,7 @@ var MasterChefAdapter = class {
|
|
|
3053
3208
|
if (!this.rpcUrl) {
|
|
3054
3209
|
throw DefiError.unsupported(`[${this.protocolName}] getPendingRewards requires RPC`);
|
|
3055
3210
|
}
|
|
3056
|
-
const client =
|
|
3211
|
+
const client = createPublicClient5({ transport: http5(this.rpcUrl) });
|
|
3057
3212
|
const rewards = await client.readContract({
|
|
3058
3213
|
address: this.masterchef,
|
|
3059
3214
|
abi: masterchefAbi,
|
|
@@ -3067,7 +3222,682 @@ var MasterChefAdapter = class {
|
|
|
3067
3222
|
}));
|
|
3068
3223
|
}
|
|
3069
3224
|
};
|
|
3070
|
-
var
|
|
3225
|
+
var lbRouterAbi = parseAbi10([
|
|
3226
|
+
"struct LiquidityParameters { address tokenX; address tokenY; uint256 binStep; uint256 amountX; uint256 amountY; uint256 amountXMin; uint256 amountYMin; uint256 activeIdDesired; uint256 idSlippage; int256[] deltaIds; uint256[] distributionX; uint256[] distributionY; address to; address refundTo; uint256 deadline; }",
|
|
3227
|
+
"function addLiquidity(LiquidityParameters calldata liquidityParameters) external returns (uint256 amountXAdded, uint256 amountYAdded, uint256 amountXLeft, uint256 amountYLeft, uint256[] memory depositIds, uint256[] memory liquidityMinted)",
|
|
3228
|
+
"function removeLiquidity(address tokenX, address tokenY, uint16 binStep, uint256 amountXMin, uint256 amountYMin, uint256[] memory ids, uint256[] memory amounts, address to, uint256 deadline) external returns (uint256 amountX, uint256 amountY)"
|
|
3229
|
+
]);
|
|
3230
|
+
var lbFactoryAbi = parseAbi10([
|
|
3231
|
+
"function getNumberOfLBPairs() external view returns (uint256)",
|
|
3232
|
+
"function getLBPairAtIndex(uint256 index) external view returns (address)"
|
|
3233
|
+
]);
|
|
3234
|
+
var lbPairAbi = parseAbi10([
|
|
3235
|
+
"function getLBHooksParameters() external view returns (bytes32)",
|
|
3236
|
+
"function getActiveId() external view returns (uint24)",
|
|
3237
|
+
"function getBinStep() external view returns (uint16)",
|
|
3238
|
+
"function getTokenX() external view returns (address)",
|
|
3239
|
+
"function getTokenY() external view returns (address)",
|
|
3240
|
+
"function balanceOf(address account, uint256 id) external view returns (uint256)",
|
|
3241
|
+
"function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory)"
|
|
3242
|
+
]);
|
|
3243
|
+
var lbRewarderAbi = parseAbi10([
|
|
3244
|
+
"function getRewardToken() external view returns (address)",
|
|
3245
|
+
"function getRewardedRange() external view returns (uint256 minBinId, uint256 maxBinId)",
|
|
3246
|
+
"function getPendingRewards(address user, uint256[] calldata ids) external view returns (uint256 pendingRewards)",
|
|
3247
|
+
"function claim(address user, uint256[] calldata ids) external",
|
|
3248
|
+
"function getPid() external view returns (uint256)",
|
|
3249
|
+
"function isStopped() external view returns (bool)",
|
|
3250
|
+
"function getLBPair() external view returns (address)",
|
|
3251
|
+
"function getMasterChef() external view returns (address)"
|
|
3252
|
+
]);
|
|
3253
|
+
var masterChefAbi = parseAbi10([
|
|
3254
|
+
"function getMoePerSecond() external view returns (uint256)",
|
|
3255
|
+
"function getTreasuryShare() external view returns (uint256)",
|
|
3256
|
+
"function getStaticShare() external view returns (uint256)",
|
|
3257
|
+
"function getVeMoe() external view returns (address)"
|
|
3258
|
+
]);
|
|
3259
|
+
var veMoeAbi = parseAbi10([
|
|
3260
|
+
"function getWeight(uint256 pid) external view returns (uint256)",
|
|
3261
|
+
"function getTotalWeight() external view returns (uint256)",
|
|
3262
|
+
"function getTopPoolIds() external view returns (uint256[] memory)"
|
|
3263
|
+
]);
|
|
3264
|
+
var lbPairBinAbi = parseAbi10([
|
|
3265
|
+
"function getBin(uint24 id) external view returns (uint128 reserveX, uint128 reserveY)",
|
|
3266
|
+
"function getActiveId() external view returns (uint24)"
|
|
3267
|
+
]);
|
|
3268
|
+
var lbQuoterAbi2 = parseAbi10([
|
|
3269
|
+
"function findBestPathFromAmountIn(address[] calldata route, uint128 amountIn) external view returns ((address[] route, address[] pairs, uint256[] binSteps, uint256[] versions, uint128[] amounts, uint128[] virtualAmountsWithoutSlippage, uint128[] fees))"
|
|
3270
|
+
]);
|
|
3271
|
+
var erc20Abi2 = parseAbi10([
|
|
3272
|
+
"function symbol() external view returns (string)"
|
|
3273
|
+
]);
|
|
3274
|
+
var _addressAbi = parseAbi10(["function f() external view returns (address)"]);
|
|
3275
|
+
function decodeAddressResult(data) {
|
|
3276
|
+
if (!data) return null;
|
|
3277
|
+
try {
|
|
3278
|
+
return decodeFunctionResult22({ abi: _addressAbi, functionName: "f", data });
|
|
3279
|
+
} catch {
|
|
3280
|
+
return null;
|
|
3281
|
+
}
|
|
3282
|
+
}
|
|
3283
|
+
var _uint256Abi = parseAbi10(["function f() external view returns (uint256)"]);
|
|
3284
|
+
function decodeUint256Result(data) {
|
|
3285
|
+
if (!data) return null;
|
|
3286
|
+
try {
|
|
3287
|
+
return decodeFunctionResult22({ abi: _uint256Abi, functionName: "f", data });
|
|
3288
|
+
} catch {
|
|
3289
|
+
return null;
|
|
3290
|
+
}
|
|
3291
|
+
}
|
|
3292
|
+
var _boolAbi = parseAbi10(["function f() external view returns (bool)"]);
|
|
3293
|
+
function decodeBoolResult(data) {
|
|
3294
|
+
if (!data) return null;
|
|
3295
|
+
try {
|
|
3296
|
+
return decodeFunctionResult22({ abi: _boolAbi, functionName: "f", data });
|
|
3297
|
+
} catch {
|
|
3298
|
+
return null;
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
function decodeStringResult(data) {
|
|
3302
|
+
if (!data) return "?";
|
|
3303
|
+
try {
|
|
3304
|
+
return decodeFunctionResult22({ abi: erc20Abi2, functionName: "symbol", data });
|
|
3305
|
+
} catch {
|
|
3306
|
+
return "?";
|
|
3307
|
+
}
|
|
3308
|
+
}
|
|
3309
|
+
var _rangeAbi = parseAbi10(["function f() external view returns (uint256 minBinId, uint256 maxBinId)"]);
|
|
3310
|
+
function decodeRangeResult(data) {
|
|
3311
|
+
if (!data) return null;
|
|
3312
|
+
try {
|
|
3313
|
+
return decodeFunctionResult22({ abi: _rangeAbi, functionName: "f", data });
|
|
3314
|
+
} catch {
|
|
3315
|
+
return null;
|
|
3316
|
+
}
|
|
3317
|
+
}
|
|
3318
|
+
var _binAbi = parseAbi10(["function f() external view returns (uint128 reserveX, uint128 reserveY)"]);
|
|
3319
|
+
function decodeBinResult(data) {
|
|
3320
|
+
if (!data) return null;
|
|
3321
|
+
try {
|
|
3322
|
+
return decodeFunctionResult22({ abi: _binAbi, functionName: "f", data });
|
|
3323
|
+
} catch {
|
|
3324
|
+
return null;
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3327
|
+
var _uint256ArrayAbi = parseAbi10(["function f() external view returns (uint256[] memory)"]);
|
|
3328
|
+
function decodeUint256ArrayResult(data) {
|
|
3329
|
+
if (!data) return null;
|
|
3330
|
+
try {
|
|
3331
|
+
return decodeFunctionResult22({ abi: _uint256ArrayAbi, functionName: "f", data });
|
|
3332
|
+
} catch {
|
|
3333
|
+
return null;
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
function extractRewarderAddress(hooksParams) {
|
|
3337
|
+
if (!hooksParams || hooksParams === "0x0000000000000000000000000000000000000000000000000000000000000000") {
|
|
3338
|
+
return null;
|
|
3339
|
+
}
|
|
3340
|
+
const hex = hooksParams.slice(2);
|
|
3341
|
+
if (hex.length < 64) return null;
|
|
3342
|
+
const addrHex = hex.slice(24, 64);
|
|
3343
|
+
if (addrHex === "0000000000000000000000000000000000000000") return null;
|
|
3344
|
+
return `0x${addrHex}`;
|
|
3345
|
+
}
|
|
3346
|
+
function buildUniformDistribution(deltaIds) {
|
|
3347
|
+
const PRECISION = 10n ** 18n;
|
|
3348
|
+
const n = deltaIds.length;
|
|
3349
|
+
const xBins = deltaIds.filter((d) => d >= 0).length;
|
|
3350
|
+
const yBins = deltaIds.filter((d) => d <= 0).length;
|
|
3351
|
+
const distributionX = [];
|
|
3352
|
+
const distributionY = [];
|
|
3353
|
+
for (const delta of deltaIds) {
|
|
3354
|
+
const xShare = delta >= 0 && xBins > 0 ? PRECISION / BigInt(xBins) : 0n;
|
|
3355
|
+
const yShare = delta <= 0 && yBins > 0 ? PRECISION / BigInt(yBins) : 0n;
|
|
3356
|
+
distributionX.push(xShare);
|
|
3357
|
+
distributionY.push(yShare);
|
|
3358
|
+
}
|
|
3359
|
+
const xSum = distributionX.reduce((a, b) => a + b, 0n);
|
|
3360
|
+
const ySum = distributionY.reduce((a, b) => a + b, 0n);
|
|
3361
|
+
if (xSum > 0n && xSum !== PRECISION) {
|
|
3362
|
+
const firstX = distributionX.findIndex((v) => v > 0n);
|
|
3363
|
+
if (firstX !== -1) distributionX[firstX] += PRECISION - xSum;
|
|
3364
|
+
}
|
|
3365
|
+
if (ySum > 0n && ySum !== PRECISION) {
|
|
3366
|
+
const firstY = distributionY.findIndex((v) => v > 0n);
|
|
3367
|
+
if (firstY !== -1) distributionY[firstY] += PRECISION - ySum;
|
|
3368
|
+
}
|
|
3369
|
+
return { distributionX, distributionY };
|
|
3370
|
+
}
|
|
3371
|
+
var MerchantMoeLBAdapter = class {
|
|
3372
|
+
protocolName;
|
|
3373
|
+
lbRouter;
|
|
3374
|
+
lbFactory;
|
|
3375
|
+
lbQuoter;
|
|
3376
|
+
rpcUrl;
|
|
3377
|
+
/** WMNT address (lb_mid_wmnt in config) used for MOE price routing */
|
|
3378
|
+
wmnt;
|
|
3379
|
+
/** USDT address (lb_mid_usdt in config) used for MNT/USD price routing */
|
|
3380
|
+
usdt;
|
|
3381
|
+
constructor(entry, rpcUrl) {
|
|
3382
|
+
this.protocolName = entry.name;
|
|
3383
|
+
const lbRouter = entry.contracts?.["lb_router"];
|
|
3384
|
+
if (!lbRouter) {
|
|
3385
|
+
throw new DefiError("CONTRACT_ERROR", "Missing 'lb_router' contract address");
|
|
3386
|
+
}
|
|
3387
|
+
const lbFactory = entry.contracts?.["lb_factory"];
|
|
3388
|
+
if (!lbFactory) {
|
|
3389
|
+
throw new DefiError("CONTRACT_ERROR", "Missing 'lb_factory' contract address");
|
|
3390
|
+
}
|
|
3391
|
+
this.lbRouter = lbRouter;
|
|
3392
|
+
this.lbFactory = lbFactory;
|
|
3393
|
+
this.lbQuoter = entry.contracts?.["lb_quoter"];
|
|
3394
|
+
this.wmnt = entry.contracts?.["lb_mid_wmnt"];
|
|
3395
|
+
this.usdt = entry.contracts?.["lb_mid_usdt"];
|
|
3396
|
+
this.rpcUrl = rpcUrl;
|
|
3397
|
+
}
|
|
3398
|
+
name() {
|
|
3399
|
+
return this.protocolName;
|
|
3400
|
+
}
|
|
3401
|
+
requireRpc() {
|
|
3402
|
+
if (!this.rpcUrl) {
|
|
3403
|
+
throw DefiError.rpcError(`[${this.protocolName}] RPC URL required`);
|
|
3404
|
+
}
|
|
3405
|
+
return this.rpcUrl;
|
|
3406
|
+
}
|
|
3407
|
+
/**
|
|
3408
|
+
* Build an addLiquidity transaction for a Liquidity Book pair.
|
|
3409
|
+
* Distributes tokenX/tokenY uniformly across active bin ± numBins.
|
|
3410
|
+
*/
|
|
3411
|
+
async buildAddLiquidity(params) {
|
|
3412
|
+
const numBins = params.numBins ?? 5;
|
|
3413
|
+
const deadline = params.deadline ?? BigInt("18446744073709551615");
|
|
3414
|
+
let activeIdDesired = params.activeIdDesired;
|
|
3415
|
+
if (activeIdDesired === void 0) {
|
|
3416
|
+
const rpcUrl = this.requireRpc();
|
|
3417
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3418
|
+
const activeId = await client.readContract({
|
|
3419
|
+
address: params.pool,
|
|
3420
|
+
abi: lbPairAbi,
|
|
3421
|
+
functionName: "getActiveId"
|
|
3422
|
+
});
|
|
3423
|
+
activeIdDesired = activeId;
|
|
3424
|
+
}
|
|
3425
|
+
const deltaIds = [];
|
|
3426
|
+
for (let d = -numBins; d <= numBins; d++) {
|
|
3427
|
+
deltaIds.push(d);
|
|
3428
|
+
}
|
|
3429
|
+
const { distributionX, distributionY } = buildUniformDistribution(deltaIds);
|
|
3430
|
+
const data = encodeFunctionData10({
|
|
3431
|
+
abi: lbRouterAbi,
|
|
3432
|
+
functionName: "addLiquidity",
|
|
3433
|
+
args: [
|
|
3434
|
+
{
|
|
3435
|
+
tokenX: params.tokenX,
|
|
3436
|
+
tokenY: params.tokenY,
|
|
3437
|
+
binStep: BigInt(params.binStep),
|
|
3438
|
+
amountX: params.amountX,
|
|
3439
|
+
amountY: params.amountY,
|
|
3440
|
+
amountXMin: 0n,
|
|
3441
|
+
amountYMin: 0n,
|
|
3442
|
+
activeIdDesired: BigInt(activeIdDesired),
|
|
3443
|
+
idSlippage: BigInt(numBins + 2),
|
|
3444
|
+
deltaIds: deltaIds.map(BigInt),
|
|
3445
|
+
distributionX,
|
|
3446
|
+
distributionY,
|
|
3447
|
+
to: params.recipient,
|
|
3448
|
+
refundTo: params.recipient,
|
|
3449
|
+
deadline
|
|
3450
|
+
}
|
|
3451
|
+
]
|
|
3452
|
+
});
|
|
3453
|
+
return {
|
|
3454
|
+
description: `[${this.protocolName}] LB addLiquidity ${params.amountX} tokenX + ${params.amountY} tokenY across ${deltaIds.length} bins`,
|
|
3455
|
+
to: this.lbRouter,
|
|
3456
|
+
data,
|
|
3457
|
+
value: 0n,
|
|
3458
|
+
gas_estimate: 8e5,
|
|
3459
|
+
approvals: [
|
|
3460
|
+
{ token: params.tokenX, spender: this.lbRouter, amount: params.amountX },
|
|
3461
|
+
{ token: params.tokenY, spender: this.lbRouter, amount: params.amountY }
|
|
3462
|
+
]
|
|
3463
|
+
};
|
|
3464
|
+
}
|
|
3465
|
+
/**
|
|
3466
|
+
* Build a removeLiquidity transaction for specific LB bins.
|
|
3467
|
+
*/
|
|
3468
|
+
async buildRemoveLiquidity(params) {
|
|
3469
|
+
const deadline = params.deadline ?? BigInt("18446744073709551615");
|
|
3470
|
+
const data = encodeFunctionData10({
|
|
3471
|
+
abi: lbRouterAbi,
|
|
3472
|
+
functionName: "removeLiquidity",
|
|
3473
|
+
args: [
|
|
3474
|
+
params.tokenX,
|
|
3475
|
+
params.tokenY,
|
|
3476
|
+
params.binStep,
|
|
3477
|
+
params.amountXMin ?? 0n,
|
|
3478
|
+
params.amountYMin ?? 0n,
|
|
3479
|
+
params.binIds.map(BigInt),
|
|
3480
|
+
params.amounts,
|
|
3481
|
+
params.recipient,
|
|
3482
|
+
deadline
|
|
3483
|
+
]
|
|
3484
|
+
});
|
|
3485
|
+
return {
|
|
3486
|
+
description: `[${this.protocolName}] LB removeLiquidity from ${params.binIds.length} bins`,
|
|
3487
|
+
to: this.lbRouter,
|
|
3488
|
+
data,
|
|
3489
|
+
value: 0n,
|
|
3490
|
+
gas_estimate: 6e5
|
|
3491
|
+
};
|
|
3492
|
+
}
|
|
3493
|
+
/**
|
|
3494
|
+
* Auto-detect bin IDs for a pool from the rewarder's rewarded range.
|
|
3495
|
+
* Falls back to active bin ± 50 scan if no rewarder exists.
|
|
3496
|
+
*/
|
|
3497
|
+
async autoDetectBins(pool) {
|
|
3498
|
+
const rpcUrl = this.requireRpc();
|
|
3499
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3500
|
+
const hooksParams = await client.readContract({
|
|
3501
|
+
address: pool,
|
|
3502
|
+
abi: lbPairAbi,
|
|
3503
|
+
functionName: "getLBHooksParameters"
|
|
3504
|
+
});
|
|
3505
|
+
const rewarder = extractRewarderAddress(hooksParams);
|
|
3506
|
+
if (rewarder) {
|
|
3507
|
+
const range = await client.readContract({
|
|
3508
|
+
address: rewarder,
|
|
3509
|
+
abi: lbRewarderAbi,
|
|
3510
|
+
functionName: "getRewardedRange"
|
|
3511
|
+
});
|
|
3512
|
+
const min = Number(range[0]);
|
|
3513
|
+
const max = Number(range[1]);
|
|
3514
|
+
const ids2 = [];
|
|
3515
|
+
for (let b = min; b <= max; b++) ids2.push(b);
|
|
3516
|
+
return ids2;
|
|
3517
|
+
}
|
|
3518
|
+
const activeId = await client.readContract({
|
|
3519
|
+
address: pool,
|
|
3520
|
+
abi: lbPairAbi,
|
|
3521
|
+
functionName: "getActiveId"
|
|
3522
|
+
});
|
|
3523
|
+
const ids = [];
|
|
3524
|
+
for (let b = activeId - 50; b <= activeId + 50; b++) ids.push(b);
|
|
3525
|
+
return ids;
|
|
3526
|
+
}
|
|
3527
|
+
/**
|
|
3528
|
+
* Get pending MOE rewards for a user across specified bin IDs.
|
|
3529
|
+
* If binIds is omitted, auto-detects from the rewarder's rewarded range.
|
|
3530
|
+
* Reads the rewarder address from the pool's hooks parameters.
|
|
3531
|
+
*/
|
|
3532
|
+
async getPendingRewards(user, pool, binIds) {
|
|
3533
|
+
const rpcUrl = this.requireRpc();
|
|
3534
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3535
|
+
const hooksParams = await client.readContract({
|
|
3536
|
+
address: pool,
|
|
3537
|
+
abi: lbPairAbi,
|
|
3538
|
+
functionName: "getLBHooksParameters"
|
|
3539
|
+
});
|
|
3540
|
+
const rewarder = extractRewarderAddress(hooksParams);
|
|
3541
|
+
if (!rewarder) {
|
|
3542
|
+
return [];
|
|
3543
|
+
}
|
|
3544
|
+
let resolvedBinIds = binIds;
|
|
3545
|
+
if (!resolvedBinIds || resolvedBinIds.length === 0) {
|
|
3546
|
+
const range = await client.readContract({
|
|
3547
|
+
address: rewarder,
|
|
3548
|
+
abi: lbRewarderAbi,
|
|
3549
|
+
functionName: "getRewardedRange"
|
|
3550
|
+
});
|
|
3551
|
+
const min = Number(range[0]);
|
|
3552
|
+
const max = Number(range[1]);
|
|
3553
|
+
resolvedBinIds = [];
|
|
3554
|
+
for (let b = min; b <= max; b++) resolvedBinIds.push(b);
|
|
3555
|
+
}
|
|
3556
|
+
const [pending, rewardToken] = await Promise.all([
|
|
3557
|
+
client.readContract({
|
|
3558
|
+
address: rewarder,
|
|
3559
|
+
abi: lbRewarderAbi,
|
|
3560
|
+
functionName: "getPendingRewards",
|
|
3561
|
+
args: [user, resolvedBinIds.map(BigInt)]
|
|
3562
|
+
}),
|
|
3563
|
+
client.readContract({
|
|
3564
|
+
address: rewarder,
|
|
3565
|
+
abi: lbRewarderAbi,
|
|
3566
|
+
functionName: "getRewardToken"
|
|
3567
|
+
})
|
|
3568
|
+
]);
|
|
3569
|
+
return [
|
|
3570
|
+
{
|
|
3571
|
+
token: rewardToken,
|
|
3572
|
+
symbol: "MOE",
|
|
3573
|
+
amount: pending
|
|
3574
|
+
}
|
|
3575
|
+
];
|
|
3576
|
+
}
|
|
3577
|
+
/**
|
|
3578
|
+
* Build a claim rewards transaction for specific LB bins.
|
|
3579
|
+
* If binIds is omitted, auto-detects from the rewarder's rewarded range.
|
|
3580
|
+
*/
|
|
3581
|
+
async buildClaimRewards(user, pool, binIds) {
|
|
3582
|
+
const rpcUrl = this.requireRpc();
|
|
3583
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3584
|
+
const hooksParams = await client.readContract({
|
|
3585
|
+
address: pool,
|
|
3586
|
+
abi: lbPairAbi,
|
|
3587
|
+
functionName: "getLBHooksParameters"
|
|
3588
|
+
});
|
|
3589
|
+
const rewarder = extractRewarderAddress(hooksParams);
|
|
3590
|
+
if (!rewarder) {
|
|
3591
|
+
throw new DefiError("CONTRACT_ERROR", `[${this.protocolName}] Pool ${pool} has no active rewarder`);
|
|
3592
|
+
}
|
|
3593
|
+
let resolvedBinIds = binIds;
|
|
3594
|
+
if (!resolvedBinIds || resolvedBinIds.length === 0) {
|
|
3595
|
+
const range = await client.readContract({
|
|
3596
|
+
address: rewarder,
|
|
3597
|
+
abi: lbRewarderAbi,
|
|
3598
|
+
functionName: "getRewardedRange"
|
|
3599
|
+
});
|
|
3600
|
+
const min = Number(range[0]);
|
|
3601
|
+
const max = Number(range[1]);
|
|
3602
|
+
resolvedBinIds = [];
|
|
3603
|
+
for (let b = min; b <= max; b++) resolvedBinIds.push(b);
|
|
3604
|
+
}
|
|
3605
|
+
const data = encodeFunctionData10({
|
|
3606
|
+
abi: lbRewarderAbi,
|
|
3607
|
+
functionName: "claim",
|
|
3608
|
+
args: [user, resolvedBinIds.map(BigInt)]
|
|
3609
|
+
});
|
|
3610
|
+
return {
|
|
3611
|
+
description: `[${this.protocolName}] LB claim rewards for ${resolvedBinIds.length} bins`,
|
|
3612
|
+
to: rewarder,
|
|
3613
|
+
data,
|
|
3614
|
+
value: 0n,
|
|
3615
|
+
gas_estimate: 3e5
|
|
3616
|
+
};
|
|
3617
|
+
}
|
|
3618
|
+
/**
|
|
3619
|
+
* Discover all active rewarded LB pools by iterating the factory.
|
|
3620
|
+
* Uses 7 multicall batches to minimise RPC round-trips and avoid 429s.
|
|
3621
|
+
*
|
|
3622
|
+
* Batch 1: getNumberOfLBPairs(), then getLBPairAtIndex(i) for all i
|
|
3623
|
+
* Batch 2: getLBHooksParameters() for all pairs → extract rewarder addresses
|
|
3624
|
+
* Batch 3: isStopped/getRewardedRange/getRewardToken/getPid/getMasterChef for each rewarder
|
|
3625
|
+
* Batch 4: getTokenX/getTokenY for each rewarded pair, then symbol() for unique tokens
|
|
3626
|
+
* Batch 5: Bootstrap MasterChef→VeMoe, then getMoePerSecond/getTreasuryShare/getStaticShare/getTotalWeight/getTopPoolIds
|
|
3627
|
+
* Batch 6: VeMoe.getWeight(pid) for each rewarded pool
|
|
3628
|
+
* Batch 7: Pool.getBin(binId) for all bins in rewarded range of each pool
|
|
3629
|
+
* Price: LB Quoter findBestPathFromAmountIn for MOE/WMNT and WMNT/USDT prices
|
|
3630
|
+
*/
|
|
3631
|
+
async discoverRewardedPools() {
|
|
3632
|
+
const rpcUrl = this.requireRpc();
|
|
3633
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3634
|
+
const pairCount = await client.readContract({
|
|
3635
|
+
address: this.lbFactory,
|
|
3636
|
+
abi: lbFactoryAbi,
|
|
3637
|
+
functionName: "getNumberOfLBPairs"
|
|
3638
|
+
});
|
|
3639
|
+
const count = Number(pairCount);
|
|
3640
|
+
if (count === 0) return [];
|
|
3641
|
+
const batch1Calls = Array.from({ length: count }, (_, i) => [
|
|
3642
|
+
this.lbFactory,
|
|
3643
|
+
encodeFunctionData10({ abi: lbFactoryAbi, functionName: "getLBPairAtIndex", args: [BigInt(i)] })
|
|
3644
|
+
]);
|
|
3645
|
+
const batch1Results = await multicallRead(rpcUrl, batch1Calls);
|
|
3646
|
+
const pairAddresses = batch1Results.map((r) => decodeAddressResult(r)).filter((a) => a !== null);
|
|
3647
|
+
if (pairAddresses.length === 0) return [];
|
|
3648
|
+
const batch2Calls = pairAddresses.map((pair) => [
|
|
3649
|
+
pair,
|
|
3650
|
+
encodeFunctionData10({ abi: lbPairAbi, functionName: "getLBHooksParameters" })
|
|
3651
|
+
]);
|
|
3652
|
+
const batch2Results = await multicallRead(rpcUrl, batch2Calls);
|
|
3653
|
+
const rewardedPairs = [];
|
|
3654
|
+
for (let i = 0; i < pairAddresses.length; i++) {
|
|
3655
|
+
const raw = batch2Results[i];
|
|
3656
|
+
if (!raw) continue;
|
|
3657
|
+
let hooksBytes;
|
|
3658
|
+
try {
|
|
3659
|
+
const _bytes32Abi = parseAbi10(["function f() external view returns (bytes32)"]);
|
|
3660
|
+
hooksBytes = decodeFunctionResult22({ abi: _bytes32Abi, functionName: "f", data: raw });
|
|
3661
|
+
} catch {
|
|
3662
|
+
continue;
|
|
3663
|
+
}
|
|
3664
|
+
const rewarder = extractRewarderAddress(hooksBytes);
|
|
3665
|
+
if (rewarder) {
|
|
3666
|
+
rewardedPairs.push({ pool: pairAddresses[i], rewarder });
|
|
3667
|
+
}
|
|
3668
|
+
}
|
|
3669
|
+
if (rewardedPairs.length === 0) return [];
|
|
3670
|
+
const batch3Calls = [];
|
|
3671
|
+
for (const { rewarder } of rewardedPairs) {
|
|
3672
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "isStopped" })]);
|
|
3673
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getRewardedRange" })]);
|
|
3674
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getRewardToken" })]);
|
|
3675
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getPid" })]);
|
|
3676
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getMasterChef" })]);
|
|
3677
|
+
}
|
|
3678
|
+
const batch3Results = await multicallRead(rpcUrl, batch3Calls);
|
|
3679
|
+
const batch4aCalls = [];
|
|
3680
|
+
for (const { pool } of rewardedPairs) {
|
|
3681
|
+
batch4aCalls.push([pool, encodeFunctionData10({ abi: lbPairAbi, functionName: "getTokenX" })]);
|
|
3682
|
+
batch4aCalls.push([pool, encodeFunctionData10({ abi: lbPairAbi, functionName: "getTokenY" })]);
|
|
3683
|
+
}
|
|
3684
|
+
const batch4aResults = await multicallRead(rpcUrl, batch4aCalls);
|
|
3685
|
+
const tokenXAddresses = [];
|
|
3686
|
+
const tokenYAddresses = [];
|
|
3687
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3688
|
+
tokenXAddresses.push(decodeAddressResult(batch4aResults[i * 2] ?? null));
|
|
3689
|
+
tokenYAddresses.push(decodeAddressResult(batch4aResults[i * 2 + 1] ?? null));
|
|
3690
|
+
}
|
|
3691
|
+
const uniqueTokens = Array.from(
|
|
3692
|
+
new Set([...tokenXAddresses, ...tokenYAddresses].filter((a) => a !== null))
|
|
3693
|
+
);
|
|
3694
|
+
const batch4bCalls = uniqueTokens.map((token) => [
|
|
3695
|
+
token,
|
|
3696
|
+
encodeFunctionData10({ abi: erc20Abi2, functionName: "symbol" })
|
|
3697
|
+
]);
|
|
3698
|
+
const batch4bResults = await multicallRead(rpcUrl, batch4bCalls);
|
|
3699
|
+
const symbolMap = /* @__PURE__ */ new Map();
|
|
3700
|
+
for (let i = 0; i < uniqueTokens.length; i++) {
|
|
3701
|
+
symbolMap.set(uniqueTokens[i], decodeStringResult(batch4bResults[i] ?? null));
|
|
3702
|
+
}
|
|
3703
|
+
const STRIDE3 = 5;
|
|
3704
|
+
const poolData = [];
|
|
3705
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3706
|
+
const base = i * STRIDE3;
|
|
3707
|
+
poolData.push({
|
|
3708
|
+
stopped: decodeBoolResult(batch3Results[base] ?? null) ?? false,
|
|
3709
|
+
range: decodeRangeResult(batch3Results[base + 1] ?? null),
|
|
3710
|
+
rewardToken: decodeAddressResult(batch3Results[base + 2] ?? null),
|
|
3711
|
+
pid: Number(decodeUint256Result(batch3Results[base + 3] ?? null) ?? 0n),
|
|
3712
|
+
masterChef: decodeAddressResult(batch3Results[base + 4] ?? null)
|
|
3713
|
+
});
|
|
3714
|
+
}
|
|
3715
|
+
const masterChefAddr = poolData.map((d) => d.masterChef).find((a) => a !== null) ?? null;
|
|
3716
|
+
let moePerDay = 0;
|
|
3717
|
+
let topPoolIds = /* @__PURE__ */ new Set();
|
|
3718
|
+
let totalWeightRaw = 0n;
|
|
3719
|
+
let veMoeAddr = null;
|
|
3720
|
+
if (masterChefAddr) {
|
|
3721
|
+
veMoeAddr = await client.readContract({
|
|
3722
|
+
address: masterChefAddr,
|
|
3723
|
+
abi: masterChefAbi,
|
|
3724
|
+
functionName: "getVeMoe"
|
|
3725
|
+
});
|
|
3726
|
+
const batch5Calls = [
|
|
3727
|
+
[masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getMoePerSecond" })],
|
|
3728
|
+
[masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getTreasuryShare" })],
|
|
3729
|
+
[masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getStaticShare" })],
|
|
3730
|
+
[veMoeAddr, encodeFunctionData10({ abi: veMoeAbi, functionName: "getTotalWeight" })],
|
|
3731
|
+
[veMoeAddr, encodeFunctionData10({ abi: veMoeAbi, functionName: "getTopPoolIds" })]
|
|
3732
|
+
];
|
|
3733
|
+
const batch5Results = await multicallRead(rpcUrl, batch5Calls);
|
|
3734
|
+
const moePerSecRaw = decodeUint256Result(batch5Results[0] ?? null) ?? 0n;
|
|
3735
|
+
const treasuryShareRaw = decodeUint256Result(batch5Results[1] ?? null) ?? 0n;
|
|
3736
|
+
const staticShareRaw = decodeUint256Result(batch5Results[2] ?? null) ?? 0n;
|
|
3737
|
+
totalWeightRaw = decodeUint256Result(batch5Results[3] ?? null) ?? 0n;
|
|
3738
|
+
const topPoolIdsRaw = decodeUint256ArrayResult(batch5Results[4] ?? null) ?? [];
|
|
3739
|
+
topPoolIds = new Set(topPoolIdsRaw.map(Number));
|
|
3740
|
+
const PRECISION = 10n ** 18n;
|
|
3741
|
+
const netPerSec = moePerSecRaw * (PRECISION - treasuryShareRaw) / PRECISION * (PRECISION - staticShareRaw) / PRECISION;
|
|
3742
|
+
moePerDay = Number(netPerSec * 86400n) / 1e18;
|
|
3743
|
+
}
|
|
3744
|
+
const weightByPid = /* @__PURE__ */ new Map();
|
|
3745
|
+
if (veMoeAddr && rewardedPairs.length > 0) {
|
|
3746
|
+
const batch6Calls = poolData.map((d) => [
|
|
3747
|
+
veMoeAddr,
|
|
3748
|
+
encodeFunctionData10({ abi: veMoeAbi, functionName: "getWeight", args: [BigInt(d.pid)] })
|
|
3749
|
+
]);
|
|
3750
|
+
const batch6Results = await multicallRead(rpcUrl, batch6Calls);
|
|
3751
|
+
for (let i = 0; i < poolData.length; i++) {
|
|
3752
|
+
weightByPid.set(poolData[i].pid, decodeUint256Result(batch6Results[i] ?? null) ?? 0n);
|
|
3753
|
+
}
|
|
3754
|
+
}
|
|
3755
|
+
let moePriceUsd = 0;
|
|
3756
|
+
let wmntPriceUsd = 0;
|
|
3757
|
+
const MOE_ADDR = "0x4515A45337F461A11Ff0FE8aBF3c606AE5dC00c9";
|
|
3758
|
+
if (this.lbQuoter && this.wmnt && this.usdt) {
|
|
3759
|
+
try {
|
|
3760
|
+
const [moeWmntQuote, wmntUsdtQuote] = await Promise.all([
|
|
3761
|
+
client.readContract({
|
|
3762
|
+
address: this.lbQuoter,
|
|
3763
|
+
abi: lbQuoterAbi2,
|
|
3764
|
+
functionName: "findBestPathFromAmountIn",
|
|
3765
|
+
args: [[MOE_ADDR, this.wmnt], 10n ** 18n]
|
|
3766
|
+
}),
|
|
3767
|
+
client.readContract({
|
|
3768
|
+
address: this.lbQuoter,
|
|
3769
|
+
abi: lbQuoterAbi2,
|
|
3770
|
+
functionName: "findBestPathFromAmountIn",
|
|
3771
|
+
args: [[this.wmnt, this.usdt], 10n ** 18n]
|
|
3772
|
+
})
|
|
3773
|
+
]);
|
|
3774
|
+
const moeInWmnt = Number(moeWmntQuote.amounts.at(-1) ?? 0n) / 1e18;
|
|
3775
|
+
wmntPriceUsd = Number(wmntUsdtQuote.amounts.at(-1) ?? 0n) / 1e6;
|
|
3776
|
+
moePriceUsd = moeInWmnt * wmntPriceUsd;
|
|
3777
|
+
} catch {
|
|
3778
|
+
}
|
|
3779
|
+
}
|
|
3780
|
+
const binRequests = [];
|
|
3781
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3782
|
+
const range = poolData[i].range;
|
|
3783
|
+
if (!range) continue;
|
|
3784
|
+
const minBin = Number(range[0]);
|
|
3785
|
+
const maxBin = Number(range[1]);
|
|
3786
|
+
for (let b = minBin; b <= maxBin; b++) {
|
|
3787
|
+
binRequests.push({ poolIdx: i, binId: b });
|
|
3788
|
+
}
|
|
3789
|
+
}
|
|
3790
|
+
const binReservesX = /* @__PURE__ */ new Map();
|
|
3791
|
+
const binReservesY = /* @__PURE__ */ new Map();
|
|
3792
|
+
if (binRequests.length > 0) {
|
|
3793
|
+
const batch7Calls = binRequests.map(({ poolIdx, binId }) => [
|
|
3794
|
+
rewardedPairs[poolIdx].pool,
|
|
3795
|
+
encodeFunctionData10({ abi: lbPairBinAbi, functionName: "getBin", args: [binId] })
|
|
3796
|
+
]);
|
|
3797
|
+
const batch7Results = await multicallRead(rpcUrl, batch7Calls);
|
|
3798
|
+
for (let j = 0; j < binRequests.length; j++) {
|
|
3799
|
+
const { poolIdx, binId } = binRequests[j];
|
|
3800
|
+
const decoded = decodeBinResult(batch7Results[j] ?? null);
|
|
3801
|
+
if (!decoded) continue;
|
|
3802
|
+
if (!binReservesX.has(poolIdx)) {
|
|
3803
|
+
binReservesX.set(poolIdx, /* @__PURE__ */ new Map());
|
|
3804
|
+
binReservesY.set(poolIdx, /* @__PURE__ */ new Map());
|
|
3805
|
+
}
|
|
3806
|
+
binReservesX.get(poolIdx).set(binId, decoded[0]);
|
|
3807
|
+
binReservesY.get(poolIdx).set(binId, decoded[1]);
|
|
3808
|
+
}
|
|
3809
|
+
}
|
|
3810
|
+
const stableSymbols = /* @__PURE__ */ new Set(["USDT", "USDC", "MUSD", "AUSD", "USDY", "FDUSD"]);
|
|
3811
|
+
const mntSymbols = /* @__PURE__ */ new Set(["WMNT", "MNT"]);
|
|
3812
|
+
const moeSymbols = /* @__PURE__ */ new Set(["MOE"]);
|
|
3813
|
+
const sixDecimalStables = /* @__PURE__ */ new Set(["USDT", "USDC", "FDUSD"]);
|
|
3814
|
+
const getTokenPriceUsd = (sym) => {
|
|
3815
|
+
if (stableSymbols.has(sym)) return 1;
|
|
3816
|
+
if (mntSymbols.has(sym)) return wmntPriceUsd;
|
|
3817
|
+
if (moeSymbols.has(sym)) return moePriceUsd;
|
|
3818
|
+
return 0;
|
|
3819
|
+
};
|
|
3820
|
+
const getTokenDecimals = (sym) => {
|
|
3821
|
+
return sixDecimalStables.has(sym) ? 6 : 18;
|
|
3822
|
+
};
|
|
3823
|
+
const results = [];
|
|
3824
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3825
|
+
const { pool, rewarder } = rewardedPairs[i];
|
|
3826
|
+
const data = poolData[i];
|
|
3827
|
+
const tokenX = tokenXAddresses[i] ?? "0x0000000000000000000000000000000000000000";
|
|
3828
|
+
const tokenY = tokenYAddresses[i] ?? "0x0000000000000000000000000000000000000000";
|
|
3829
|
+
const symX = symbolMap.get(tokenX) ?? "?";
|
|
3830
|
+
const symY = symbolMap.get(tokenY) ?? "?";
|
|
3831
|
+
const isTopPool = topPoolIds.has(data.pid);
|
|
3832
|
+
const weight = weightByPid.get(data.pid) ?? 0n;
|
|
3833
|
+
let poolMoePerDay = 0;
|
|
3834
|
+
if (isTopPool && totalWeightRaw > 0n && weight > 0n) {
|
|
3835
|
+
poolMoePerDay = moePerDay * (Number(weight) / Number(totalWeightRaw));
|
|
3836
|
+
}
|
|
3837
|
+
const rxMap = binReservesX.get(i);
|
|
3838
|
+
const ryMap = binReservesY.get(i);
|
|
3839
|
+
const range = data.range;
|
|
3840
|
+
let rangeTvlUsd = 0;
|
|
3841
|
+
let rewardedBins = 0;
|
|
3842
|
+
if (range) {
|
|
3843
|
+
const minBin = Number(range[0]);
|
|
3844
|
+
const maxBin = Number(range[1]);
|
|
3845
|
+
rewardedBins = maxBin - minBin + 1;
|
|
3846
|
+
if (rxMap && ryMap) {
|
|
3847
|
+
const priceX = getTokenPriceUsd(symX);
|
|
3848
|
+
const priceY = getTokenPriceUsd(symY);
|
|
3849
|
+
const decX = getTokenDecimals(symX);
|
|
3850
|
+
const decY = getTokenDecimals(symY);
|
|
3851
|
+
for (let b = minBin; b <= maxBin; b++) {
|
|
3852
|
+
const rx = rxMap.get(b) ?? 0n;
|
|
3853
|
+
const ry = ryMap.get(b) ?? 0n;
|
|
3854
|
+
rangeTvlUsd += Number(rx) / 10 ** decX * priceX;
|
|
3855
|
+
rangeTvlUsd += Number(ry) / 10 ** decY * priceY;
|
|
3856
|
+
}
|
|
3857
|
+
}
|
|
3858
|
+
}
|
|
3859
|
+
const aprPercent = rangeTvlUsd > 0 && moePriceUsd > 0 ? poolMoePerDay * moePriceUsd * 365 / rangeTvlUsd * 100 : 0;
|
|
3860
|
+
results.push({
|
|
3861
|
+
pool,
|
|
3862
|
+
rewarder,
|
|
3863
|
+
rewardToken: data.rewardToken ?? "0x0000000000000000000000000000000000000000",
|
|
3864
|
+
minBinId: range ? Number(range[0]) : 0,
|
|
3865
|
+
maxBinId: range ? Number(range[1]) : 0,
|
|
3866
|
+
pid: data.pid,
|
|
3867
|
+
stopped: data.stopped,
|
|
3868
|
+
tokenX,
|
|
3869
|
+
tokenY,
|
|
3870
|
+
symbolX: symX,
|
|
3871
|
+
symbolY: symY,
|
|
3872
|
+
isTopPool,
|
|
3873
|
+
moePerDay: poolMoePerDay,
|
|
3874
|
+
rangeTvlUsd,
|
|
3875
|
+
aprPercent,
|
|
3876
|
+
rewardedBins
|
|
3877
|
+
});
|
|
3878
|
+
}
|
|
3879
|
+
return results;
|
|
3880
|
+
}
|
|
3881
|
+
/**
|
|
3882
|
+
* Get a user's LB positions (bin balances) across a range of bin IDs.
|
|
3883
|
+
* If binIds is omitted, auto-detects from the rewarder's rewarded range (or active ± 50).
|
|
3884
|
+
*/
|
|
3885
|
+
async getUserPositions(user, pool, binIds) {
|
|
3886
|
+
const rpcUrl = this.requireRpc();
|
|
3887
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3888
|
+
const resolvedBinIds = binIds && binIds.length > 0 ? binIds : await this.autoDetectBins(pool);
|
|
3889
|
+
const accounts = resolvedBinIds.map(() => user);
|
|
3890
|
+
const ids = resolvedBinIds.map(BigInt);
|
|
3891
|
+
const balances = await client.readContract({
|
|
3892
|
+
address: pool,
|
|
3893
|
+
abi: lbPairAbi,
|
|
3894
|
+
functionName: "balanceOfBatch",
|
|
3895
|
+
args: [accounts, ids]
|
|
3896
|
+
});
|
|
3897
|
+
return resolvedBinIds.map((binId, i) => ({ binId, balance: balances[i] ?? 0n })).filter((p) => p.balance > 0n);
|
|
3898
|
+
}
|
|
3899
|
+
};
|
|
3900
|
+
var POOL_ABI = parseAbi11([
|
|
3071
3901
|
"function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
|
|
3072
3902
|
"function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
|
|
3073
3903
|
"function repay(address asset, uint256 amount, uint256 interestRateMode, address onBehalfOf) external returns (uint256)",
|
|
@@ -3075,27 +3905,27 @@ var POOL_ABI = parseAbi10([
|
|
|
3075
3905
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)",
|
|
3076
3906
|
"function getReserveData(address asset) external view returns (uint256 configuration, uint128 liquidityIndex, uint128 currentLiquidityRate, uint128 variableBorrowIndex, uint128 currentVariableBorrowRate, uint128 currentStableBorrowRate, uint40 lastUpdateTimestamp, uint16 id, address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress, address interestRateStrategyAddress, uint128 accruedToTreasury, uint128 unbacked, uint128 isolationModeTotalDebt)"
|
|
3077
3907
|
]);
|
|
3078
|
-
var
|
|
3908
|
+
var ERC20_ABI2 = parseAbi11([
|
|
3079
3909
|
"function totalSupply() external view returns (uint256)"
|
|
3080
3910
|
]);
|
|
3081
|
-
var INCENTIVES_ABI =
|
|
3911
|
+
var INCENTIVES_ABI = parseAbi11([
|
|
3082
3912
|
"function getIncentivesController() external view returns (address)"
|
|
3083
3913
|
]);
|
|
3084
|
-
var REWARDS_CONTROLLER_ABI =
|
|
3914
|
+
var REWARDS_CONTROLLER_ABI = parseAbi11([
|
|
3085
3915
|
"function getRewardsByAsset(address asset) external view returns (address[])",
|
|
3086
3916
|
"function getRewardsData(address asset, address reward) external view returns (uint256 index, uint256 emissionsPerSecond, uint256 lastUpdateTimestamp, uint256 distributionEnd)"
|
|
3087
3917
|
]);
|
|
3088
|
-
var POOL_PROVIDER_ABI =
|
|
3918
|
+
var POOL_PROVIDER_ABI = parseAbi11([
|
|
3089
3919
|
"function ADDRESSES_PROVIDER() external view returns (address)"
|
|
3090
3920
|
]);
|
|
3091
|
-
var ADDRESSES_PROVIDER_ABI =
|
|
3921
|
+
var ADDRESSES_PROVIDER_ABI = parseAbi11([
|
|
3092
3922
|
"function getPriceOracle() external view returns (address)"
|
|
3093
3923
|
]);
|
|
3094
|
-
var ORACLE_ABI =
|
|
3924
|
+
var ORACLE_ABI = parseAbi11([
|
|
3095
3925
|
"function getAssetPrice(address asset) external view returns (uint256)",
|
|
3096
3926
|
"function BASE_CURRENCY_UNIT() external view returns (uint256)"
|
|
3097
3927
|
]);
|
|
3098
|
-
var ERC20_DECIMALS_ABI =
|
|
3928
|
+
var ERC20_DECIMALS_ABI = parseAbi11([
|
|
3099
3929
|
"function decimals() external view returns (uint8)"
|
|
3100
3930
|
]);
|
|
3101
3931
|
function u256ToF64(v) {
|
|
@@ -3103,6 +3933,46 @@ function u256ToF64(v) {
|
|
|
3103
3933
|
if (v > MAX_U128) return Infinity;
|
|
3104
3934
|
return Number(v);
|
|
3105
3935
|
}
|
|
3936
|
+
function decodeAddress(data) {
|
|
3937
|
+
if (!data || data.length < 66) return null;
|
|
3938
|
+
return `0x${data.slice(26, 66)}`;
|
|
3939
|
+
}
|
|
3940
|
+
function decodeAddressArray(data) {
|
|
3941
|
+
if (!data) return [];
|
|
3942
|
+
try {
|
|
3943
|
+
return decodeFunctionResult3({
|
|
3944
|
+
abi: REWARDS_CONTROLLER_ABI,
|
|
3945
|
+
functionName: "getRewardsByAsset",
|
|
3946
|
+
data
|
|
3947
|
+
});
|
|
3948
|
+
} catch {
|
|
3949
|
+
return [];
|
|
3950
|
+
}
|
|
3951
|
+
}
|
|
3952
|
+
function decodeReserveData(data) {
|
|
3953
|
+
if (!data) return null;
|
|
3954
|
+
try {
|
|
3955
|
+
return decodeFunctionResult3({
|
|
3956
|
+
abi: POOL_ABI,
|
|
3957
|
+
functionName: "getReserveData",
|
|
3958
|
+
data
|
|
3959
|
+
});
|
|
3960
|
+
} catch {
|
|
3961
|
+
return null;
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
function decodeRewardsData(data) {
|
|
3965
|
+
if (!data) return null;
|
|
3966
|
+
try {
|
|
3967
|
+
return decodeFunctionResult3({
|
|
3968
|
+
abi: REWARDS_CONTROLLER_ABI,
|
|
3969
|
+
functionName: "getRewardsData",
|
|
3970
|
+
data
|
|
3971
|
+
});
|
|
3972
|
+
} catch {
|
|
3973
|
+
return null;
|
|
3974
|
+
}
|
|
3975
|
+
}
|
|
3106
3976
|
var AaveV3Adapter = class {
|
|
3107
3977
|
protocolName;
|
|
3108
3978
|
pool;
|
|
@@ -3118,7 +3988,7 @@ var AaveV3Adapter = class {
|
|
|
3118
3988
|
return this.protocolName;
|
|
3119
3989
|
}
|
|
3120
3990
|
async buildSupply(params) {
|
|
3121
|
-
const data =
|
|
3991
|
+
const data = encodeFunctionData11({
|
|
3122
3992
|
abi: POOL_ABI,
|
|
3123
3993
|
functionName: "supply",
|
|
3124
3994
|
args: [params.asset, params.amount, params.on_behalf_of, 0]
|
|
@@ -3128,12 +3998,13 @@ var AaveV3Adapter = class {
|
|
|
3128
3998
|
to: this.pool,
|
|
3129
3999
|
data,
|
|
3130
4000
|
value: 0n,
|
|
3131
|
-
gas_estimate: 3e5
|
|
4001
|
+
gas_estimate: 3e5,
|
|
4002
|
+
approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
|
|
3132
4003
|
};
|
|
3133
4004
|
}
|
|
3134
4005
|
async buildBorrow(params) {
|
|
3135
4006
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
3136
|
-
const data =
|
|
4007
|
+
const data = encodeFunctionData11({
|
|
3137
4008
|
abi: POOL_ABI,
|
|
3138
4009
|
functionName: "borrow",
|
|
3139
4010
|
args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
|
|
@@ -3148,7 +4019,7 @@ var AaveV3Adapter = class {
|
|
|
3148
4019
|
}
|
|
3149
4020
|
async buildRepay(params) {
|
|
3150
4021
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
3151
|
-
const data =
|
|
4022
|
+
const data = encodeFunctionData11({
|
|
3152
4023
|
abi: POOL_ABI,
|
|
3153
4024
|
functionName: "repay",
|
|
3154
4025
|
args: [params.asset, params.amount, rateMode, params.on_behalf_of]
|
|
@@ -3158,11 +4029,12 @@ var AaveV3Adapter = class {
|
|
|
3158
4029
|
to: this.pool,
|
|
3159
4030
|
data,
|
|
3160
4031
|
value: 0n,
|
|
3161
|
-
gas_estimate: 3e5
|
|
4032
|
+
gas_estimate: 3e5,
|
|
4033
|
+
approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
|
|
3162
4034
|
};
|
|
3163
4035
|
}
|
|
3164
4036
|
async buildWithdraw(params) {
|
|
3165
|
-
const data =
|
|
4037
|
+
const data = encodeFunctionData11({
|
|
3166
4038
|
abi: POOL_ABI,
|
|
3167
4039
|
functionName: "withdraw",
|
|
3168
4040
|
args: [params.asset, params.amount, params.to]
|
|
@@ -3177,15 +4049,21 @@ var AaveV3Adapter = class {
|
|
|
3177
4049
|
}
|
|
3178
4050
|
async getRates(asset) {
|
|
3179
4051
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
3180
|
-
const
|
|
3181
|
-
const result = await client.readContract({
|
|
3182
|
-
address: this.pool,
|
|
4052
|
+
const reserveCallData = encodeFunctionData11({
|
|
3183
4053
|
abi: POOL_ABI,
|
|
3184
4054
|
functionName: "getReserveData",
|
|
3185
4055
|
args: [asset]
|
|
3186
|
-
})
|
|
4056
|
+
});
|
|
4057
|
+
const [reserveRaw] = await multicallRead(this.rpcUrl, [
|
|
4058
|
+
[this.pool, reserveCallData]
|
|
4059
|
+
]).catch((e) => {
|
|
3187
4060
|
throw DefiError.rpcError(`[${this.protocolName}] getReserveData failed: ${e}`);
|
|
3188
4061
|
});
|
|
4062
|
+
const reserveDecoded = decodeReserveData(reserveRaw ?? null);
|
|
4063
|
+
if (!reserveDecoded) {
|
|
4064
|
+
throw DefiError.rpcError(`[${this.protocolName}] getReserveData returned no data`);
|
|
4065
|
+
}
|
|
4066
|
+
const result = reserveDecoded;
|
|
3189
4067
|
const RAY = 1e27;
|
|
3190
4068
|
const SECONDS_PER_YEAR4 = 31536e3;
|
|
3191
4069
|
const toApy = (rayRate) => {
|
|
@@ -3197,74 +4075,56 @@ var AaveV3Adapter = class {
|
|
|
3197
4075
|
const stableRate = toApy(result[5]);
|
|
3198
4076
|
const aTokenAddress = result[8];
|
|
3199
4077
|
const variableDebtTokenAddress = result[10];
|
|
3200
|
-
const [
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
abi: ERC20_ABI,
|
|
3204
|
-
functionName: "totalSupply"
|
|
3205
|
-
}).catch(() => 0n),
|
|
3206
|
-
client.readContract({
|
|
3207
|
-
address: variableDebtTokenAddress,
|
|
3208
|
-
abi: ERC20_ABI,
|
|
3209
|
-
functionName: "totalSupply"
|
|
3210
|
-
}).catch(() => 0n)
|
|
4078
|
+
const [supplyRaw, borrowRaw] = await multicallRead(this.rpcUrl, [
|
|
4079
|
+
[aTokenAddress, encodeFunctionData11({ abi: ERC20_ABI2, functionName: "totalSupply" })],
|
|
4080
|
+
[variableDebtTokenAddress, encodeFunctionData11({ abi: ERC20_ABI2, functionName: "totalSupply" })]
|
|
3211
4081
|
]);
|
|
4082
|
+
const totalSupply = decodeU256(supplyRaw ?? null);
|
|
4083
|
+
const totalBorrow = decodeU256(borrowRaw ?? null);
|
|
3212
4084
|
const utilization = totalSupply > 0n ? Number(totalBorrow * 10000n / totalSupply) / 100 : 0;
|
|
3213
4085
|
const supplyRewardTokens = [];
|
|
3214
4086
|
const borrowRewardTokens = [];
|
|
3215
4087
|
const supplyEmissions = [];
|
|
3216
4088
|
const borrowEmissions = [];
|
|
3217
4089
|
try {
|
|
3218
|
-
const
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
});
|
|
4090
|
+
const [controllerRaw] = await multicallRead(this.rpcUrl, [
|
|
4091
|
+
[aTokenAddress, encodeFunctionData11({ abi: INCENTIVES_ABI, functionName: "getIncentivesController" })]
|
|
4092
|
+
]);
|
|
4093
|
+
const controllerAddr = decodeAddress(controllerRaw ?? null);
|
|
3223
4094
|
if (controllerAddr && controllerAddr !== zeroAddress5) {
|
|
3224
|
-
const [
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
abi: REWARDS_CONTROLLER_ABI,
|
|
3228
|
-
functionName: "getRewardsByAsset",
|
|
3229
|
-
args: [aTokenAddress]
|
|
3230
|
-
}).catch(() => []),
|
|
3231
|
-
client.readContract({
|
|
3232
|
-
address: controllerAddr,
|
|
3233
|
-
abi: REWARDS_CONTROLLER_ABI,
|
|
3234
|
-
functionName: "getRewardsByAsset",
|
|
3235
|
-
args: [variableDebtTokenAddress]
|
|
3236
|
-
}).catch(() => [])
|
|
4095
|
+
const [supplyRewardsRaw, borrowRewardsRaw] = await multicallRead(this.rpcUrl, [
|
|
4096
|
+
[controllerAddr, encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [aTokenAddress] })],
|
|
4097
|
+
[controllerAddr, encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [variableDebtTokenAddress] })]
|
|
3237
4098
|
]);
|
|
3238
|
-
const
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
args: [aTokenAddress, reward]
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
4099
|
+
const supplyRewards = decodeAddressArray(supplyRewardsRaw ?? null);
|
|
4100
|
+
const borrowRewards = decodeAddressArray(borrowRewardsRaw ?? null);
|
|
4101
|
+
const rewardsDataCalls = [
|
|
4102
|
+
...supplyRewards.map((reward) => [
|
|
4103
|
+
controllerAddr,
|
|
4104
|
+
encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [aTokenAddress, reward] })
|
|
4105
|
+
]),
|
|
4106
|
+
...borrowRewards.map((reward) => [
|
|
4107
|
+
controllerAddr,
|
|
4108
|
+
encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [variableDebtTokenAddress, reward] })
|
|
4109
|
+
])
|
|
4110
|
+
];
|
|
4111
|
+
if (rewardsDataCalls.length > 0) {
|
|
4112
|
+
const rewardsDataResults = await multicallRead(this.rpcUrl, rewardsDataCalls);
|
|
4113
|
+
const supplyDataResults = rewardsDataResults.slice(0, supplyRewards.length);
|
|
4114
|
+
const borrowDataResults = rewardsDataResults.slice(supplyRewards.length);
|
|
4115
|
+
for (let i = 0; i < supplyRewards.length; i++) {
|
|
4116
|
+
const data = decodeRewardsData(supplyDataResults[i] ?? null);
|
|
4117
|
+
if (data && data[1] > 0n) {
|
|
4118
|
+
supplyRewardTokens.push(supplyRewards[i]);
|
|
4119
|
+
supplyEmissions.push(data[1].toString());
|
|
4120
|
+
}
|
|
3252
4121
|
}
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
args: [variableDebtTokenAddress, reward]
|
|
3260
|
-
}).catch(() => null)
|
|
3261
|
-
);
|
|
3262
|
-
const borrowData = await Promise.all(borrowDataPromises);
|
|
3263
|
-
for (let i = 0; i < borrowRewards.length; i++) {
|
|
3264
|
-
const data = borrowData[i];
|
|
3265
|
-
if (data && data[1] > 0n) {
|
|
3266
|
-
borrowRewardTokens.push(borrowRewards[i]);
|
|
3267
|
-
borrowEmissions.push(data[1].toString());
|
|
4122
|
+
for (let i = 0; i < borrowRewards.length; i++) {
|
|
4123
|
+
const data = decodeRewardsData(borrowDataResults[i] ?? null);
|
|
4124
|
+
if (data && data[1] > 0n) {
|
|
4125
|
+
borrowRewardTokens.push(borrowRewards[i]);
|
|
4126
|
+
borrowEmissions.push(data[1].toString());
|
|
4127
|
+
}
|
|
3268
4128
|
}
|
|
3269
4129
|
}
|
|
3270
4130
|
}
|
|
@@ -3276,55 +4136,49 @@ var AaveV3Adapter = class {
|
|
|
3276
4136
|
const hasBorrowRewards = borrowRewardTokens.length > 0;
|
|
3277
4137
|
if ((hasSupplyRewards || hasBorrowRewards) && totalSupply > 0n) {
|
|
3278
4138
|
try {
|
|
3279
|
-
const
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
const
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
const [
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
functionName: "getAssetPrice",
|
|
3294
|
-
args: [asset]
|
|
3295
|
-
}),
|
|
3296
|
-
client.readContract({
|
|
3297
|
-
address: oracleAddr,
|
|
3298
|
-
abi: ORACLE_ABI,
|
|
3299
|
-
functionName: "BASE_CURRENCY_UNIT"
|
|
3300
|
-
}),
|
|
3301
|
-
client.readContract({
|
|
3302
|
-
address: asset,
|
|
3303
|
-
abi: ERC20_DECIMALS_ABI,
|
|
3304
|
-
functionName: "decimals"
|
|
3305
|
-
}).catch(() => 18)
|
|
4139
|
+
const [providerRaw] = await multicallRead(this.rpcUrl, [
|
|
4140
|
+
[this.pool, encodeFunctionData11({ abi: POOL_PROVIDER_ABI, functionName: "ADDRESSES_PROVIDER" })]
|
|
4141
|
+
]);
|
|
4142
|
+
const providerAddr = decodeAddress(providerRaw ?? null);
|
|
4143
|
+
if (!providerAddr) throw new Error("No provider address");
|
|
4144
|
+
const [oracleRaw] = await multicallRead(this.rpcUrl, [
|
|
4145
|
+
[providerAddr, encodeFunctionData11({ abi: ADDRESSES_PROVIDER_ABI, functionName: "getPriceOracle" })]
|
|
4146
|
+
]);
|
|
4147
|
+
const oracleAddr = decodeAddress(oracleRaw ?? null);
|
|
4148
|
+
if (!oracleAddr) throw new Error("No oracle address");
|
|
4149
|
+
const [assetPriceRaw, baseCurrencyUnitRaw, assetDecimalsRaw] = await multicallRead(this.rpcUrl, [
|
|
4150
|
+
[oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [asset] })],
|
|
4151
|
+
[oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "BASE_CURRENCY_UNIT" })],
|
|
4152
|
+
[asset, encodeFunctionData11({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
|
|
3306
4153
|
]);
|
|
3307
|
-
const
|
|
4154
|
+
const assetPrice = decodeU256(assetPriceRaw ?? null);
|
|
4155
|
+
const baseCurrencyUnit = decodeU256(baseCurrencyUnitRaw ?? null);
|
|
4156
|
+
const assetDecimals = assetDecimalsRaw ? Number(decodeU256(assetDecimalsRaw)) : 18;
|
|
4157
|
+
const priceUnit = Number(baseCurrencyUnit) || 1e8;
|
|
3308
4158
|
const assetPriceF = Number(assetPrice) / priceUnit;
|
|
3309
4159
|
const assetDecimalsDivisor = 10 ** assetDecimals;
|
|
4160
|
+
const allRewardTokens = Array.from(/* @__PURE__ */ new Set([...supplyRewardTokens, ...borrowRewardTokens]));
|
|
4161
|
+
const rewardPriceCalls = allRewardTokens.flatMap((token) => [
|
|
4162
|
+
[oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [token] })],
|
|
4163
|
+
[token, encodeFunctionData11({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
|
|
4164
|
+
]);
|
|
4165
|
+
const rewardPriceResults = rewardPriceCalls.length > 0 ? await multicallRead(this.rpcUrl, rewardPriceCalls) : [];
|
|
4166
|
+
const rewardPriceMap = /* @__PURE__ */ new Map();
|
|
4167
|
+
for (let i = 0; i < allRewardTokens.length; i++) {
|
|
4168
|
+
const priceRaw = rewardPriceResults[i * 2] ?? null;
|
|
4169
|
+
const decimalsRaw = rewardPriceResults[i * 2 + 1] ?? null;
|
|
4170
|
+
const price = decodeU256(priceRaw);
|
|
4171
|
+
const decimals = decimalsRaw ? Number(decodeU256(decimalsRaw)) : 18;
|
|
4172
|
+
rewardPriceMap.set(allRewardTokens[i].toLowerCase(), { price, decimals });
|
|
4173
|
+
}
|
|
3310
4174
|
if (hasSupplyRewards) {
|
|
3311
4175
|
let totalSupplyIncentiveUsdPerYear = 0;
|
|
3312
4176
|
const totalSupplyUsd = Number(totalSupply) / assetDecimalsDivisor * assetPriceF;
|
|
3313
4177
|
for (let i = 0; i < supplyRewardTokens.length; i++) {
|
|
3314
4178
|
const emissionPerSec = BigInt(supplyEmissions[i]);
|
|
3315
|
-
const
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
abi: ORACLE_ABI,
|
|
3319
|
-
functionName: "getAssetPrice",
|
|
3320
|
-
args: [supplyRewardTokens[i]]
|
|
3321
|
-
}).catch(() => 0n),
|
|
3322
|
-
client.readContract({
|
|
3323
|
-
address: supplyRewardTokens[i],
|
|
3324
|
-
abi: ERC20_DECIMALS_ABI,
|
|
3325
|
-
functionName: "decimals"
|
|
3326
|
-
}).catch(() => 18)
|
|
3327
|
-
]);
|
|
4179
|
+
const entry = rewardPriceMap.get(supplyRewardTokens[i].toLowerCase());
|
|
4180
|
+
const rewardPrice = entry?.price ?? 0n;
|
|
4181
|
+
const rewardDecimals = entry?.decimals ?? 18;
|
|
3328
4182
|
if (rewardPrice > 0n) {
|
|
3329
4183
|
const rewardPriceF = Number(rewardPrice) / priceUnit;
|
|
3330
4184
|
const emissionPerYear = Number(emissionPerSec) / 10 ** rewardDecimals * SECONDS_PER_YEAR4;
|
|
@@ -3340,19 +4194,9 @@ var AaveV3Adapter = class {
|
|
|
3340
4194
|
const totalBorrowUsd = Number(totalBorrow) / assetDecimalsDivisor * assetPriceF;
|
|
3341
4195
|
for (let i = 0; i < borrowRewardTokens.length; i++) {
|
|
3342
4196
|
const emissionPerSec = BigInt(borrowEmissions[i]);
|
|
3343
|
-
const
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
abi: ORACLE_ABI,
|
|
3347
|
-
functionName: "getAssetPrice",
|
|
3348
|
-
args: [borrowRewardTokens[i]]
|
|
3349
|
-
}).catch(() => 0n),
|
|
3350
|
-
client.readContract({
|
|
3351
|
-
address: borrowRewardTokens[i],
|
|
3352
|
-
abi: ERC20_DECIMALS_ABI,
|
|
3353
|
-
functionName: "decimals"
|
|
3354
|
-
}).catch(() => 18)
|
|
3355
|
-
]);
|
|
4197
|
+
const entry = rewardPriceMap.get(borrowRewardTokens[i].toLowerCase());
|
|
4198
|
+
const rewardPrice = entry?.price ?? 0n;
|
|
4199
|
+
const rewardDecimals = entry?.decimals ?? 18;
|
|
3356
4200
|
if (rewardPrice > 0n) {
|
|
3357
4201
|
const rewardPriceF = Number(rewardPrice) / priceUnit;
|
|
3358
4202
|
const emissionPerYear = Number(emissionPerSec) / 10 ** rewardDecimals * SECONDS_PER_YEAR4;
|
|
@@ -3416,7 +4260,7 @@ var AaveV3Adapter = class {
|
|
|
3416
4260
|
};
|
|
3417
4261
|
}
|
|
3418
4262
|
};
|
|
3419
|
-
var POOL_ABI2 =
|
|
4263
|
+
var POOL_ABI2 = parseAbi12([
|
|
3420
4264
|
"function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
|
|
3421
4265
|
"function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
|
|
3422
4266
|
"function repay(address asset, uint256 amount, uint256 rateMode, address onBehalfOf) external returns (uint256)",
|
|
@@ -3429,7 +4273,7 @@ var POOL_ABI2 = parseAbi11([
|
|
|
3429
4273
|
// [9]=variableDebtTokenAddress, [10]=interestRateStrategyAddress, [11]=id
|
|
3430
4274
|
"function getReserveData(address asset) external view returns (uint256 configuration, uint128 liquidityIndex, uint128 variableBorrowIndex, uint128 currentLiquidityRate, uint128 currentVariableBorrowRate, uint128 currentStableBorrowRate, uint40 lastUpdateTimestamp, address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress, address interestRateStrategyAddress, uint8 id)"
|
|
3431
4275
|
]);
|
|
3432
|
-
var
|
|
4276
|
+
var ERC20_ABI22 = parseAbi12([
|
|
3433
4277
|
"function totalSupply() external view returns (uint256)"
|
|
3434
4278
|
]);
|
|
3435
4279
|
function u256ToF642(v) {
|
|
@@ -3452,7 +4296,7 @@ var AaveV2Adapter = class {
|
|
|
3452
4296
|
return this.protocolName;
|
|
3453
4297
|
}
|
|
3454
4298
|
async buildSupply(params) {
|
|
3455
|
-
const data =
|
|
4299
|
+
const data = encodeFunctionData12({
|
|
3456
4300
|
abi: POOL_ABI2,
|
|
3457
4301
|
functionName: "deposit",
|
|
3458
4302
|
args: [params.asset, params.amount, params.on_behalf_of, 0]
|
|
@@ -3462,12 +4306,13 @@ var AaveV2Adapter = class {
|
|
|
3462
4306
|
to: this.pool,
|
|
3463
4307
|
data,
|
|
3464
4308
|
value: 0n,
|
|
3465
|
-
gas_estimate: 3e5
|
|
4309
|
+
gas_estimate: 3e5,
|
|
4310
|
+
approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
|
|
3466
4311
|
};
|
|
3467
4312
|
}
|
|
3468
4313
|
async buildBorrow(params) {
|
|
3469
4314
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
3470
|
-
const data =
|
|
4315
|
+
const data = encodeFunctionData12({
|
|
3471
4316
|
abi: POOL_ABI2,
|
|
3472
4317
|
functionName: "borrow",
|
|
3473
4318
|
args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
|
|
@@ -3482,7 +4327,7 @@ var AaveV2Adapter = class {
|
|
|
3482
4327
|
}
|
|
3483
4328
|
async buildRepay(params) {
|
|
3484
4329
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
3485
|
-
const data =
|
|
4330
|
+
const data = encodeFunctionData12({
|
|
3486
4331
|
abi: POOL_ABI2,
|
|
3487
4332
|
functionName: "repay",
|
|
3488
4333
|
args: [params.asset, params.amount, rateMode, params.on_behalf_of]
|
|
@@ -3492,11 +4337,12 @@ var AaveV2Adapter = class {
|
|
|
3492
4337
|
to: this.pool,
|
|
3493
4338
|
data,
|
|
3494
4339
|
value: 0n,
|
|
3495
|
-
gas_estimate: 3e5
|
|
4340
|
+
gas_estimate: 3e5,
|
|
4341
|
+
approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
|
|
3496
4342
|
};
|
|
3497
4343
|
}
|
|
3498
4344
|
async buildWithdraw(params) {
|
|
3499
|
-
const data =
|
|
4345
|
+
const data = encodeFunctionData12({
|
|
3500
4346
|
abi: POOL_ABI2,
|
|
3501
4347
|
functionName: "withdraw",
|
|
3502
4348
|
args: [params.asset, params.amount, params.to]
|
|
@@ -3534,12 +4380,12 @@ var AaveV2Adapter = class {
|
|
|
3534
4380
|
const [totalSupply, totalBorrow] = await Promise.all([
|
|
3535
4381
|
client.readContract({
|
|
3536
4382
|
address: aTokenAddress,
|
|
3537
|
-
abi:
|
|
4383
|
+
abi: ERC20_ABI22,
|
|
3538
4384
|
functionName: "totalSupply"
|
|
3539
4385
|
}).catch(() => 0n),
|
|
3540
4386
|
client.readContract({
|
|
3541
4387
|
address: variableDebtTokenAddress,
|
|
3542
|
-
abi:
|
|
4388
|
+
abi: ERC20_ABI22,
|
|
3543
4389
|
functionName: "totalSupply"
|
|
3544
4390
|
}).catch(() => 0n)
|
|
3545
4391
|
]);
|
|
@@ -3584,7 +4430,7 @@ var AaveV2Adapter = class {
|
|
|
3584
4430
|
};
|
|
3585
4431
|
}
|
|
3586
4432
|
};
|
|
3587
|
-
var ORACLE_ABI2 =
|
|
4433
|
+
var ORACLE_ABI2 = parseAbi13([
|
|
3588
4434
|
"function getAssetPrice(address asset) external view returns (uint256)",
|
|
3589
4435
|
"function getAssetsPrices(address[] calldata assets) external view returns (uint256[] memory)",
|
|
3590
4436
|
"function BASE_CURRENCY_UNIT() external view returns (uint256)"
|
|
@@ -3661,7 +4507,7 @@ var AaveOracleAdapter = class {
|
|
|
3661
4507
|
});
|
|
3662
4508
|
}
|
|
3663
4509
|
};
|
|
3664
|
-
var CTOKEN_ABI =
|
|
4510
|
+
var CTOKEN_ABI = parseAbi14([
|
|
3665
4511
|
"function supplyRatePerBlock() external view returns (uint256)",
|
|
3666
4512
|
"function borrowRatePerBlock() external view returns (uint256)",
|
|
3667
4513
|
"function totalSupply() external view returns (uint256)",
|
|
@@ -3688,7 +4534,7 @@ var CompoundV2Adapter = class {
|
|
|
3688
4534
|
return this.protocolName;
|
|
3689
4535
|
}
|
|
3690
4536
|
async buildSupply(params) {
|
|
3691
|
-
const data =
|
|
4537
|
+
const data = encodeFunctionData13({
|
|
3692
4538
|
abi: CTOKEN_ABI,
|
|
3693
4539
|
functionName: "mint",
|
|
3694
4540
|
args: [params.amount]
|
|
@@ -3702,7 +4548,7 @@ var CompoundV2Adapter = class {
|
|
|
3702
4548
|
};
|
|
3703
4549
|
}
|
|
3704
4550
|
async buildBorrow(params) {
|
|
3705
|
-
const data =
|
|
4551
|
+
const data = encodeFunctionData13({
|
|
3706
4552
|
abi: CTOKEN_ABI,
|
|
3707
4553
|
functionName: "borrow",
|
|
3708
4554
|
args: [params.amount]
|
|
@@ -3716,7 +4562,7 @@ var CompoundV2Adapter = class {
|
|
|
3716
4562
|
};
|
|
3717
4563
|
}
|
|
3718
4564
|
async buildRepay(params) {
|
|
3719
|
-
const data =
|
|
4565
|
+
const data = encodeFunctionData13({
|
|
3720
4566
|
abi: CTOKEN_ABI,
|
|
3721
4567
|
functionName: "repayBorrow",
|
|
3722
4568
|
args: [params.amount]
|
|
@@ -3730,7 +4576,7 @@ var CompoundV2Adapter = class {
|
|
|
3730
4576
|
};
|
|
3731
4577
|
}
|
|
3732
4578
|
async buildWithdraw(params) {
|
|
3733
|
-
const data =
|
|
4579
|
+
const data = encodeFunctionData13({
|
|
3734
4580
|
abi: CTOKEN_ABI,
|
|
3735
4581
|
functionName: "redeem",
|
|
3736
4582
|
args: [params.amount]
|
|
@@ -3779,7 +4625,7 @@ var CompoundV2Adapter = class {
|
|
|
3779
4625
|
);
|
|
3780
4626
|
}
|
|
3781
4627
|
};
|
|
3782
|
-
var COMET_ABI =
|
|
4628
|
+
var COMET_ABI = parseAbi15([
|
|
3783
4629
|
"function getUtilization() external view returns (uint256)",
|
|
3784
4630
|
"function getSupplyRate(uint256 utilization) external view returns (uint64)",
|
|
3785
4631
|
"function getBorrowRate(uint256 utilization) external view returns (uint64)",
|
|
@@ -3805,7 +4651,7 @@ var CompoundV3Adapter = class {
|
|
|
3805
4651
|
return this.protocolName;
|
|
3806
4652
|
}
|
|
3807
4653
|
async buildSupply(params) {
|
|
3808
|
-
const data =
|
|
4654
|
+
const data = encodeFunctionData14({
|
|
3809
4655
|
abi: COMET_ABI,
|
|
3810
4656
|
functionName: "supply",
|
|
3811
4657
|
args: [params.asset, params.amount]
|
|
@@ -3819,7 +4665,7 @@ var CompoundV3Adapter = class {
|
|
|
3819
4665
|
};
|
|
3820
4666
|
}
|
|
3821
4667
|
async buildBorrow(params) {
|
|
3822
|
-
const data =
|
|
4668
|
+
const data = encodeFunctionData14({
|
|
3823
4669
|
abi: COMET_ABI,
|
|
3824
4670
|
functionName: "withdraw",
|
|
3825
4671
|
args: [params.asset, params.amount]
|
|
@@ -3833,7 +4679,7 @@ var CompoundV3Adapter = class {
|
|
|
3833
4679
|
};
|
|
3834
4680
|
}
|
|
3835
4681
|
async buildRepay(params) {
|
|
3836
|
-
const data =
|
|
4682
|
+
const data = encodeFunctionData14({
|
|
3837
4683
|
abi: COMET_ABI,
|
|
3838
4684
|
functionName: "supply",
|
|
3839
4685
|
args: [params.asset, params.amount]
|
|
@@ -3847,7 +4693,7 @@ var CompoundV3Adapter = class {
|
|
|
3847
4693
|
};
|
|
3848
4694
|
}
|
|
3849
4695
|
async buildWithdraw(params) {
|
|
3850
|
-
const data =
|
|
4696
|
+
const data = encodeFunctionData14({
|
|
3851
4697
|
abi: COMET_ABI,
|
|
3852
4698
|
functionName: "withdraw",
|
|
3853
4699
|
args: [params.asset, params.amount]
|
|
@@ -3901,7 +4747,7 @@ var CompoundV3Adapter = class {
|
|
|
3901
4747
|
);
|
|
3902
4748
|
}
|
|
3903
4749
|
};
|
|
3904
|
-
var EULER_VAULT_ABI =
|
|
4750
|
+
var EULER_VAULT_ABI = parseAbi16([
|
|
3905
4751
|
"function deposit(uint256 amount, address receiver) external returns (uint256)",
|
|
3906
4752
|
"function withdraw(uint256 amount, address receiver, address owner) external returns (uint256)",
|
|
3907
4753
|
"function borrow(uint256 amount, address receiver) external returns (uint256)",
|
|
@@ -3927,7 +4773,7 @@ var EulerV2Adapter = class {
|
|
|
3927
4773
|
return this.protocolName;
|
|
3928
4774
|
}
|
|
3929
4775
|
async buildSupply(params) {
|
|
3930
|
-
const data =
|
|
4776
|
+
const data = encodeFunctionData15({
|
|
3931
4777
|
abi: EULER_VAULT_ABI,
|
|
3932
4778
|
functionName: "deposit",
|
|
3933
4779
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -3941,7 +4787,7 @@ var EulerV2Adapter = class {
|
|
|
3941
4787
|
};
|
|
3942
4788
|
}
|
|
3943
4789
|
async buildBorrow(params) {
|
|
3944
|
-
const data =
|
|
4790
|
+
const data = encodeFunctionData15({
|
|
3945
4791
|
abi: EULER_VAULT_ABI,
|
|
3946
4792
|
functionName: "borrow",
|
|
3947
4793
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -3955,7 +4801,7 @@ var EulerV2Adapter = class {
|
|
|
3955
4801
|
};
|
|
3956
4802
|
}
|
|
3957
4803
|
async buildRepay(params) {
|
|
3958
|
-
const data =
|
|
4804
|
+
const data = encodeFunctionData15({
|
|
3959
4805
|
abi: EULER_VAULT_ABI,
|
|
3960
4806
|
functionName: "repay",
|
|
3961
4807
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -3969,7 +4815,7 @@ var EulerV2Adapter = class {
|
|
|
3969
4815
|
};
|
|
3970
4816
|
}
|
|
3971
4817
|
async buildWithdraw(params) {
|
|
3972
|
-
const data =
|
|
4818
|
+
const data = encodeFunctionData15({
|
|
3973
4819
|
abi: EULER_VAULT_ABI,
|
|
3974
4820
|
functionName: "withdraw",
|
|
3975
4821
|
args: [params.amount, params.to, params.to]
|
|
@@ -4018,7 +4864,7 @@ var EulerV2Adapter = class {
|
|
|
4018
4864
|
);
|
|
4019
4865
|
}
|
|
4020
4866
|
};
|
|
4021
|
-
var MORPHO_ABI =
|
|
4867
|
+
var MORPHO_ABI = parseAbi17([
|
|
4022
4868
|
"function market(bytes32 id) external view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)",
|
|
4023
4869
|
"function idToMarketParams(bytes32 id) external view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)",
|
|
4024
4870
|
"function supply((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, uint256 shares, address onBehalf, bytes data) external returns (uint256 assetsSupplied, uint256 sharesSupplied)",
|
|
@@ -4026,13 +4872,13 @@ var MORPHO_ABI = parseAbi16([
|
|
|
4026
4872
|
"function repay((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, uint256 shares, address onBehalf, bytes data) external returns (uint256 assetsRepaid, uint256 sharesRepaid)",
|
|
4027
4873
|
"function withdraw((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, uint256 shares, address onBehalf, address receiver) external returns (uint256 assetsWithdrawn, uint256 sharesWithdrawn)"
|
|
4028
4874
|
]);
|
|
4029
|
-
var META_MORPHO_ABI =
|
|
4875
|
+
var META_MORPHO_ABI = parseAbi17([
|
|
4030
4876
|
"function supplyQueueLength() external view returns (uint256)",
|
|
4031
4877
|
"function supplyQueue(uint256 index) external view returns (bytes32)",
|
|
4032
4878
|
"function totalAssets() external view returns (uint256)",
|
|
4033
4879
|
"function totalSupply() external view returns (uint256)"
|
|
4034
4880
|
]);
|
|
4035
|
-
var IRM_ABI =
|
|
4881
|
+
var IRM_ABI = parseAbi17([
|
|
4036
4882
|
"function borrowRateView((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee) market) external view returns (uint256)"
|
|
4037
4883
|
]);
|
|
4038
4884
|
var SECONDS_PER_YEAR3 = 365.25 * 24 * 3600;
|
|
@@ -4045,6 +4891,30 @@ function defaultMarketParams(loanToken = zeroAddress7) {
|
|
|
4045
4891
|
lltv: 0n
|
|
4046
4892
|
};
|
|
4047
4893
|
}
|
|
4894
|
+
function decodeMarket(data) {
|
|
4895
|
+
if (!data) return null;
|
|
4896
|
+
try {
|
|
4897
|
+
return decodeFunctionResult4({
|
|
4898
|
+
abi: MORPHO_ABI,
|
|
4899
|
+
functionName: "market",
|
|
4900
|
+
data
|
|
4901
|
+
});
|
|
4902
|
+
} catch {
|
|
4903
|
+
return null;
|
|
4904
|
+
}
|
|
4905
|
+
}
|
|
4906
|
+
function decodeMarketParams(data) {
|
|
4907
|
+
if (!data) return null;
|
|
4908
|
+
try {
|
|
4909
|
+
return decodeFunctionResult4({
|
|
4910
|
+
abi: MORPHO_ABI,
|
|
4911
|
+
functionName: "idToMarketParams",
|
|
4912
|
+
data
|
|
4913
|
+
});
|
|
4914
|
+
} catch {
|
|
4915
|
+
return null;
|
|
4916
|
+
}
|
|
4917
|
+
}
|
|
4048
4918
|
var MorphoBlueAdapter = class {
|
|
4049
4919
|
protocolName;
|
|
4050
4920
|
morpho;
|
|
@@ -4064,7 +4934,7 @@ var MorphoBlueAdapter = class {
|
|
|
4064
4934
|
}
|
|
4065
4935
|
async buildSupply(params) {
|
|
4066
4936
|
const market = defaultMarketParams(params.asset);
|
|
4067
|
-
const data =
|
|
4937
|
+
const data = encodeFunctionData16({
|
|
4068
4938
|
abi: MORPHO_ABI,
|
|
4069
4939
|
functionName: "supply",
|
|
4070
4940
|
args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
|
|
@@ -4079,7 +4949,7 @@ var MorphoBlueAdapter = class {
|
|
|
4079
4949
|
}
|
|
4080
4950
|
async buildBorrow(params) {
|
|
4081
4951
|
const market = defaultMarketParams(params.asset);
|
|
4082
|
-
const data =
|
|
4952
|
+
const data = encodeFunctionData16({
|
|
4083
4953
|
abi: MORPHO_ABI,
|
|
4084
4954
|
functionName: "borrow",
|
|
4085
4955
|
args: [market, params.amount, 0n, params.on_behalf_of, params.on_behalf_of]
|
|
@@ -4094,7 +4964,7 @@ var MorphoBlueAdapter = class {
|
|
|
4094
4964
|
}
|
|
4095
4965
|
async buildRepay(params) {
|
|
4096
4966
|
const market = defaultMarketParams(params.asset);
|
|
4097
|
-
const data =
|
|
4967
|
+
const data = encodeFunctionData16({
|
|
4098
4968
|
abi: MORPHO_ABI,
|
|
4099
4969
|
functionName: "repay",
|
|
4100
4970
|
args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
|
|
@@ -4109,7 +4979,7 @@ var MorphoBlueAdapter = class {
|
|
|
4109
4979
|
}
|
|
4110
4980
|
async buildWithdraw(params) {
|
|
4111
4981
|
const market = defaultMarketParams(params.asset);
|
|
4112
|
-
const data =
|
|
4982
|
+
const data = encodeFunctionData16({
|
|
4113
4983
|
abi: MORPHO_ABI,
|
|
4114
4984
|
functionName: "withdraw",
|
|
4115
4985
|
args: [market, params.amount, 0n, params.to, params.to]
|
|
@@ -4127,14 +4997,12 @@ var MorphoBlueAdapter = class {
|
|
|
4127
4997
|
if (!this.defaultVault) {
|
|
4128
4998
|
throw DefiError.contractError(`[${this.protocolName}] No MetaMorpho vault configured for rate query`);
|
|
4129
4999
|
}
|
|
4130
|
-
const
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
abi: META_MORPHO_ABI,
|
|
4134
|
-
functionName: "supplyQueueLength"
|
|
4135
|
-
}).catch((e) => {
|
|
5000
|
+
const [queueLenRaw] = await multicallRead(this.rpcUrl, [
|
|
5001
|
+
[this.defaultVault, encodeFunctionData16({ abi: META_MORPHO_ABI, functionName: "supplyQueueLength" })]
|
|
5002
|
+
]).catch((e) => {
|
|
4136
5003
|
throw DefiError.rpcError(`[${this.protocolName}] supplyQueueLength failed: ${e}`);
|
|
4137
5004
|
});
|
|
5005
|
+
const queueLen = decodeU256(queueLenRaw ?? null);
|
|
4138
5006
|
if (queueLen === 0n) {
|
|
4139
5007
|
return {
|
|
4140
5008
|
protocol: this.protocolName,
|
|
@@ -4146,45 +5014,40 @@ var MorphoBlueAdapter = class {
|
|
|
4146
5014
|
total_borrow: 0n
|
|
4147
5015
|
};
|
|
4148
5016
|
}
|
|
4149
|
-
const
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
functionName: "supplyQueue",
|
|
4153
|
-
args: [0n]
|
|
4154
|
-
}).catch((e) => {
|
|
5017
|
+
const [marketIdRaw] = await multicallRead(this.rpcUrl, [
|
|
5018
|
+
[this.defaultVault, encodeFunctionData16({ abi: META_MORPHO_ABI, functionName: "supplyQueue", args: [0n] })]
|
|
5019
|
+
]).catch((e) => {
|
|
4155
5020
|
throw DefiError.rpcError(`[${this.protocolName}] supplyQueue(0) failed: ${e}`);
|
|
4156
5021
|
});
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
5022
|
+
if (!marketIdRaw || marketIdRaw.length < 66) {
|
|
5023
|
+
throw DefiError.rpcError(`[${this.protocolName}] supplyQueue(0) returned no data`);
|
|
5024
|
+
}
|
|
5025
|
+
const marketId = marketIdRaw.slice(0, 66);
|
|
5026
|
+
const [marketRaw, paramsRaw] = await multicallRead(this.rpcUrl, [
|
|
5027
|
+
[this.morpho, encodeFunctionData16({ abi: MORPHO_ABI, functionName: "market", args: [marketId] })],
|
|
5028
|
+
[this.morpho, encodeFunctionData16({ abi: MORPHO_ABI, functionName: "idToMarketParams", args: [marketId] })]
|
|
5029
|
+
]).catch((e) => {
|
|
5030
|
+
throw DefiError.rpcError(`[${this.protocolName}] market/idToMarketParams failed: ${e}`);
|
|
4164
5031
|
});
|
|
4165
|
-
const
|
|
5032
|
+
const mktDecoded = decodeMarket(marketRaw ?? null);
|
|
5033
|
+
if (!mktDecoded) throw DefiError.rpcError(`[${this.protocolName}] market() returned no data`);
|
|
5034
|
+
const [totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee] = mktDecoded;
|
|
5035
|
+
const paramsDecoded = decodeMarketParams(paramsRaw ?? null);
|
|
5036
|
+
if (!paramsDecoded) throw DefiError.rpcError(`[${this.protocolName}] idToMarketParams returned no data`);
|
|
5037
|
+
const [loanToken, collateralToken, oracle, irm, lltv] = paramsDecoded;
|
|
4166
5038
|
const supplyF = Number(totalSupplyAssets);
|
|
4167
5039
|
const borrowF = Number(totalBorrowAssets);
|
|
4168
5040
|
const util = supplyF > 0 ? borrowF / supplyF : 0;
|
|
4169
|
-
const params2 = await client.readContract({
|
|
4170
|
-
address: this.morpho,
|
|
4171
|
-
abi: MORPHO_ABI,
|
|
4172
|
-
functionName: "idToMarketParams",
|
|
4173
|
-
args: [marketId]
|
|
4174
|
-
}).catch((e) => {
|
|
4175
|
-
throw DefiError.rpcError(`[${this.protocolName}] idToMarketParams failed: ${e}`);
|
|
4176
|
-
});
|
|
4177
|
-
const [loanToken, collateralToken, oracle, irm, lltv] = params2;
|
|
4178
5041
|
const irmMarketParams = { loanToken, collateralToken, oracle, irm, lltv };
|
|
4179
5042
|
const irmMarket = { totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee };
|
|
4180
|
-
const borrowRatePerSec = await
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
});
|
|
5043
|
+
const borrowRatePerSec = await (async () => {
|
|
5044
|
+
const [borrowRateRaw] = await multicallRead(this.rpcUrl, [
|
|
5045
|
+
[irm, encodeFunctionData16({ abi: IRM_ABI, functionName: "borrowRateView", args: [irmMarketParams, irmMarket] })]
|
|
5046
|
+
]).catch((e) => {
|
|
5047
|
+
throw DefiError.rpcError(`[${this.protocolName}] borrowRateView failed: ${e}`);
|
|
5048
|
+
});
|
|
5049
|
+
return decodeU256(borrowRateRaw ?? null);
|
|
5050
|
+
})();
|
|
4188
5051
|
const ratePerSec = Number(borrowRatePerSec) / 1e18;
|
|
4189
5052
|
const borrowApy = ratePerSec * SECONDS_PER_YEAR3 * 100;
|
|
4190
5053
|
const feePct = Number(fee) / 1e18;
|
|
@@ -4205,18 +5068,18 @@ var MorphoBlueAdapter = class {
|
|
|
4205
5068
|
);
|
|
4206
5069
|
}
|
|
4207
5070
|
};
|
|
4208
|
-
var BORROWER_OPS_ABI =
|
|
5071
|
+
var BORROWER_OPS_ABI = parseAbi18([
|
|
4209
5072
|
"function openTrove(address _owner, uint256 _ownerIndex, uint256 _collAmount, uint256 _boldAmount, uint256 _upperHint, uint256 _lowerHint, uint256 _annualInterestRate, uint256 _maxUpfrontFee, address _addManager, address _removeManager, address _receiver) external returns (uint256)",
|
|
4210
5073
|
"function adjustTrove(uint256 _troveId, uint256 _collChange, bool _isCollIncrease, uint256 _debtChange, bool _isDebtIncrease, uint256 _upperHint, uint256 _lowerHint, uint256 _maxUpfrontFee) external",
|
|
4211
5074
|
"function closeTrove(uint256 _troveId) external"
|
|
4212
5075
|
]);
|
|
4213
|
-
var TROVE_MANAGER_ABI =
|
|
5076
|
+
var TROVE_MANAGER_ABI = parseAbi18([
|
|
4214
5077
|
"function getLatestTroveData(uint256 _troveId) external view returns (uint256 entireDebt, uint256 entireColl, uint256 redistDebtGain, uint256 redistCollGain, uint256 accruedInterest, uint256 recordedDebt, uint256 annualInterestRate, uint256 accruedBatchManagementFee, uint256 weightedRecordedDebt, uint256 lastInterestRateAdjTime)"
|
|
4215
5078
|
]);
|
|
4216
|
-
var HINT_HELPERS_ABI =
|
|
5079
|
+
var HINT_HELPERS_ABI = parseAbi18([
|
|
4217
5080
|
"function getApproxHint(uint256 _collIndex, uint256 _interestRate, uint256 _numTrials, uint256 _inputRandomSeed) external view returns (uint256 hintId, uint256 diff, uint256 latestRandomSeed)"
|
|
4218
5081
|
]);
|
|
4219
|
-
var SORTED_TROVES_ABI =
|
|
5082
|
+
var SORTED_TROVES_ABI = parseAbi18([
|
|
4220
5083
|
"function findInsertPosition(uint256 _annualInterestRate, uint256 _prevId, uint256 _nextId) external view returns (uint256 prevId, uint256 nextId)"
|
|
4221
5084
|
]);
|
|
4222
5085
|
var FelixCdpAdapter = class {
|
|
@@ -4244,7 +5107,7 @@ var FelixCdpAdapter = class {
|
|
|
4244
5107
|
if (!this.hintHelpers || !this.sortedTroves || !this.rpcUrl) {
|
|
4245
5108
|
return [0n, 0n];
|
|
4246
5109
|
}
|
|
4247
|
-
const client =
|
|
5110
|
+
const client = createPublicClient13({ transport: http13(this.rpcUrl) });
|
|
4248
5111
|
const approxResult = await client.readContract({
|
|
4249
5112
|
address: this.hintHelpers,
|
|
4250
5113
|
abi: HINT_HELPERS_ABI,
|
|
@@ -4267,7 +5130,7 @@ var FelixCdpAdapter = class {
|
|
|
4267
5130
|
const interestRate = 50000000000000000n;
|
|
4268
5131
|
const [upperHint, lowerHint] = await this.getHints(interestRate);
|
|
4269
5132
|
const hasHints = upperHint !== 0n || lowerHint !== 0n;
|
|
4270
|
-
const data =
|
|
5133
|
+
const data = encodeFunctionData17({
|
|
4271
5134
|
abi: BORROWER_OPS_ABI,
|
|
4272
5135
|
functionName: "openTrove",
|
|
4273
5136
|
args: [
|
|
@@ -4296,7 +5159,7 @@ var FelixCdpAdapter = class {
|
|
|
4296
5159
|
async buildAdjust(params) {
|
|
4297
5160
|
const collChange = params.collateral_delta ?? 0n;
|
|
4298
5161
|
const debtChange = params.debt_delta ?? 0n;
|
|
4299
|
-
const data =
|
|
5162
|
+
const data = encodeFunctionData17({
|
|
4300
5163
|
abi: BORROWER_OPS_ABI,
|
|
4301
5164
|
functionName: "adjustTrove",
|
|
4302
5165
|
args: [
|
|
@@ -4319,7 +5182,7 @@ var FelixCdpAdapter = class {
|
|
|
4319
5182
|
};
|
|
4320
5183
|
}
|
|
4321
5184
|
async buildClose(params) {
|
|
4322
|
-
const data =
|
|
5185
|
+
const data = encodeFunctionData17({
|
|
4323
5186
|
abi: BORROWER_OPS_ABI,
|
|
4324
5187
|
functionName: "closeTrove",
|
|
4325
5188
|
args: [params.cdp_id]
|
|
@@ -4335,7 +5198,7 @@ var FelixCdpAdapter = class {
|
|
|
4335
5198
|
async getCdpInfo(cdpId) {
|
|
4336
5199
|
if (!this.rpcUrl) throw DefiError.rpcError(`[${this.protocolName}] getCdpInfo requires RPC \u2014 set HYPEREVM_RPC_URL`);
|
|
4337
5200
|
if (!this.troveManager) throw DefiError.contractError(`[${this.protocolName}] trove_manager contract not configured`);
|
|
4338
|
-
const client =
|
|
5201
|
+
const client = createPublicClient13({ transport: http13(this.rpcUrl) });
|
|
4339
5202
|
const data = await client.readContract({
|
|
4340
5203
|
address: this.troveManager,
|
|
4341
5204
|
abi: TROVE_MANAGER_ABI,
|
|
@@ -4368,7 +5231,7 @@ var FelixCdpAdapter = class {
|
|
|
4368
5231
|
};
|
|
4369
5232
|
}
|
|
4370
5233
|
};
|
|
4371
|
-
var PRICE_FEED_ABI =
|
|
5234
|
+
var PRICE_FEED_ABI = parseAbi19([
|
|
4372
5235
|
"function fetchPrice() external view returns (uint256 price, bool isNewOracleFailureDetected)",
|
|
4373
5236
|
"function lastGoodPrice() external view returns (uint256)"
|
|
4374
5237
|
]);
|
|
@@ -4394,7 +5257,7 @@ var FelixOracleAdapter = class {
|
|
|
4394
5257
|
if (asset !== this.asset && this.asset !== "0x0000000000000000000000000000000000000000") {
|
|
4395
5258
|
throw DefiError.unsupported(`[${this.protocolName}] Felix PriceFeed only supports asset ${this.asset}`);
|
|
4396
5259
|
}
|
|
4397
|
-
const client =
|
|
5260
|
+
const client = createPublicClient14({ transport: http14(this.rpcUrl) });
|
|
4398
5261
|
let priceVal;
|
|
4399
5262
|
try {
|
|
4400
5263
|
const result = await client.readContract({
|
|
@@ -4433,7 +5296,7 @@ var FelixOracleAdapter = class {
|
|
|
4433
5296
|
return results;
|
|
4434
5297
|
}
|
|
4435
5298
|
};
|
|
4436
|
-
var ERC4626_ABI =
|
|
5299
|
+
var ERC4626_ABI = parseAbi20([
|
|
4437
5300
|
"function asset() external view returns (address)",
|
|
4438
5301
|
"function totalAssets() external view returns (uint256)",
|
|
4439
5302
|
"function totalSupply() external view returns (uint256)",
|
|
@@ -4457,7 +5320,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4457
5320
|
return this.protocolName;
|
|
4458
5321
|
}
|
|
4459
5322
|
async buildDeposit(assets, receiver) {
|
|
4460
|
-
const data =
|
|
5323
|
+
const data = encodeFunctionData18({
|
|
4461
5324
|
abi: ERC4626_ABI,
|
|
4462
5325
|
functionName: "deposit",
|
|
4463
5326
|
args: [assets, receiver]
|
|
@@ -4471,7 +5334,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4471
5334
|
};
|
|
4472
5335
|
}
|
|
4473
5336
|
async buildWithdraw(assets, receiver, owner) {
|
|
4474
|
-
const data =
|
|
5337
|
+
const data = encodeFunctionData18({
|
|
4475
5338
|
abi: ERC4626_ABI,
|
|
4476
5339
|
functionName: "withdraw",
|
|
4477
5340
|
args: [assets, receiver, owner]
|
|
@@ -4486,7 +5349,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4486
5349
|
}
|
|
4487
5350
|
async totalAssets() {
|
|
4488
5351
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4489
|
-
const client =
|
|
5352
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4490
5353
|
return client.readContract({
|
|
4491
5354
|
address: this.vaultAddress,
|
|
4492
5355
|
abi: ERC4626_ABI,
|
|
@@ -4497,7 +5360,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4497
5360
|
}
|
|
4498
5361
|
async convertToShares(assets) {
|
|
4499
5362
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4500
|
-
const client =
|
|
5363
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4501
5364
|
return client.readContract({
|
|
4502
5365
|
address: this.vaultAddress,
|
|
4503
5366
|
abi: ERC4626_ABI,
|
|
@@ -4509,7 +5372,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4509
5372
|
}
|
|
4510
5373
|
async convertToAssets(shares) {
|
|
4511
5374
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4512
|
-
const client =
|
|
5375
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4513
5376
|
return client.readContract({
|
|
4514
5377
|
address: this.vaultAddress,
|
|
4515
5378
|
abi: ERC4626_ABI,
|
|
@@ -4521,7 +5384,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4521
5384
|
}
|
|
4522
5385
|
async getVaultInfo() {
|
|
4523
5386
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4524
|
-
const client =
|
|
5387
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4525
5388
|
const [totalAssets, totalSupply, asset] = await Promise.all([
|
|
4526
5389
|
client.readContract({ address: this.vaultAddress, abi: ERC4626_ABI, functionName: "totalAssets" }).catch((e) => {
|
|
4527
5390
|
throw DefiError.rpcError(`[${this.protocolName}] totalAssets failed: ${e}`);
|
|
@@ -4542,7 +5405,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4542
5405
|
};
|
|
4543
5406
|
}
|
|
4544
5407
|
};
|
|
4545
|
-
var GENERIC_LST_ABI =
|
|
5408
|
+
var GENERIC_LST_ABI = parseAbi21([
|
|
4546
5409
|
"function stake() external payable returns (uint256)",
|
|
4547
5410
|
"function unstake(uint256 amount) external returns (uint256)"
|
|
4548
5411
|
]);
|
|
@@ -4559,7 +5422,7 @@ var GenericLstAdapter = class {
|
|
|
4559
5422
|
return this.protocolName;
|
|
4560
5423
|
}
|
|
4561
5424
|
async buildStake(params) {
|
|
4562
|
-
const data =
|
|
5425
|
+
const data = encodeFunctionData19({ abi: GENERIC_LST_ABI, functionName: "stake" });
|
|
4563
5426
|
return {
|
|
4564
5427
|
description: `[${this.protocolName}] Stake ${params.amount} HYPE`,
|
|
4565
5428
|
to: this.staking,
|
|
@@ -4569,7 +5432,7 @@ var GenericLstAdapter = class {
|
|
|
4569
5432
|
};
|
|
4570
5433
|
}
|
|
4571
5434
|
async buildUnstake(params) {
|
|
4572
|
-
const data =
|
|
5435
|
+
const data = encodeFunctionData19({
|
|
4573
5436
|
abi: GENERIC_LST_ABI,
|
|
4574
5437
|
functionName: "unstake",
|
|
4575
5438
|
args: [params.amount]
|
|
@@ -4586,11 +5449,11 @@ var GenericLstAdapter = class {
|
|
|
4586
5449
|
throw DefiError.unsupported(`[${this.protocolName}] getInfo requires RPC`);
|
|
4587
5450
|
}
|
|
4588
5451
|
};
|
|
4589
|
-
var STHYPE_ABI =
|
|
5452
|
+
var STHYPE_ABI = parseAbi222([
|
|
4590
5453
|
"function submit(address referral) external payable returns (uint256)",
|
|
4591
5454
|
"function requestWithdrawals(uint256[] amounts, address owner) external returns (uint256[] requestIds)"
|
|
4592
5455
|
]);
|
|
4593
|
-
var ERC20_ABI3 =
|
|
5456
|
+
var ERC20_ABI3 = parseAbi222([
|
|
4594
5457
|
"function totalSupply() external view returns (uint256)"
|
|
4595
5458
|
]);
|
|
4596
5459
|
var StHypeAdapter = class {
|
|
@@ -4610,7 +5473,7 @@ var StHypeAdapter = class {
|
|
|
4610
5473
|
return this.protocolName;
|
|
4611
5474
|
}
|
|
4612
5475
|
async buildStake(params) {
|
|
4613
|
-
const data =
|
|
5476
|
+
const data = encodeFunctionData20({
|
|
4614
5477
|
abi: STHYPE_ABI,
|
|
4615
5478
|
functionName: "submit",
|
|
4616
5479
|
args: [zeroAddress9]
|
|
@@ -4624,7 +5487,7 @@ var StHypeAdapter = class {
|
|
|
4624
5487
|
};
|
|
4625
5488
|
}
|
|
4626
5489
|
async buildUnstake(params) {
|
|
4627
|
-
const data =
|
|
5490
|
+
const data = encodeFunctionData20({
|
|
4628
5491
|
abi: STHYPE_ABI,
|
|
4629
5492
|
functionName: "requestWithdrawals",
|
|
4630
5493
|
args: [[params.amount], params.recipient]
|
|
@@ -4639,7 +5502,7 @@ var StHypeAdapter = class {
|
|
|
4639
5502
|
}
|
|
4640
5503
|
async getInfo() {
|
|
4641
5504
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4642
|
-
const client =
|
|
5505
|
+
const client = createPublicClient16({ transport: http16(this.rpcUrl) });
|
|
4643
5506
|
const tokenAddr = this.sthypeToken ?? this.staking;
|
|
4644
5507
|
const totalSupply = await client.readContract({
|
|
4645
5508
|
address: tokenAddr,
|
|
@@ -4657,12 +5520,12 @@ var StHypeAdapter = class {
|
|
|
4657
5520
|
};
|
|
4658
5521
|
}
|
|
4659
5522
|
};
|
|
4660
|
-
var KINETIQ_ABI =
|
|
5523
|
+
var KINETIQ_ABI = parseAbi23([
|
|
4661
5524
|
"function stake() external payable returns (uint256)",
|
|
4662
5525
|
"function requestUnstake(uint256 amount) external returns (uint256)",
|
|
4663
5526
|
"function totalStaked() external view returns (uint256)"
|
|
4664
5527
|
]);
|
|
4665
|
-
var ORACLE_ABI3 =
|
|
5528
|
+
var ORACLE_ABI3 = parseAbi23([
|
|
4666
5529
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
4667
5530
|
]);
|
|
4668
5531
|
var WHYPE = "0x5555555555555555555555555555555555555555";
|
|
@@ -4684,7 +5547,7 @@ var KinetiqAdapter = class {
|
|
|
4684
5547
|
return this.protocolName;
|
|
4685
5548
|
}
|
|
4686
5549
|
async buildStake(params) {
|
|
4687
|
-
const data =
|
|
5550
|
+
const data = encodeFunctionData21({ abi: KINETIQ_ABI, functionName: "stake" });
|
|
4688
5551
|
return {
|
|
4689
5552
|
description: `[${this.protocolName}] Stake ${params.amount} HYPE for kHYPE`,
|
|
4690
5553
|
to: this.staking,
|
|
@@ -4694,7 +5557,7 @@ var KinetiqAdapter = class {
|
|
|
4694
5557
|
};
|
|
4695
5558
|
}
|
|
4696
5559
|
async buildUnstake(params) {
|
|
4697
|
-
const data =
|
|
5560
|
+
const data = encodeFunctionData21({
|
|
4698
5561
|
abi: KINETIQ_ABI,
|
|
4699
5562
|
functionName: "requestUnstake",
|
|
4700
5563
|
args: [params.amount]
|
|
@@ -4709,7 +5572,7 @@ var KinetiqAdapter = class {
|
|
|
4709
5572
|
}
|
|
4710
5573
|
async getInfo() {
|
|
4711
5574
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4712
|
-
const client =
|
|
5575
|
+
const client = createPublicClient17({ transport: http17(this.rpcUrl) });
|
|
4713
5576
|
const totalStaked = await client.readContract({
|
|
4714
5577
|
address: this.staking,
|
|
4715
5578
|
abi: KINETIQ_ABI,
|
|
@@ -4731,15 +5594,15 @@ var KinetiqAdapter = class {
|
|
|
4731
5594
|
};
|
|
4732
5595
|
}
|
|
4733
5596
|
};
|
|
4734
|
-
var HLP_ABI =
|
|
5597
|
+
var HLP_ABI = parseAbi24([
|
|
4735
5598
|
"function deposit(uint256 amount) external returns (uint256)",
|
|
4736
5599
|
"function withdraw(uint256 shares) external returns (uint256)"
|
|
4737
5600
|
]);
|
|
4738
|
-
var RYSK_ABI =
|
|
5601
|
+
var RYSK_ABI = parseAbi25([
|
|
4739
5602
|
"function openOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 premium)",
|
|
4740
5603
|
"function closeOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 payout)"
|
|
4741
5604
|
]);
|
|
4742
|
-
var ERC721_ABI =
|
|
5605
|
+
var ERC721_ABI = parseAbi26([
|
|
4743
5606
|
"function name() returns (string)",
|
|
4744
5607
|
"function symbol() returns (string)",
|
|
4745
5608
|
"function totalSupply() returns (uint256)",
|
|
@@ -4759,7 +5622,7 @@ var ERC721Adapter = class {
|
|
|
4759
5622
|
}
|
|
4760
5623
|
async getCollectionInfo(collection) {
|
|
4761
5624
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4762
|
-
const client =
|
|
5625
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
4763
5626
|
const [collectionName, symbol, totalSupply] = await Promise.all([
|
|
4764
5627
|
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "name" }).catch((e) => {
|
|
4765
5628
|
throw DefiError.rpcError(`[${this.protocolName}] name failed: ${e}`);
|
|
@@ -4778,7 +5641,7 @@ var ERC721Adapter = class {
|
|
|
4778
5641
|
}
|
|
4779
5642
|
async getTokenInfo(collection, tokenId) {
|
|
4780
5643
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4781
|
-
const client =
|
|
5644
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
4782
5645
|
const [owner, tokenUri] = await Promise.all([
|
|
4783
5646
|
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "ownerOf", args: [tokenId] }).catch((e) => {
|
|
4784
5647
|
throw DefiError.rpcError(`[${this.protocolName}] ownerOf failed: ${e}`);
|
|
@@ -4794,7 +5657,7 @@ var ERC721Adapter = class {
|
|
|
4794
5657
|
}
|
|
4795
5658
|
async getBalance(owner, collection) {
|
|
4796
5659
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4797
|
-
const client =
|
|
5660
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
4798
5661
|
return client.readContract({ address: collection, abi: ERC721_ABI, functionName: "balanceOf", args: [owner] }).catch((e) => {
|
|
4799
5662
|
throw DefiError.rpcError(`[${this.protocolName}] balanceOf failed: ${e}`);
|
|
4800
5663
|
});
|
|
@@ -4915,6 +5778,9 @@ function createOracleFromCdp(entry, _asset, rpcUrl) {
|
|
|
4915
5778
|
throw DefiError.unsupported(`Oracle not available for CDP interface '${entry.interface}'`);
|
|
4916
5779
|
}
|
|
4917
5780
|
}
|
|
5781
|
+
function createMerchantMoeLB(entry, rpcUrl) {
|
|
5782
|
+
return new MerchantMoeLBAdapter(entry, rpcUrl);
|
|
5783
|
+
}
|
|
4918
5784
|
var DexSpotPrice = class {
|
|
4919
5785
|
/**
|
|
4920
5786
|
* Get the spot price for `token` denominated in `quoteToken` (e.g. USDC).
|
|
@@ -5922,20 +6788,20 @@ function registerYield(parent, getOpts, makeExecutor2) {
|
|
|
5922
6788
|
}
|
|
5923
6789
|
|
|
5924
6790
|
// src/commands/portfolio.ts
|
|
5925
|
-
import { encodeFunctionData as
|
|
6791
|
+
import { encodeFunctionData as encodeFunctionData25, parseAbi as parseAbi28 } from "viem";
|
|
5926
6792
|
|
|
5927
6793
|
// src/portfolio-tracker.ts
|
|
5928
6794
|
import { mkdirSync, writeFileSync, readdirSync as readdirSync2, readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
5929
6795
|
import { homedir } from "os";
|
|
5930
6796
|
import { resolve as resolve2 } from "path";
|
|
5931
|
-
import { encodeFunctionData as
|
|
5932
|
-
var ERC20_ABI4 =
|
|
6797
|
+
import { encodeFunctionData as encodeFunctionData24, parseAbi as parseAbi27 } from "viem";
|
|
6798
|
+
var ERC20_ABI4 = parseAbi27([
|
|
5933
6799
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
5934
6800
|
]);
|
|
5935
|
-
var ORACLE_ABI4 =
|
|
6801
|
+
var ORACLE_ABI4 = parseAbi27([
|
|
5936
6802
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
5937
6803
|
]);
|
|
5938
|
-
var POOL_ABI3 =
|
|
6804
|
+
var POOL_ABI3 = parseAbi27([
|
|
5939
6805
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
5940
6806
|
]);
|
|
5941
6807
|
function decodeU256Word(data, wordOffset = 0) {
|
|
@@ -5964,7 +6830,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
5964
6830
|
tokenEntries.push({ symbol: t.symbol, address: entry.address, decimals: entry.decimals });
|
|
5965
6831
|
calls.push([
|
|
5966
6832
|
entry.address,
|
|
5967
|
-
|
|
6833
|
+
encodeFunctionData24({ abi: ERC20_ABI4, functionName: "balanceOf", args: [user] })
|
|
5968
6834
|
]);
|
|
5969
6835
|
callLabels.push(`balance:${t.symbol}`);
|
|
5970
6836
|
}
|
|
@@ -5972,7 +6838,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
5972
6838
|
for (const p of lendingProtocols) {
|
|
5973
6839
|
calls.push([
|
|
5974
6840
|
p.contracts["pool"],
|
|
5975
|
-
|
|
6841
|
+
encodeFunctionData24({ abi: POOL_ABI3, functionName: "getUserAccountData", args: [user] })
|
|
5976
6842
|
]);
|
|
5977
6843
|
callLabels.push(`lending:${p.name}`);
|
|
5978
6844
|
}
|
|
@@ -5982,7 +6848,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
5982
6848
|
if (oracleAddr) {
|
|
5983
6849
|
calls.push([
|
|
5984
6850
|
oracleAddr,
|
|
5985
|
-
|
|
6851
|
+
encodeFunctionData24({ abi: ORACLE_ABI4, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
5986
6852
|
]);
|
|
5987
6853
|
callLabels.push("price:native");
|
|
5988
6854
|
}
|
|
@@ -6120,13 +6986,13 @@ function calculatePnL(current, previous) {
|
|
|
6120
6986
|
}
|
|
6121
6987
|
|
|
6122
6988
|
// src/commands/portfolio.ts
|
|
6123
|
-
var ERC20_ABI5 =
|
|
6989
|
+
var ERC20_ABI5 = parseAbi28([
|
|
6124
6990
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
6125
6991
|
]);
|
|
6126
|
-
var POOL_ABI4 =
|
|
6992
|
+
var POOL_ABI4 = parseAbi28([
|
|
6127
6993
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
6128
6994
|
]);
|
|
6129
|
-
var ORACLE_ABI5 =
|
|
6995
|
+
var ORACLE_ABI5 = parseAbi28([
|
|
6130
6996
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
6131
6997
|
]);
|
|
6132
6998
|
function decodeU2562(data, wordOffset = 0) {
|
|
@@ -6166,7 +7032,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6166
7032
|
if (entry.address === "0x0000000000000000000000000000000000000000") continue;
|
|
6167
7033
|
calls.push([
|
|
6168
7034
|
entry.address,
|
|
6169
|
-
|
|
7035
|
+
encodeFunctionData25({ abi: ERC20_ABI5, functionName: "balanceOf", args: [user] })
|
|
6170
7036
|
]);
|
|
6171
7037
|
callLabels.push(`balance:${symbol}`);
|
|
6172
7038
|
}
|
|
@@ -6174,7 +7040,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6174
7040
|
for (const p of lendingProtocols) {
|
|
6175
7041
|
calls.push([
|
|
6176
7042
|
p.contracts["pool"],
|
|
6177
|
-
|
|
7043
|
+
encodeFunctionData25({ abi: POOL_ABI4, functionName: "getUserAccountData", args: [user] })
|
|
6178
7044
|
]);
|
|
6179
7045
|
callLabels.push(`lending:${p.name}`);
|
|
6180
7046
|
}
|
|
@@ -6184,7 +7050,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6184
7050
|
if (oracleAddr) {
|
|
6185
7051
|
calls.push([
|
|
6186
7052
|
oracleAddr,
|
|
6187
|
-
|
|
7053
|
+
encodeFunctionData25({ abi: ORACLE_ABI5, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
6188
7054
|
]);
|
|
6189
7055
|
callLabels.push("price:native");
|
|
6190
7056
|
}
|
|
@@ -6546,14 +7412,14 @@ function registerAlert(parent, getOpts) {
|
|
|
6546
7412
|
}
|
|
6547
7413
|
|
|
6548
7414
|
// src/commands/scan.ts
|
|
6549
|
-
import { encodeFunctionData as
|
|
6550
|
-
var AAVE_ORACLE_ABI =
|
|
7415
|
+
import { encodeFunctionData as encodeFunctionData26, parseAbi as parseAbi29 } from "viem";
|
|
7416
|
+
var AAVE_ORACLE_ABI = parseAbi29([
|
|
6551
7417
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
6552
7418
|
]);
|
|
6553
|
-
var UNIV2_ROUTER_ABI =
|
|
7419
|
+
var UNIV2_ROUTER_ABI = parseAbi29([
|
|
6554
7420
|
"function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory)"
|
|
6555
7421
|
]);
|
|
6556
|
-
var VTOKEN_ABI =
|
|
7422
|
+
var VTOKEN_ABI = parseAbi29([
|
|
6557
7423
|
"function exchangeRateStored() external view returns (uint256)"
|
|
6558
7424
|
]);
|
|
6559
7425
|
var STABLECOINS = /* @__PURE__ */ new Set(["USDC", "USDT", "DAI", "USDT0"]);
|
|
@@ -6663,7 +7529,7 @@ function registerScan(parent, getOpts) {
|
|
|
6663
7529
|
callTypes.push({ kind: "oracle", oracle: oracle.name, token: token.symbol, oracleDecimals: oracle.decimals });
|
|
6664
7530
|
calls.push([
|
|
6665
7531
|
oracle.addr,
|
|
6666
|
-
|
|
7532
|
+
encodeFunctionData26({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })
|
|
6667
7533
|
]);
|
|
6668
7534
|
}
|
|
6669
7535
|
}
|
|
@@ -6674,7 +7540,7 @@ function registerScan(parent, getOpts) {
|
|
|
6674
7540
|
callTypes.push({ kind: "dex", token: token.symbol, outDecimals: quoteStable.decimals });
|
|
6675
7541
|
calls.push([
|
|
6676
7542
|
dexRouter,
|
|
6677
|
-
|
|
7543
|
+
encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [amountIn, path] })
|
|
6678
7544
|
]);
|
|
6679
7545
|
}
|
|
6680
7546
|
}
|
|
@@ -6683,7 +7549,7 @@ function registerScan(parent, getOpts) {
|
|
|
6683
7549
|
callTypes.push({ kind: "stable", from: "USDC", to: "USDT", outDecimals: usdt.decimals });
|
|
6684
7550
|
calls.push([
|
|
6685
7551
|
dexRouter,
|
|
6686
|
-
|
|
7552
|
+
encodeFunctionData26({
|
|
6687
7553
|
abi: UNIV2_ROUTER_ABI,
|
|
6688
7554
|
functionName: "getAmountsOut",
|
|
6689
7555
|
args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]]
|
|
@@ -6692,7 +7558,7 @@ function registerScan(parent, getOpts) {
|
|
|
6692
7558
|
callTypes.push({ kind: "stable", from: "USDT", to: "USDC", outDecimals: usdc.decimals });
|
|
6693
7559
|
calls.push([
|
|
6694
7560
|
dexRouter,
|
|
6695
|
-
|
|
7561
|
+
encodeFunctionData26({
|
|
6696
7562
|
abi: UNIV2_ROUTER_ABI,
|
|
6697
7563
|
functionName: "getAmountsOut",
|
|
6698
7564
|
args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]]
|
|
@@ -6703,7 +7569,7 @@ function registerScan(parent, getOpts) {
|
|
|
6703
7569
|
for (const fork of compoundForks) {
|
|
6704
7570
|
for (const { key, addr } of fork.vtokens) {
|
|
6705
7571
|
callTypes.push({ kind: "exchangeRate", protocol: fork.name, vtoken: key });
|
|
6706
|
-
calls.push([addr,
|
|
7572
|
+
calls.push([addr, encodeFunctionData26({ abi: VTOKEN_ABI, functionName: "exchangeRateStored", args: [] })]);
|
|
6707
7573
|
}
|
|
6708
7574
|
}
|
|
6709
7575
|
}
|
|
@@ -6921,22 +7787,22 @@ async function runAllChains(registry, patterns, oracleThreshold, stableThreshold
|
|
|
6921
7787
|
for (const oracle of oracles) {
|
|
6922
7788
|
for (const token of scanTokens) {
|
|
6923
7789
|
cts.push({ kind: "oracle", oracle: oracle.name, token: token.symbol, dec: oracle.decimals });
|
|
6924
|
-
calls.push([oracle.addr,
|
|
7790
|
+
calls.push([oracle.addr, encodeFunctionData26({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })]);
|
|
6925
7791
|
}
|
|
6926
7792
|
}
|
|
6927
7793
|
if (dexRouter) {
|
|
6928
7794
|
for (const token of scanTokens) {
|
|
6929
7795
|
const path = wrappedNative && token.address.toLowerCase() === wrappedNative.toLowerCase() ? [token.address, quoteStable.address] : wrappedNative ? [token.address, wrappedNative, quoteStable.address] : [token.address, quoteStable.address];
|
|
6930
7796
|
cts.push({ kind: "dex", token: token.symbol, dec: quoteStable.decimals });
|
|
6931
|
-
calls.push([dexRouter,
|
|
7797
|
+
calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(token.decimals), path] })]);
|
|
6932
7798
|
}
|
|
6933
7799
|
}
|
|
6934
7800
|
}
|
|
6935
7801
|
if (doStable && usdc && usdt && dexRouter) {
|
|
6936
7802
|
cts.push({ kind: "stable", from: "USDC", to: "USDT", dec: usdt.decimals });
|
|
6937
|
-
calls.push([dexRouter,
|
|
7803
|
+
calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]] })]);
|
|
6938
7804
|
cts.push({ kind: "stable", from: "USDT", to: "USDC", dec: usdc.decimals });
|
|
6939
|
-
calls.push([dexRouter,
|
|
7805
|
+
calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]] })]);
|
|
6940
7806
|
}
|
|
6941
7807
|
if (calls.length === 0) return null;
|
|
6942
7808
|
const ct0 = Date.now();
|
|
@@ -7064,14 +7930,14 @@ function registerArb(parent, getOpts, makeExecutor2) {
|
|
|
7064
7930
|
}
|
|
7065
7931
|
|
|
7066
7932
|
// src/commands/positions.ts
|
|
7067
|
-
import { encodeFunctionData as
|
|
7068
|
-
var ERC20_ABI6 =
|
|
7933
|
+
import { encodeFunctionData as encodeFunctionData27, parseAbi as parseAbi30 } from "viem";
|
|
7934
|
+
var ERC20_ABI6 = parseAbi30([
|
|
7069
7935
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
7070
7936
|
]);
|
|
7071
|
-
var POOL_ABI5 =
|
|
7937
|
+
var POOL_ABI5 = parseAbi30([
|
|
7072
7938
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
7073
7939
|
]);
|
|
7074
|
-
var ORACLE_ABI6 =
|
|
7940
|
+
var ORACLE_ABI6 = parseAbi30([
|
|
7075
7941
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
7076
7942
|
]);
|
|
7077
7943
|
function round22(x) {
|
|
@@ -7100,7 +7966,7 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7100
7966
|
callTypes.push({ kind: "token", symbol: token.symbol, decimals: token.decimals });
|
|
7101
7967
|
calls.push([
|
|
7102
7968
|
token.address,
|
|
7103
|
-
|
|
7969
|
+
encodeFunctionData27({ abi: ERC20_ABI6, functionName: "balanceOf", args: [user] })
|
|
7104
7970
|
]);
|
|
7105
7971
|
}
|
|
7106
7972
|
}
|
|
@@ -7108,14 +7974,14 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7108
7974
|
callTypes.push({ kind: "lending", protocol: name, iface });
|
|
7109
7975
|
calls.push([
|
|
7110
7976
|
pool,
|
|
7111
|
-
|
|
7977
|
+
encodeFunctionData27({ abi: POOL_ABI5, functionName: "getUserAccountData", args: [user] })
|
|
7112
7978
|
]);
|
|
7113
7979
|
}
|
|
7114
7980
|
if (oracleAddr) {
|
|
7115
7981
|
callTypes.push({ kind: "native_price" });
|
|
7116
7982
|
calls.push([
|
|
7117
7983
|
oracleAddr,
|
|
7118
|
-
|
|
7984
|
+
encodeFunctionData27({ abi: ORACLE_ABI6, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
7119
7985
|
]);
|
|
7120
7986
|
}
|
|
7121
7987
|
if (calls.length === 0) return null;
|
|
@@ -7408,14 +8274,14 @@ function registerPrice(parent, getOpts) {
|
|
|
7408
8274
|
}
|
|
7409
8275
|
|
|
7410
8276
|
// src/commands/wallet.ts
|
|
7411
|
-
import { createPublicClient as
|
|
8277
|
+
import { createPublicClient as createPublicClient19, http as http19, formatEther } from "viem";
|
|
7412
8278
|
function registerWallet(parent, getOpts) {
|
|
7413
8279
|
const wallet = parent.command("wallet").description("Wallet management");
|
|
7414
8280
|
wallet.command("balance").description("Show native token balance").requiredOption("--address <address>", "Wallet address to query").action(async (opts) => {
|
|
7415
8281
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7416
8282
|
const registry = Registry.loadEmbedded();
|
|
7417
8283
|
const chain = registry.getChain(chainName);
|
|
7418
|
-
const client =
|
|
8284
|
+
const client = createPublicClient19({ transport: http19(chain.effectiveRpcUrl()) });
|
|
7419
8285
|
const balance = await client.getBalance({ address: opts.address });
|
|
7420
8286
|
printOutput({
|
|
7421
8287
|
chain: chain.name,
|
|
@@ -7432,14 +8298,14 @@ function registerWallet(parent, getOpts) {
|
|
|
7432
8298
|
}
|
|
7433
8299
|
|
|
7434
8300
|
// src/commands/token.ts
|
|
7435
|
-
import { createPublicClient as
|
|
8301
|
+
import { createPublicClient as createPublicClient20, http as http20, maxUint256 } from "viem";
|
|
7436
8302
|
function registerToken(parent, getOpts, makeExecutor2) {
|
|
7437
8303
|
const token = parent.command("token").description("Token operations: approve, allowance, transfer, balance");
|
|
7438
8304
|
token.command("balance").description("Query token balance for an address").requiredOption("--token <token>", "Token symbol or address").requiredOption("--owner <address>", "Wallet address to query").action(async (opts) => {
|
|
7439
8305
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7440
8306
|
const registry = Registry.loadEmbedded();
|
|
7441
8307
|
const chain = registry.getChain(chainName);
|
|
7442
|
-
const client =
|
|
8308
|
+
const client = createPublicClient20({ transport: http20(chain.effectiveRpcUrl()) });
|
|
7443
8309
|
const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
|
|
7444
8310
|
const [balance, symbol, decimals] = await Promise.all([
|
|
7445
8311
|
client.readContract({ address: tokenAddr, abi: erc20Abi, functionName: "balanceOf", args: [opts.owner] }),
|
|
@@ -7468,7 +8334,7 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
7468
8334
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7469
8335
|
const registry = Registry.loadEmbedded();
|
|
7470
8336
|
const chain = registry.getChain(chainName);
|
|
7471
|
-
const client =
|
|
8337
|
+
const client = createPublicClient20({ transport: http20(chain.effectiveRpcUrl()) });
|
|
7472
8338
|
const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
|
|
7473
8339
|
const allowance = await client.readContract({
|
|
7474
8340
|
address: tokenAddr,
|
|
@@ -7490,8 +8356,8 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
7490
8356
|
}
|
|
7491
8357
|
|
|
7492
8358
|
// src/commands/whales.ts
|
|
7493
|
-
import { encodeFunctionData as
|
|
7494
|
-
var POOL_ABI6 =
|
|
8359
|
+
import { encodeFunctionData as encodeFunctionData28, parseAbi as parseAbi31 } from "viem";
|
|
8360
|
+
var POOL_ABI6 = parseAbi31([
|
|
7495
8361
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
7496
8362
|
]);
|
|
7497
8363
|
function round24(x) {
|
|
@@ -7602,7 +8468,7 @@ function registerWhales(parent, getOpts) {
|
|
|
7602
8468
|
for (const { pool } of lendingPools) {
|
|
7603
8469
|
calls.push([
|
|
7604
8470
|
pool,
|
|
7605
|
-
|
|
8471
|
+
encodeFunctionData28({ abi: POOL_ABI6, functionName: "getUserAccountData", args: [whale.address] })
|
|
7606
8472
|
]);
|
|
7607
8473
|
}
|
|
7608
8474
|
}
|
|
@@ -8030,11 +8896,11 @@ function registerBridge(parent, getOpts) {
|
|
|
8030
8896
|
const amountUsdc = Number(BigInt(opts.amount)) / 1e6;
|
|
8031
8897
|
const { fee, maxFeeSubunits } = await getCctpFeeEstimate(srcDomain, dstDomain, amountUsdc);
|
|
8032
8898
|
const recipientPadded = `0x${"0".repeat(24)}${recipient.replace("0x", "").toLowerCase()}`;
|
|
8033
|
-
const { encodeFunctionData:
|
|
8034
|
-
const tokenMessengerAbi =
|
|
8899
|
+
const { encodeFunctionData: encodeFunctionData30, parseAbi: parseAbi34 } = await import("viem");
|
|
8900
|
+
const tokenMessengerAbi = parseAbi34([
|
|
8035
8901
|
"function depositForBurn(uint256 amount, uint32 destinationDomain, bytes32 mintRecipient, address burnToken, bytes32 destinationCaller, uint256 maxFee, uint32 minFinalityThreshold) external returns (uint64 nonce)"
|
|
8036
8902
|
]);
|
|
8037
|
-
const data =
|
|
8903
|
+
const data = encodeFunctionData30({
|
|
8038
8904
|
abi: tokenMessengerAbi,
|
|
8039
8905
|
functionName: "depositForBurn",
|
|
8040
8906
|
args: [
|
|
@@ -8371,6 +9237,107 @@ function registerSetup(program2) {
|
|
|
8371
9237
|
});
|
|
8372
9238
|
}
|
|
8373
9239
|
|
|
9240
|
+
// src/commands/lb.ts
|
|
9241
|
+
function registerLB(parent, getOpts, makeExecutor2) {
|
|
9242
|
+
const lb = parent.command("lb").description("Merchant Moe Liquidity Book: add/remove liquidity, rewards, positions");
|
|
9243
|
+
lb.command("add").description("Add liquidity to a Liquidity Book pair").requiredOption("--protocol <protocol>", "Protocol slug (e.g. merchantmoe-mantle)").requiredOption("--pool <address>", "LB pair address").requiredOption("--token-x <address>", "Token X address").requiredOption("--token-y <address>", "Token Y address").requiredOption("--bin-step <step>", "Bin step of the pair").option("--amount-x <wei>", "Amount of token X in wei", "0").option("--amount-y <wei>", "Amount of token Y in wei", "0").option("--bins <N>", "Number of bins on each side of active bin", "5").option("--active-id <id>", "Active bin id (defaults to on-chain query)").option("--recipient <address>", "Recipient address").action(async (opts) => {
|
|
9244
|
+
const executor = makeExecutor2();
|
|
9245
|
+
const registry = Registry.loadEmbedded();
|
|
9246
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9247
|
+
const chainName = parent.opts().chain;
|
|
9248
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9249
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9250
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9251
|
+
const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
|
|
9252
|
+
const tx = await adapter.buildAddLiquidity({
|
|
9253
|
+
pool: opts.pool,
|
|
9254
|
+
tokenX: opts.tokenX,
|
|
9255
|
+
tokenY: opts.tokenY,
|
|
9256
|
+
binStep: parseInt(opts.binStep),
|
|
9257
|
+
amountX: BigInt(opts.amountX),
|
|
9258
|
+
amountY: BigInt(opts.amountY),
|
|
9259
|
+
numBins: parseInt(opts.bins),
|
|
9260
|
+
activeIdDesired: opts.activeId ? parseInt(opts.activeId) : void 0,
|
|
9261
|
+
recipient
|
|
9262
|
+
});
|
|
9263
|
+
const result = await executor.execute(tx);
|
|
9264
|
+
printOutput(result, getOpts());
|
|
9265
|
+
});
|
|
9266
|
+
lb.command("remove").description("Remove liquidity from Liquidity Book bins").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--token-x <address>", "Token X address").requiredOption("--token-y <address>", "Token Y address").requiredOption("--bin-step <step>", "Bin step of the pair").requiredOption("--bins <binIds>", "Comma-separated bin IDs to remove from").requiredOption("--amounts <amounts>", "Comma-separated LB token amounts to remove per bin (wei)").option("--recipient <address>", "Recipient address").action(async (opts) => {
|
|
9267
|
+
const executor = makeExecutor2();
|
|
9268
|
+
const registry = Registry.loadEmbedded();
|
|
9269
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9270
|
+
const adapter = createMerchantMoeLB(protocol);
|
|
9271
|
+
const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
|
|
9272
|
+
const binIds = opts.bins.split(",").map((s) => parseInt(s.trim()));
|
|
9273
|
+
const amounts = opts.amounts.split(",").map((s) => BigInt(s.trim()));
|
|
9274
|
+
const tx = await adapter.buildRemoveLiquidity({
|
|
9275
|
+
tokenX: opts.tokenX,
|
|
9276
|
+
tokenY: opts.tokenY,
|
|
9277
|
+
binStep: parseInt(opts.binStep),
|
|
9278
|
+
binIds,
|
|
9279
|
+
amounts,
|
|
9280
|
+
recipient
|
|
9281
|
+
});
|
|
9282
|
+
const result = await executor.execute(tx);
|
|
9283
|
+
printOutput(result, getOpts());
|
|
9284
|
+
});
|
|
9285
|
+
lb.command("rewards").description("Show pending MOE rewards for a pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "LB pair address").option("--bins <binIds>", "Comma-separated bin IDs to check (auto-detected from rewarder range if omitted)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
|
|
9286
|
+
const registry = Registry.loadEmbedded();
|
|
9287
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9288
|
+
const chainName = parent.opts().chain;
|
|
9289
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9290
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9291
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9292
|
+
const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
|
|
9293
|
+
if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
|
|
9294
|
+
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
9295
|
+
const rewards = await adapter.getPendingRewards(user, opts.pool, binIds);
|
|
9296
|
+
printOutput(rewards, getOpts());
|
|
9297
|
+
});
|
|
9298
|
+
lb.command("claim").description("Claim pending MOE rewards from a pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "LB pair address").option("--bins <binIds>", "Comma-separated bin IDs to claim from (auto-detected from rewarder range if omitted)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
|
|
9299
|
+
const executor = makeExecutor2();
|
|
9300
|
+
const registry = Registry.loadEmbedded();
|
|
9301
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9302
|
+
const chainName = parent.opts().chain;
|
|
9303
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9304
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9305
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9306
|
+
const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
|
|
9307
|
+
if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
|
|
9308
|
+
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
9309
|
+
const tx = await adapter.buildClaimRewards(user, opts.pool, binIds);
|
|
9310
|
+
const result = await executor.execute(tx);
|
|
9311
|
+
printOutput(result, getOpts());
|
|
9312
|
+
});
|
|
9313
|
+
lb.command("discover").description("Find all rewarded LB pools on chain").requiredOption("--protocol <protocol>", "Protocol slug").option("--active-only", "Only show non-stopped pools").action(async (opts) => {
|
|
9314
|
+
const registry = Registry.loadEmbedded();
|
|
9315
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9316
|
+
const chainName = parent.opts().chain;
|
|
9317
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9318
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9319
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9320
|
+
let pools = await adapter.discoverRewardedPools();
|
|
9321
|
+
if (opts.activeOnly) {
|
|
9322
|
+
pools = pools.filter((p) => !p.stopped);
|
|
9323
|
+
}
|
|
9324
|
+
printOutput(pools, getOpts());
|
|
9325
|
+
});
|
|
9326
|
+
lb.command("positions").description("Show user positions per bin in a LB pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "LB pair address").option("--bins <binIds>", "Comma-separated bin IDs to query (auto-detected from rewarder range or active \xB1 50 if omitted)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
|
|
9327
|
+
const registry = Registry.loadEmbedded();
|
|
9328
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9329
|
+
const chainName = parent.opts().chain;
|
|
9330
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9331
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9332
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9333
|
+
const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
|
|
9334
|
+
if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
|
|
9335
|
+
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
9336
|
+
const positions = await adapter.getUserPositions(user, opts.pool, binIds);
|
|
9337
|
+
printOutput(positions, getOpts());
|
|
9338
|
+
});
|
|
9339
|
+
}
|
|
9340
|
+
|
|
8374
9341
|
// src/cli.ts
|
|
8375
9342
|
var _require = createRequire(import.meta.url);
|
|
8376
9343
|
var _pkg = _require("../package.json");
|
|
@@ -8382,7 +9349,7 @@ var BANNER = `
|
|
|
8382
9349
|
\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551
|
|
8383
9350
|
\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D
|
|
8384
9351
|
|
|
8385
|
-
2 chains \xB7
|
|
9352
|
+
2 chains \xB7 30 protocols \xB7 by HypurrQuant
|
|
8386
9353
|
|
|
8387
9354
|
Scan exploits, swap tokens, bridge assets, track whales,
|
|
8388
9355
|
compare yields \u2014 all from your terminal.
|
|
@@ -8422,6 +9389,7 @@ registerSwap(program, getOutputMode, makeExecutor);
|
|
|
8422
9389
|
registerBridge(program, getOutputMode);
|
|
8423
9390
|
registerNft(program, getOutputMode);
|
|
8424
9391
|
registerFarm(program, getOutputMode, makeExecutor);
|
|
9392
|
+
registerLB(program, getOutputMode, makeExecutor);
|
|
8425
9393
|
registerSetup(program);
|
|
8426
9394
|
program.command("agent").description("Agent mode: read JSON commands from stdin (for AI agents)").action(async () => {
|
|
8427
9395
|
const executor = makeExecutor();
|
|
@@ -8432,13 +9400,13 @@ program.command("agent").description("Agent mode: read JSON commands from stdin
|
|
|
8432
9400
|
|
|
8433
9401
|
// src/landing.ts
|
|
8434
9402
|
import pc3 from "picocolors";
|
|
8435
|
-
import { encodeFunctionData as
|
|
9403
|
+
import { encodeFunctionData as encodeFunctionData29, parseAbi as parseAbi33, formatUnits } from "viem";
|
|
8436
9404
|
var HYPEREVM_DISPLAY = ["HYPE", "WHYPE", "USDC", "USDT0", "USDe", "kHYPE", "wstHYPE"];
|
|
8437
9405
|
var MANTLE_DISPLAY = ["MNT", "WMNT", "USDC", "USDT", "WETH", "mETH"];
|
|
8438
|
-
var balanceOfAbi =
|
|
9406
|
+
var balanceOfAbi = parseAbi33([
|
|
8439
9407
|
"function balanceOf(address account) view returns (uint256)"
|
|
8440
9408
|
]);
|
|
8441
|
-
var getEthBalanceAbi =
|
|
9409
|
+
var getEthBalanceAbi = parseAbi33([
|
|
8442
9410
|
"function getEthBalance(address addr) view returns (uint256)"
|
|
8443
9411
|
]);
|
|
8444
9412
|
async function fetchBalances(rpcUrl, wallet, tokens) {
|
|
@@ -8447,7 +9415,7 @@ async function fetchBalances(rpcUrl, wallet, tokens) {
|
|
|
8447
9415
|
if (isNative) {
|
|
8448
9416
|
return [
|
|
8449
9417
|
MULTICALL3_ADDRESS,
|
|
8450
|
-
|
|
9418
|
+
encodeFunctionData29({
|
|
8451
9419
|
abi: getEthBalanceAbi,
|
|
8452
9420
|
functionName: "getEthBalance",
|
|
8453
9421
|
args: [wallet]
|
|
@@ -8456,7 +9424,7 @@ async function fetchBalances(rpcUrl, wallet, tokens) {
|
|
|
8456
9424
|
}
|
|
8457
9425
|
return [
|
|
8458
9426
|
t.address,
|
|
8459
|
-
|
|
9427
|
+
encodeFunctionData29({
|
|
8460
9428
|
abi: balanceOfAbi,
|
|
8461
9429
|
functionName: "balanceOf",
|
|
8462
9430
|
args: [wallet]
|
|
@@ -8630,6 +9598,7 @@ async function main() {
|
|
|
8630
9598
|
"bridge",
|
|
8631
9599
|
"nft",
|
|
8632
9600
|
"farm",
|
|
9601
|
+
"lb",
|
|
8633
9602
|
"agent",
|
|
8634
9603
|
"setup",
|
|
8635
9604
|
"init"
|