@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/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { Command } from "commander";
|
|
|
5
5
|
import { createRequire } from "module";
|
|
6
6
|
|
|
7
7
|
// src/executor.ts
|
|
8
|
-
import { createPublicClient as createPublicClient2, createWalletClient, http as http2 } from "viem";
|
|
8
|
+
import { createPublicClient as createPublicClient2, createWalletClient, http as http2, parseAbi as parseAbi3, encodeFunctionData as encodeFunctionData3 } from "viem";
|
|
9
9
|
import { privateKeyToAccount } from "viem/accounts";
|
|
10
10
|
|
|
11
11
|
// ../defi-core/dist/index.js
|
|
@@ -703,6 +703,16 @@ function parse(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
|
|
|
703
703
|
|
|
704
704
|
// ../defi-core/dist/index.js
|
|
705
705
|
import { existsSync } from "fs";
|
|
706
|
+
var TxStatus = /* @__PURE__ */ ((TxStatus2) => {
|
|
707
|
+
TxStatus2["DryRun"] = "dry_run";
|
|
708
|
+
TxStatus2["Simulated"] = "simulated";
|
|
709
|
+
TxStatus2["SimulationFailed"] = "simulation_failed";
|
|
710
|
+
TxStatus2["NeedsApproval"] = "needs_approval";
|
|
711
|
+
TxStatus2["Pending"] = "pending";
|
|
712
|
+
TxStatus2["Confirmed"] = "confirmed";
|
|
713
|
+
TxStatus2["Failed"] = "failed";
|
|
714
|
+
return TxStatus2;
|
|
715
|
+
})(TxStatus || {});
|
|
706
716
|
var InterestRateMode = /* @__PURE__ */ ((InterestRateMode2) => {
|
|
707
717
|
InterestRateMode2["Variable"] = "variable";
|
|
708
718
|
InterestRateMode2["Stable"] = "stable";
|
|
@@ -864,6 +874,10 @@ async function multicallRead(rpcUrl, calls) {
|
|
|
864
874
|
});
|
|
865
875
|
return decoded.map((r) => r.success ? r.returnData : null);
|
|
866
876
|
}
|
|
877
|
+
function decodeU256(data) {
|
|
878
|
+
if (!data || data.length < 66) return 0n;
|
|
879
|
+
return BigInt(data.slice(0, 66));
|
|
880
|
+
}
|
|
867
881
|
var ChainConfig = class {
|
|
868
882
|
name;
|
|
869
883
|
chain_id;
|
|
@@ -1008,8 +1022,13 @@ var Registry = class _Registry {
|
|
|
1008
1022
|
};
|
|
1009
1023
|
|
|
1010
1024
|
// src/executor.ts
|
|
1025
|
+
var ERC20_ABI = parseAbi3([
|
|
1026
|
+
"function allowance(address owner, address spender) external view returns (uint256)",
|
|
1027
|
+
"function approve(address spender, uint256 amount) external returns (bool)"
|
|
1028
|
+
]);
|
|
1011
1029
|
var GAS_BUFFER_BPS = 12000n;
|
|
1012
|
-
var DEFAULT_PRIORITY_FEE_WEI =
|
|
1030
|
+
var DEFAULT_PRIORITY_FEE_WEI = 20000000000n;
|
|
1031
|
+
var MAX_GAS_LIMIT = 5000000000n;
|
|
1013
1032
|
var Executor = class _Executor {
|
|
1014
1033
|
dryRun;
|
|
1015
1034
|
rpcUrl;
|
|
@@ -1023,6 +1042,62 @@ var Executor = class _Executor {
|
|
|
1023
1042
|
static applyGasBuffer(gas) {
|
|
1024
1043
|
return gas * GAS_BUFFER_BPS / 10000n;
|
|
1025
1044
|
}
|
|
1045
|
+
/**
|
|
1046
|
+
* Check allowance for a single token/spender pair and send an approve tx if needed.
|
|
1047
|
+
* Only called in broadcast mode (not dry-run).
|
|
1048
|
+
*/
|
|
1049
|
+
async checkAndApprove(token, spender, amount, owner, publicClient, walletClient) {
|
|
1050
|
+
const allowance = await publicClient.readContract({
|
|
1051
|
+
address: token,
|
|
1052
|
+
abi: ERC20_ABI,
|
|
1053
|
+
functionName: "allowance",
|
|
1054
|
+
args: [owner, spender]
|
|
1055
|
+
});
|
|
1056
|
+
if (allowance >= amount) return;
|
|
1057
|
+
process.stderr.write(
|
|
1058
|
+
` Approving ${amount} of ${token} for ${spender}...
|
|
1059
|
+
`
|
|
1060
|
+
);
|
|
1061
|
+
const approveData = encodeFunctionData3({
|
|
1062
|
+
abi: ERC20_ABI,
|
|
1063
|
+
functionName: "approve",
|
|
1064
|
+
args: [spender, amount]
|
|
1065
|
+
});
|
|
1066
|
+
const rpcUrl = this.rpcUrl;
|
|
1067
|
+
const gasLimit = await (async () => {
|
|
1068
|
+
try {
|
|
1069
|
+
const estimated = await publicClient.estimateGas({
|
|
1070
|
+
to: token,
|
|
1071
|
+
data: approveData,
|
|
1072
|
+
account: owner
|
|
1073
|
+
});
|
|
1074
|
+
const buffered = _Executor.applyGasBuffer(estimated);
|
|
1075
|
+
return buffered > MAX_GAS_LIMIT ? MAX_GAS_LIMIT : buffered;
|
|
1076
|
+
} catch {
|
|
1077
|
+
return 80000n;
|
|
1078
|
+
}
|
|
1079
|
+
})();
|
|
1080
|
+
const [maxFeePerGas, maxPriorityFeePerGas] = await this.fetchEip1559Fees(rpcUrl);
|
|
1081
|
+
const approveTxHash = await walletClient.sendTransaction({
|
|
1082
|
+
chain: null,
|
|
1083
|
+
account: walletClient.account,
|
|
1084
|
+
to: token,
|
|
1085
|
+
data: approveData,
|
|
1086
|
+
gas: gasLimit > 0n ? gasLimit : void 0,
|
|
1087
|
+
maxFeePerGas: maxFeePerGas > 0n ? maxFeePerGas : void 0,
|
|
1088
|
+
maxPriorityFeePerGas: maxPriorityFeePerGas > 0n ? maxPriorityFeePerGas : void 0
|
|
1089
|
+
});
|
|
1090
|
+
const approveTxUrl = this.explorerUrl ? `${this.explorerUrl}/tx/${approveTxHash}` : void 0;
|
|
1091
|
+
process.stderr.write(` Approve tx: ${approveTxHash}
|
|
1092
|
+
`);
|
|
1093
|
+
if (approveTxUrl) process.stderr.write(` Explorer: ${approveTxUrl}
|
|
1094
|
+
`);
|
|
1095
|
+
await publicClient.waitForTransactionReceipt({ hash: approveTxHash });
|
|
1096
|
+
process.stderr.write(
|
|
1097
|
+
` Approved ${amount} of ${token} for ${spender}
|
|
1098
|
+
`
|
|
1099
|
+
);
|
|
1100
|
+
}
|
|
1026
1101
|
/** Fetch EIP-1559 fee params from the network. Returns [maxFeePerGas, maxPriorityFeePerGas]. */
|
|
1027
1102
|
async fetchEip1559Fees(rpcUrl) {
|
|
1028
1103
|
try {
|
|
@@ -1049,7 +1124,10 @@ var Executor = class _Executor {
|
|
|
1049
1124
|
value: tx.value,
|
|
1050
1125
|
account: from
|
|
1051
1126
|
});
|
|
1052
|
-
if (estimated > 0n)
|
|
1127
|
+
if (estimated > 0n) {
|
|
1128
|
+
const buffered = _Executor.applyGasBuffer(estimated);
|
|
1129
|
+
return buffered > MAX_GAS_LIMIT ? MAX_GAS_LIMIT : buffered;
|
|
1130
|
+
}
|
|
1053
1131
|
} catch {
|
|
1054
1132
|
}
|
|
1055
1133
|
return tx.gas_estimate ? BigInt(tx.gas_estimate) : 0n;
|
|
@@ -1063,6 +1141,46 @@ var Executor = class _Executor {
|
|
|
1063
1141
|
const client = createPublicClient2({ transport: http2(rpcUrl) });
|
|
1064
1142
|
const privateKey = process.env["DEFI_PRIVATE_KEY"];
|
|
1065
1143
|
const from = privateKey ? privateKeyToAccount(privateKey).address : "0x0000000000000000000000000000000000000001";
|
|
1144
|
+
if (tx.approvals && tx.approvals.length > 0) {
|
|
1145
|
+
const pendingApprovals = [];
|
|
1146
|
+
for (const approval of tx.approvals) {
|
|
1147
|
+
try {
|
|
1148
|
+
const allowance = await client.readContract({
|
|
1149
|
+
address: approval.token,
|
|
1150
|
+
abi: ERC20_ABI,
|
|
1151
|
+
functionName: "allowance",
|
|
1152
|
+
args: [from, approval.spender]
|
|
1153
|
+
});
|
|
1154
|
+
if (allowance < approval.amount) {
|
|
1155
|
+
pendingApprovals.push({
|
|
1156
|
+
token: approval.token,
|
|
1157
|
+
spender: approval.spender,
|
|
1158
|
+
needed: approval.amount.toString(),
|
|
1159
|
+
current: allowance.toString()
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
} catch {
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
if (pendingApprovals.length > 0) {
|
|
1166
|
+
return {
|
|
1167
|
+
tx_hash: void 0,
|
|
1168
|
+
status: TxStatus.NeedsApproval,
|
|
1169
|
+
gas_used: tx.gas_estimate,
|
|
1170
|
+
description: tx.description,
|
|
1171
|
+
details: {
|
|
1172
|
+
to: tx.to,
|
|
1173
|
+
from,
|
|
1174
|
+
data: tx.data,
|
|
1175
|
+
value: tx.value.toString(),
|
|
1176
|
+
mode: "simulated",
|
|
1177
|
+
result: "needs_approval",
|
|
1178
|
+
pending_approvals: pendingApprovals,
|
|
1179
|
+
hint: "Use --broadcast to auto-approve and execute"
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1066
1184
|
try {
|
|
1067
1185
|
await client.call({ to: tx.to, data: tx.data, value: tx.value, account: from });
|
|
1068
1186
|
const gasEstimate = await this.estimateGasWithBuffer(rpcUrl, tx, from);
|
|
@@ -1135,6 +1253,18 @@ var Executor = class _Executor {
|
|
|
1135
1253
|
}
|
|
1136
1254
|
const publicClient = createPublicClient2({ transport: http2(rpcUrl) });
|
|
1137
1255
|
const walletClient = createWalletClient({ account, transport: http2(rpcUrl) });
|
|
1256
|
+
if (tx.approvals && tx.approvals.length > 0) {
|
|
1257
|
+
for (const approval of tx.approvals) {
|
|
1258
|
+
await this.checkAndApprove(
|
|
1259
|
+
approval.token,
|
|
1260
|
+
approval.spender,
|
|
1261
|
+
approval.amount,
|
|
1262
|
+
account.address,
|
|
1263
|
+
publicClient,
|
|
1264
|
+
walletClient
|
|
1265
|
+
);
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1138
1268
|
const gasLimit = await this.estimateGasWithBuffer(rpcUrl, tx, account.address);
|
|
1139
1269
|
const [maxFeePerGas, maxPriorityFeePerGas] = await this.fetchEip1559Fees(rpcUrl);
|
|
1140
1270
|
process.stderr.write(`Broadcasting transaction to ${rpcUrl}...
|
|
@@ -1711,45 +1841,52 @@ function registerSchema(parent, getOpts) {
|
|
|
1711
1841
|
}
|
|
1712
1842
|
|
|
1713
1843
|
// ../defi-protocols/dist/index.js
|
|
1714
|
-
import { encodeFunctionData as
|
|
1844
|
+
import { encodeFunctionData as encodeFunctionData4, parseAbi as parseAbi4, createPublicClient as createPublicClient4, http as http4, decodeAbiParameters } from "viem";
|
|
1715
1845
|
import { encodeFunctionData as encodeFunctionData22, parseAbi as parseAbi22, createPublicClient as createPublicClient22, http as http22, decodeFunctionResult as decodeFunctionResult2, decodeAbiParameters as decodeAbiParameters2 } from "viem";
|
|
1716
1846
|
import { encodeFunctionData as encodeFunctionData32, parseAbi as parseAbi32, createPublicClient as createPublicClient32, http as http32, decodeAbiParameters as decodeAbiParameters3, concatHex, zeroAddress } from "viem";
|
|
1717
|
-
import { encodeFunctionData as
|
|
1847
|
+
import { encodeFunctionData as encodeFunctionData42, parseAbi as parseAbi42, zeroAddress as zeroAddress2 } from "viem";
|
|
1718
1848
|
import { encodeFunctionData as encodeFunctionData5, parseAbi as parseAbi5 } from "viem";
|
|
1719
|
-
import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6,
|
|
1849
|
+
import { encodeFunctionData as encodeFunctionData6, parseAbi as parseAbi6, decodeAbiParameters as decodeAbiParameters4 } from "viem";
|
|
1720
1850
|
import { encodeFunctionData as encodeFunctionData7, parseAbi as parseAbi7, zeroAddress as zeroAddress3 } from "viem";
|
|
1721
|
-
import { createPublicClient as
|
|
1722
|
-
import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9, createPublicClient as
|
|
1723
|
-
import {
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
import { createPublicClient as
|
|
1731
|
-
import { createPublicClient as
|
|
1732
|
-
import { createPublicClient as
|
|
1733
|
-
import { parseAbi as
|
|
1734
|
-
import { createPublicClient as
|
|
1735
|
-
import { createPublicClient as
|
|
1736
|
-
import { parseAbi as
|
|
1851
|
+
import { createPublicClient as createPublicClient42, encodeFunctionData as encodeFunctionData8, http as http42, parseAbi as parseAbi8, zeroAddress as zeroAddress4 } from "viem";
|
|
1852
|
+
import { encodeFunctionData as encodeFunctionData9, parseAbi as parseAbi9, createPublicClient as createPublicClient5, http as http5 } from "viem";
|
|
1853
|
+
import {
|
|
1854
|
+
encodeFunctionData as encodeFunctionData10,
|
|
1855
|
+
decodeFunctionResult as decodeFunctionResult22,
|
|
1856
|
+
parseAbi as parseAbi10,
|
|
1857
|
+
createPublicClient as createPublicClient6,
|
|
1858
|
+
http as http6
|
|
1859
|
+
} from "viem";
|
|
1860
|
+
import { createPublicClient as createPublicClient7, http as http7, parseAbi as parseAbi11, encodeFunctionData as encodeFunctionData11, decodeFunctionResult as decodeFunctionResult3, zeroAddress as zeroAddress5 } from "viem";
|
|
1861
|
+
import { createPublicClient as createPublicClient8, http as http8, parseAbi as parseAbi12, encodeFunctionData as encodeFunctionData12, zeroAddress as zeroAddress6 } from "viem";
|
|
1862
|
+
import { createPublicClient as createPublicClient9, http as http9, parseAbi as parseAbi13 } from "viem";
|
|
1863
|
+
import { createPublicClient as createPublicClient10, http as http10, parseAbi as parseAbi14, encodeFunctionData as encodeFunctionData13 } from "viem";
|
|
1864
|
+
import { createPublicClient as createPublicClient11, http as http11, parseAbi as parseAbi15, encodeFunctionData as encodeFunctionData14 } from "viem";
|
|
1865
|
+
import { createPublicClient as createPublicClient12, http as http12, parseAbi as parseAbi16, encodeFunctionData as encodeFunctionData15 } from "viem";
|
|
1866
|
+
import { parseAbi as parseAbi17, encodeFunctionData as encodeFunctionData16, decodeFunctionResult as decodeFunctionResult4, zeroAddress as zeroAddress7 } from "viem";
|
|
1867
|
+
import { createPublicClient as createPublicClient13, http as http13, parseAbi as parseAbi18, encodeFunctionData as encodeFunctionData17, zeroAddress as zeroAddress8 } from "viem";
|
|
1868
|
+
import { createPublicClient as createPublicClient14, http as http14, parseAbi as parseAbi19 } from "viem";
|
|
1869
|
+
import { createPublicClient as createPublicClient15, http as http15, parseAbi as parseAbi20, encodeFunctionData as encodeFunctionData18 } from "viem";
|
|
1870
|
+
import { parseAbi as parseAbi21, encodeFunctionData as encodeFunctionData19 } from "viem";
|
|
1871
|
+
import { createPublicClient as createPublicClient16, http as http16, parseAbi as parseAbi222, encodeFunctionData as encodeFunctionData20, zeroAddress as zeroAddress9 } from "viem";
|
|
1872
|
+
import { createPublicClient as createPublicClient17, http as http17, parseAbi as parseAbi23, encodeFunctionData as encodeFunctionData21, zeroAddress as zeroAddress10 } from "viem";
|
|
1737
1873
|
import { parseAbi as parseAbi24, encodeFunctionData as encodeFunctionData222 } from "viem";
|
|
1738
|
-
import {
|
|
1874
|
+
import { parseAbi as parseAbi25, encodeFunctionData as encodeFunctionData23 } from "viem";
|
|
1875
|
+
import { createPublicClient as createPublicClient18, http as http18, parseAbi as parseAbi26 } from "viem";
|
|
1739
1876
|
var DEFAULT_FEE = 3e3;
|
|
1740
|
-
var swapRouterAbi =
|
|
1877
|
+
var swapRouterAbi = parseAbi4([
|
|
1741
1878
|
"struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; }",
|
|
1742
1879
|
"function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut)"
|
|
1743
1880
|
]);
|
|
1744
|
-
var quoterAbi =
|
|
1881
|
+
var quoterAbi = parseAbi4([
|
|
1745
1882
|
"struct QuoteExactInputSingleParams { address tokenIn; address tokenOut; uint256 amountIn; uint24 fee; uint160 sqrtPriceLimitX96; }",
|
|
1746
1883
|
"function quoteExactInputSingle(QuoteExactInputSingleParams memory params) external returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)"
|
|
1747
1884
|
]);
|
|
1748
|
-
var ramsesQuoterAbi =
|
|
1885
|
+
var ramsesQuoterAbi = parseAbi4([
|
|
1749
1886
|
"struct QuoteExactInputSingleParams { address tokenIn; address tokenOut; uint256 amountIn; int24 tickSpacing; uint160 sqrtPriceLimitX96; }",
|
|
1750
1887
|
"function quoteExactInputSingle(QuoteExactInputSingleParams memory params) external returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)"
|
|
1751
1888
|
]);
|
|
1752
|
-
var positionManagerAbi =
|
|
1889
|
+
var positionManagerAbi = parseAbi4([
|
|
1753
1890
|
"struct MintParams { address token0; address token1; uint24 fee; int24 tickLower; int24 tickUpper; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; address recipient; uint256 deadline; }",
|
|
1754
1891
|
"function mint(MintParams calldata params) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1)"
|
|
1755
1892
|
]);
|
|
@@ -1782,7 +1919,7 @@ var UniswapV3Adapter = class {
|
|
|
1782
1919
|
async buildSwap(params) {
|
|
1783
1920
|
const deadline = BigInt(params.deadline ?? 18446744073709551615n);
|
|
1784
1921
|
const amountOutMinimum = 0n;
|
|
1785
|
-
const data =
|
|
1922
|
+
const data = encodeFunctionData4({
|
|
1786
1923
|
abi: swapRouterAbi,
|
|
1787
1924
|
functionName: "exactInputSingle",
|
|
1788
1925
|
args: [
|
|
@@ -1803,7 +1940,8 @@ var UniswapV3Adapter = class {
|
|
|
1803
1940
|
to: this.router,
|
|
1804
1941
|
data,
|
|
1805
1942
|
value: 0n,
|
|
1806
|
-
gas_estimate: 2e5
|
|
1943
|
+
gas_estimate: 2e5,
|
|
1944
|
+
approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
|
|
1807
1945
|
};
|
|
1808
1946
|
}
|
|
1809
1947
|
async quote(params) {
|
|
@@ -1818,7 +1956,7 @@ var UniswapV3Adapter = class {
|
|
|
1818
1956
|
tickSpacings.map(async (ts) => {
|
|
1819
1957
|
const result = await client2.call({
|
|
1820
1958
|
to: this.quoter,
|
|
1821
|
-
data:
|
|
1959
|
+
data: encodeFunctionData4({
|
|
1822
1960
|
abi: ramsesQuoterAbi,
|
|
1823
1961
|
functionName: "quoteExactInputSingle",
|
|
1824
1962
|
args: [
|
|
@@ -1864,7 +2002,7 @@ var UniswapV3Adapter = class {
|
|
|
1864
2002
|
feeTiers.map(async (fee) => {
|
|
1865
2003
|
const result = await client2.call({
|
|
1866
2004
|
to: this.quoter,
|
|
1867
|
-
data:
|
|
2005
|
+
data: encodeFunctionData4({
|
|
1868
2006
|
abi: quoterAbi,
|
|
1869
2007
|
functionName: "quoteExactInputSingle",
|
|
1870
2008
|
args: [
|
|
@@ -1903,7 +2041,7 @@ var UniswapV3Adapter = class {
|
|
|
1903
2041
|
}
|
|
1904
2042
|
}
|
|
1905
2043
|
const client = createPublicClient4({ transport: http4(this.rpcUrl) });
|
|
1906
|
-
const callData =
|
|
2044
|
+
const callData = encodeFunctionData4({
|
|
1907
2045
|
abi: swapRouterAbi,
|
|
1908
2046
|
functionName: "exactInputSingle",
|
|
1909
2047
|
args: [
|
|
@@ -1949,7 +2087,7 @@ var UniswapV3Adapter = class {
|
|
|
1949
2087
|
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];
|
|
1950
2088
|
const amount0 = rawAmount0 === 0n && rawAmount1 > 0n ? 1n : rawAmount0;
|
|
1951
2089
|
const amount1 = rawAmount1 === 0n && rawAmount0 > 0n ? 1n : rawAmount1;
|
|
1952
|
-
const data =
|
|
2090
|
+
const data = encodeFunctionData4({
|
|
1953
2091
|
abi: positionManagerAbi,
|
|
1954
2092
|
functionName: "mint",
|
|
1955
2093
|
args: [
|
|
@@ -1973,7 +2111,11 @@ var UniswapV3Adapter = class {
|
|
|
1973
2111
|
to: pm,
|
|
1974
2112
|
data,
|
|
1975
2113
|
value: 0n,
|
|
1976
|
-
gas_estimate: 5e5
|
|
2114
|
+
gas_estimate: 5e5,
|
|
2115
|
+
approvals: [
|
|
2116
|
+
{ token: token0, spender: pm, amount: amount0 },
|
|
2117
|
+
{ token: token1, spender: pm, amount: amount1 }
|
|
2118
|
+
]
|
|
1977
2119
|
};
|
|
1978
2120
|
}
|
|
1979
2121
|
async buildRemoveLiquidity(_params) {
|
|
@@ -2032,7 +2174,8 @@ var UniswapV2Adapter = class {
|
|
|
2032
2174
|
to: this.router,
|
|
2033
2175
|
data,
|
|
2034
2176
|
value: 0n,
|
|
2035
|
-
gas_estimate: 15e4
|
|
2177
|
+
gas_estimate: 15e4,
|
|
2178
|
+
approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
|
|
2036
2179
|
};
|
|
2037
2180
|
}
|
|
2038
2181
|
async quote(params) {
|
|
@@ -2151,7 +2294,11 @@ var UniswapV2Adapter = class {
|
|
|
2151
2294
|
to: this.router,
|
|
2152
2295
|
data,
|
|
2153
2296
|
value: 0n,
|
|
2154
|
-
gas_estimate: 3e5
|
|
2297
|
+
gas_estimate: 3e5,
|
|
2298
|
+
approvals: [
|
|
2299
|
+
{ token: params.token_a, spender: this.router, amount: params.amount_a },
|
|
2300
|
+
{ token: params.token_b, spender: this.router, amount: params.amount_b }
|
|
2301
|
+
]
|
|
2155
2302
|
};
|
|
2156
2303
|
}
|
|
2157
2304
|
async buildRemoveLiquidity(params) {
|
|
@@ -2238,7 +2385,8 @@ var AlgebraV3Adapter = class {
|
|
|
2238
2385
|
to: this.router,
|
|
2239
2386
|
data,
|
|
2240
2387
|
value: 0n,
|
|
2241
|
-
gas_estimate: 25e4
|
|
2388
|
+
gas_estimate: 25e4,
|
|
2389
|
+
approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
|
|
2242
2390
|
};
|
|
2243
2391
|
}
|
|
2244
2392
|
async quote(params) {
|
|
@@ -2356,7 +2504,11 @@ var AlgebraV3Adapter = class {
|
|
|
2356
2504
|
to: pm,
|
|
2357
2505
|
data,
|
|
2358
2506
|
value: 0n,
|
|
2359
|
-
gas_estimate: 5e5
|
|
2507
|
+
gas_estimate: 5e5,
|
|
2508
|
+
approvals: [
|
|
2509
|
+
{ token: token0, spender: pm, amount: amount0 },
|
|
2510
|
+
{ token: token1, spender: pm, amount: amount1 }
|
|
2511
|
+
]
|
|
2360
2512
|
};
|
|
2361
2513
|
}
|
|
2362
2514
|
async buildRemoveLiquidity(_params) {
|
|
@@ -2365,7 +2517,7 @@ var AlgebraV3Adapter = class {
|
|
|
2365
2517
|
);
|
|
2366
2518
|
}
|
|
2367
2519
|
};
|
|
2368
|
-
var abi3 =
|
|
2520
|
+
var abi3 = parseAbi42([
|
|
2369
2521
|
"function swapSingleTokenExactIn(address pool, address tokenIn, address tokenOut, uint256 exactAmountIn, uint256 minAmountOut, uint256 deadline, bool wethIsEth, bytes calldata userData) external returns (uint256 amountOut)"
|
|
2370
2522
|
]);
|
|
2371
2523
|
var BalancerV3Adapter = class {
|
|
@@ -2385,7 +2537,7 @@ var BalancerV3Adapter = class {
|
|
|
2385
2537
|
async buildSwap(params) {
|
|
2386
2538
|
const minAmountOut = 0n;
|
|
2387
2539
|
const deadline = BigInt(params.deadline ?? 18446744073709551615n);
|
|
2388
|
-
const data =
|
|
2540
|
+
const data = encodeFunctionData42({
|
|
2389
2541
|
abi: abi3,
|
|
2390
2542
|
functionName: "swapSingleTokenExactIn",
|
|
2391
2543
|
args: [
|
|
@@ -2533,18 +2685,10 @@ var SolidlyAdapter = class {
|
|
|
2533
2685
|
to: this.router,
|
|
2534
2686
|
data,
|
|
2535
2687
|
value: 0n,
|
|
2536
|
-
gas_estimate: 2e5
|
|
2688
|
+
gas_estimate: 2e5,
|
|
2689
|
+
approvals: [{ token: params.token_in, spender: this.router, amount: params.amount_in }]
|
|
2537
2690
|
};
|
|
2538
2691
|
}
|
|
2539
|
-
async callGetAmountsOut(client, callData) {
|
|
2540
|
-
const result = await client.call({ to: this.router, data: callData });
|
|
2541
|
-
if (!result.data) return 0n;
|
|
2542
|
-
const [amounts] = decodeAbiParameters4(
|
|
2543
|
-
[{ name: "amounts", type: "uint256[]" }],
|
|
2544
|
-
result.data
|
|
2545
|
-
);
|
|
2546
|
-
return amounts.length >= 2 ? amounts[amounts.length - 1] : 0n;
|
|
2547
|
-
}
|
|
2548
2692
|
encodeV1(params, stable) {
|
|
2549
2693
|
return encodeFunctionData6({
|
|
2550
2694
|
abi: abi4,
|
|
@@ -2561,7 +2705,6 @@ var SolidlyAdapter = class {
|
|
|
2561
2705
|
}
|
|
2562
2706
|
async quote(params) {
|
|
2563
2707
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
2564
|
-
const client = createPublicClient42({ transport: http42(this.rpcUrl) });
|
|
2565
2708
|
const candidates = [
|
|
2566
2709
|
{ callData: this.encodeV1(params, false), stable: false },
|
|
2567
2710
|
{ callData: this.encodeV1(params, true), stable: true }
|
|
@@ -2572,16 +2715,26 @@ var SolidlyAdapter = class {
|
|
|
2572
2715
|
{ callData: this.encodeV2(params, true), stable: true }
|
|
2573
2716
|
);
|
|
2574
2717
|
}
|
|
2575
|
-
const
|
|
2576
|
-
|
|
2718
|
+
const rawResults = await multicallRead(
|
|
2719
|
+
this.rpcUrl,
|
|
2720
|
+
candidates.map((c) => [this.router, c.callData])
|
|
2577
2721
|
);
|
|
2578
2722
|
let bestOut = 0n;
|
|
2579
2723
|
let bestStable = false;
|
|
2580
|
-
for (let i = 0; i <
|
|
2581
|
-
const
|
|
2582
|
-
if (
|
|
2583
|
-
|
|
2584
|
-
|
|
2724
|
+
for (let i = 0; i < rawResults.length; i++) {
|
|
2725
|
+
const raw = rawResults[i];
|
|
2726
|
+
if (!raw) continue;
|
|
2727
|
+
try {
|
|
2728
|
+
const [amounts] = decodeAbiParameters4(
|
|
2729
|
+
[{ name: "amounts", type: "uint256[]" }],
|
|
2730
|
+
raw
|
|
2731
|
+
);
|
|
2732
|
+
const out = amounts.length >= 2 ? amounts[amounts.length - 1] : 0n;
|
|
2733
|
+
if (out > bestOut) {
|
|
2734
|
+
bestOut = out;
|
|
2735
|
+
bestStable = candidates[i].stable;
|
|
2736
|
+
}
|
|
2737
|
+
} catch {
|
|
2585
2738
|
}
|
|
2586
2739
|
}
|
|
2587
2740
|
if (bestOut === 0n) {
|
|
@@ -2616,7 +2769,11 @@ var SolidlyAdapter = class {
|
|
|
2616
2769
|
to: this.router,
|
|
2617
2770
|
data,
|
|
2618
2771
|
value: 0n,
|
|
2619
|
-
gas_estimate: 35e4
|
|
2772
|
+
gas_estimate: 35e4,
|
|
2773
|
+
approvals: [
|
|
2774
|
+
{ token: params.token_a, spender: this.router, amount: params.amount_a },
|
|
2775
|
+
{ token: params.token_b, spender: this.router, amount: params.amount_b }
|
|
2776
|
+
]
|
|
2620
2777
|
};
|
|
2621
2778
|
}
|
|
2622
2779
|
async buildRemoveLiquidity(params) {
|
|
@@ -2742,7 +2899,7 @@ var SolidlyGaugeAdapter = class {
|
|
|
2742
2899
|
return this.protocolName;
|
|
2743
2900
|
}
|
|
2744
2901
|
// IGauge
|
|
2745
|
-
async buildDeposit(gauge, amount, tokenId) {
|
|
2902
|
+
async buildDeposit(gauge, amount, tokenId, lpToken) {
|
|
2746
2903
|
if (tokenId !== void 0) {
|
|
2747
2904
|
const data2 = encodeFunctionData8({
|
|
2748
2905
|
abi: gaugeAbi,
|
|
@@ -2754,7 +2911,8 @@ var SolidlyGaugeAdapter = class {
|
|
|
2754
2911
|
to: gauge,
|
|
2755
2912
|
data: data2,
|
|
2756
2913
|
value: 0n,
|
|
2757
|
-
gas_estimate: 2e5
|
|
2914
|
+
gas_estimate: 2e5,
|
|
2915
|
+
approvals: lpToken ? [{ token: lpToken, spender: gauge, amount }] : void 0
|
|
2758
2916
|
};
|
|
2759
2917
|
}
|
|
2760
2918
|
const data = encodeFunctionData8({
|
|
@@ -2767,7 +2925,8 @@ var SolidlyGaugeAdapter = class {
|
|
|
2767
2925
|
to: gauge,
|
|
2768
2926
|
data,
|
|
2769
2927
|
value: 0n,
|
|
2770
|
-
gas_estimate: 2e5
|
|
2928
|
+
gas_estimate: 2e5,
|
|
2929
|
+
approvals: lpToken ? [{ token: lpToken, spender: gauge, amount }] : void 0
|
|
2771
2930
|
};
|
|
2772
2931
|
}
|
|
2773
2932
|
async buildWithdraw(gauge, amount) {
|
|
@@ -2787,7 +2946,7 @@ var SolidlyGaugeAdapter = class {
|
|
|
2787
2946
|
async buildClaimRewards(gauge, account) {
|
|
2788
2947
|
if (account && this.rpcUrl) {
|
|
2789
2948
|
try {
|
|
2790
|
-
const client =
|
|
2949
|
+
const client = createPublicClient42({ transport: http42(this.rpcUrl) });
|
|
2791
2950
|
const listLen = await client.readContract({
|
|
2792
2951
|
address: gauge,
|
|
2793
2952
|
abi: gaugeAbi,
|
|
@@ -3045,7 +3204,7 @@ var MasterChefAdapter = class {
|
|
|
3045
3204
|
if (!this.rpcUrl) {
|
|
3046
3205
|
throw DefiError.unsupported(`[${this.protocolName}] getPendingRewards requires RPC`);
|
|
3047
3206
|
}
|
|
3048
|
-
const client =
|
|
3207
|
+
const client = createPublicClient5({ transport: http5(this.rpcUrl) });
|
|
3049
3208
|
const rewards = await client.readContract({
|
|
3050
3209
|
address: this.masterchef,
|
|
3051
3210
|
abi: masterchefAbi,
|
|
@@ -3059,7 +3218,682 @@ var MasterChefAdapter = class {
|
|
|
3059
3218
|
}));
|
|
3060
3219
|
}
|
|
3061
3220
|
};
|
|
3062
|
-
var
|
|
3221
|
+
var lbRouterAbi = parseAbi10([
|
|
3222
|
+
"struct LiquidityParameters { address tokenX; address tokenY; uint256 binStep; uint256 amountX; uint256 amountY; uint256 amountXMin; uint256 amountYMin; uint256 activeIdDesired; uint256 idSlippage; int256[] deltaIds; uint256[] distributionX; uint256[] distributionY; address to; address refundTo; uint256 deadline; }",
|
|
3223
|
+
"function addLiquidity(LiquidityParameters calldata liquidityParameters) external returns (uint256 amountXAdded, uint256 amountYAdded, uint256 amountXLeft, uint256 amountYLeft, uint256[] memory depositIds, uint256[] memory liquidityMinted)",
|
|
3224
|
+
"function removeLiquidity(address tokenX, address tokenY, uint16 binStep, uint256 amountXMin, uint256 amountYMin, uint256[] memory ids, uint256[] memory amounts, address to, uint256 deadline) external returns (uint256 amountX, uint256 amountY)"
|
|
3225
|
+
]);
|
|
3226
|
+
var lbFactoryAbi = parseAbi10([
|
|
3227
|
+
"function getNumberOfLBPairs() external view returns (uint256)",
|
|
3228
|
+
"function getLBPairAtIndex(uint256 index) external view returns (address)"
|
|
3229
|
+
]);
|
|
3230
|
+
var lbPairAbi = parseAbi10([
|
|
3231
|
+
"function getLBHooksParameters() external view returns (bytes32)",
|
|
3232
|
+
"function getActiveId() external view returns (uint24)",
|
|
3233
|
+
"function getBinStep() external view returns (uint16)",
|
|
3234
|
+
"function getTokenX() external view returns (address)",
|
|
3235
|
+
"function getTokenY() external view returns (address)",
|
|
3236
|
+
"function balanceOf(address account, uint256 id) external view returns (uint256)",
|
|
3237
|
+
"function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory)"
|
|
3238
|
+
]);
|
|
3239
|
+
var lbRewarderAbi = parseAbi10([
|
|
3240
|
+
"function getRewardToken() external view returns (address)",
|
|
3241
|
+
"function getRewardedRange() external view returns (uint256 minBinId, uint256 maxBinId)",
|
|
3242
|
+
"function getPendingRewards(address user, uint256[] calldata ids) external view returns (uint256 pendingRewards)",
|
|
3243
|
+
"function claim(address user, uint256[] calldata ids) external",
|
|
3244
|
+
"function getPid() external view returns (uint256)",
|
|
3245
|
+
"function isStopped() external view returns (bool)",
|
|
3246
|
+
"function getLBPair() external view returns (address)",
|
|
3247
|
+
"function getMasterChef() external view returns (address)"
|
|
3248
|
+
]);
|
|
3249
|
+
var masterChefAbi = parseAbi10([
|
|
3250
|
+
"function getMoePerSecond() external view returns (uint256)",
|
|
3251
|
+
"function getTreasuryShare() external view returns (uint256)",
|
|
3252
|
+
"function getStaticShare() external view returns (uint256)",
|
|
3253
|
+
"function getVeMoe() external view returns (address)"
|
|
3254
|
+
]);
|
|
3255
|
+
var veMoeAbi = parseAbi10([
|
|
3256
|
+
"function getWeight(uint256 pid) external view returns (uint256)",
|
|
3257
|
+
"function getTotalWeight() external view returns (uint256)",
|
|
3258
|
+
"function getTopPoolIds() external view returns (uint256[] memory)"
|
|
3259
|
+
]);
|
|
3260
|
+
var lbPairBinAbi = parseAbi10([
|
|
3261
|
+
"function getBin(uint24 id) external view returns (uint128 reserveX, uint128 reserveY)",
|
|
3262
|
+
"function getActiveId() external view returns (uint24)"
|
|
3263
|
+
]);
|
|
3264
|
+
var lbQuoterAbi2 = parseAbi10([
|
|
3265
|
+
"function findBestPathFromAmountIn(address[] calldata route, uint128 amountIn) external view returns ((address[] route, address[] pairs, uint256[] binSteps, uint256[] versions, uint128[] amounts, uint128[] virtualAmountsWithoutSlippage, uint128[] fees))"
|
|
3266
|
+
]);
|
|
3267
|
+
var erc20Abi2 = parseAbi10([
|
|
3268
|
+
"function symbol() external view returns (string)"
|
|
3269
|
+
]);
|
|
3270
|
+
var _addressAbi = parseAbi10(["function f() external view returns (address)"]);
|
|
3271
|
+
function decodeAddressResult(data) {
|
|
3272
|
+
if (!data) return null;
|
|
3273
|
+
try {
|
|
3274
|
+
return decodeFunctionResult22({ abi: _addressAbi, functionName: "f", data });
|
|
3275
|
+
} catch {
|
|
3276
|
+
return null;
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
3279
|
+
var _uint256Abi = parseAbi10(["function f() external view returns (uint256)"]);
|
|
3280
|
+
function decodeUint256Result(data) {
|
|
3281
|
+
if (!data) return null;
|
|
3282
|
+
try {
|
|
3283
|
+
return decodeFunctionResult22({ abi: _uint256Abi, functionName: "f", data });
|
|
3284
|
+
} catch {
|
|
3285
|
+
return null;
|
|
3286
|
+
}
|
|
3287
|
+
}
|
|
3288
|
+
var _boolAbi = parseAbi10(["function f() external view returns (bool)"]);
|
|
3289
|
+
function decodeBoolResult(data) {
|
|
3290
|
+
if (!data) return null;
|
|
3291
|
+
try {
|
|
3292
|
+
return decodeFunctionResult22({ abi: _boolAbi, functionName: "f", data });
|
|
3293
|
+
} catch {
|
|
3294
|
+
return null;
|
|
3295
|
+
}
|
|
3296
|
+
}
|
|
3297
|
+
function decodeStringResult(data) {
|
|
3298
|
+
if (!data) return "?";
|
|
3299
|
+
try {
|
|
3300
|
+
return decodeFunctionResult22({ abi: erc20Abi2, functionName: "symbol", data });
|
|
3301
|
+
} catch {
|
|
3302
|
+
return "?";
|
|
3303
|
+
}
|
|
3304
|
+
}
|
|
3305
|
+
var _rangeAbi = parseAbi10(["function f() external view returns (uint256 minBinId, uint256 maxBinId)"]);
|
|
3306
|
+
function decodeRangeResult(data) {
|
|
3307
|
+
if (!data) return null;
|
|
3308
|
+
try {
|
|
3309
|
+
return decodeFunctionResult22({ abi: _rangeAbi, functionName: "f", data });
|
|
3310
|
+
} catch {
|
|
3311
|
+
return null;
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
var _binAbi = parseAbi10(["function f() external view returns (uint128 reserveX, uint128 reserveY)"]);
|
|
3315
|
+
function decodeBinResult(data) {
|
|
3316
|
+
if (!data) return null;
|
|
3317
|
+
try {
|
|
3318
|
+
return decodeFunctionResult22({ abi: _binAbi, functionName: "f", data });
|
|
3319
|
+
} catch {
|
|
3320
|
+
return null;
|
|
3321
|
+
}
|
|
3322
|
+
}
|
|
3323
|
+
var _uint256ArrayAbi = parseAbi10(["function f() external view returns (uint256[] memory)"]);
|
|
3324
|
+
function decodeUint256ArrayResult(data) {
|
|
3325
|
+
if (!data) return null;
|
|
3326
|
+
try {
|
|
3327
|
+
return decodeFunctionResult22({ abi: _uint256ArrayAbi, functionName: "f", data });
|
|
3328
|
+
} catch {
|
|
3329
|
+
return null;
|
|
3330
|
+
}
|
|
3331
|
+
}
|
|
3332
|
+
function extractRewarderAddress(hooksParams) {
|
|
3333
|
+
if (!hooksParams || hooksParams === "0x0000000000000000000000000000000000000000000000000000000000000000") {
|
|
3334
|
+
return null;
|
|
3335
|
+
}
|
|
3336
|
+
const hex = hooksParams.slice(2);
|
|
3337
|
+
if (hex.length < 64) return null;
|
|
3338
|
+
const addrHex = hex.slice(24, 64);
|
|
3339
|
+
if (addrHex === "0000000000000000000000000000000000000000") return null;
|
|
3340
|
+
return `0x${addrHex}`;
|
|
3341
|
+
}
|
|
3342
|
+
function buildUniformDistribution(deltaIds) {
|
|
3343
|
+
const PRECISION = 10n ** 18n;
|
|
3344
|
+
const n = deltaIds.length;
|
|
3345
|
+
const xBins = deltaIds.filter((d) => d >= 0).length;
|
|
3346
|
+
const yBins = deltaIds.filter((d) => d <= 0).length;
|
|
3347
|
+
const distributionX = [];
|
|
3348
|
+
const distributionY = [];
|
|
3349
|
+
for (const delta of deltaIds) {
|
|
3350
|
+
const xShare = delta >= 0 && xBins > 0 ? PRECISION / BigInt(xBins) : 0n;
|
|
3351
|
+
const yShare = delta <= 0 && yBins > 0 ? PRECISION / BigInt(yBins) : 0n;
|
|
3352
|
+
distributionX.push(xShare);
|
|
3353
|
+
distributionY.push(yShare);
|
|
3354
|
+
}
|
|
3355
|
+
const xSum = distributionX.reduce((a, b) => a + b, 0n);
|
|
3356
|
+
const ySum = distributionY.reduce((a, b) => a + b, 0n);
|
|
3357
|
+
if (xSum > 0n && xSum !== PRECISION) {
|
|
3358
|
+
const firstX = distributionX.findIndex((v) => v > 0n);
|
|
3359
|
+
if (firstX !== -1) distributionX[firstX] += PRECISION - xSum;
|
|
3360
|
+
}
|
|
3361
|
+
if (ySum > 0n && ySum !== PRECISION) {
|
|
3362
|
+
const firstY = distributionY.findIndex((v) => v > 0n);
|
|
3363
|
+
if (firstY !== -1) distributionY[firstY] += PRECISION - ySum;
|
|
3364
|
+
}
|
|
3365
|
+
return { distributionX, distributionY };
|
|
3366
|
+
}
|
|
3367
|
+
var MerchantMoeLBAdapter = class {
|
|
3368
|
+
protocolName;
|
|
3369
|
+
lbRouter;
|
|
3370
|
+
lbFactory;
|
|
3371
|
+
lbQuoter;
|
|
3372
|
+
rpcUrl;
|
|
3373
|
+
/** WMNT address (lb_mid_wmnt in config) used for MOE price routing */
|
|
3374
|
+
wmnt;
|
|
3375
|
+
/** USDT address (lb_mid_usdt in config) used for MNT/USD price routing */
|
|
3376
|
+
usdt;
|
|
3377
|
+
constructor(entry, rpcUrl) {
|
|
3378
|
+
this.protocolName = entry.name;
|
|
3379
|
+
const lbRouter = entry.contracts?.["lb_router"];
|
|
3380
|
+
if (!lbRouter) {
|
|
3381
|
+
throw new DefiError("CONTRACT_ERROR", "Missing 'lb_router' contract address");
|
|
3382
|
+
}
|
|
3383
|
+
const lbFactory = entry.contracts?.["lb_factory"];
|
|
3384
|
+
if (!lbFactory) {
|
|
3385
|
+
throw new DefiError("CONTRACT_ERROR", "Missing 'lb_factory' contract address");
|
|
3386
|
+
}
|
|
3387
|
+
this.lbRouter = lbRouter;
|
|
3388
|
+
this.lbFactory = lbFactory;
|
|
3389
|
+
this.lbQuoter = entry.contracts?.["lb_quoter"];
|
|
3390
|
+
this.wmnt = entry.contracts?.["lb_mid_wmnt"];
|
|
3391
|
+
this.usdt = entry.contracts?.["lb_mid_usdt"];
|
|
3392
|
+
this.rpcUrl = rpcUrl;
|
|
3393
|
+
}
|
|
3394
|
+
name() {
|
|
3395
|
+
return this.protocolName;
|
|
3396
|
+
}
|
|
3397
|
+
requireRpc() {
|
|
3398
|
+
if (!this.rpcUrl) {
|
|
3399
|
+
throw DefiError.rpcError(`[${this.protocolName}] RPC URL required`);
|
|
3400
|
+
}
|
|
3401
|
+
return this.rpcUrl;
|
|
3402
|
+
}
|
|
3403
|
+
/**
|
|
3404
|
+
* Build an addLiquidity transaction for a Liquidity Book pair.
|
|
3405
|
+
* Distributes tokenX/tokenY uniformly across active bin ± numBins.
|
|
3406
|
+
*/
|
|
3407
|
+
async buildAddLiquidity(params) {
|
|
3408
|
+
const numBins = params.numBins ?? 5;
|
|
3409
|
+
const deadline = params.deadline ?? BigInt("18446744073709551615");
|
|
3410
|
+
let activeIdDesired = params.activeIdDesired;
|
|
3411
|
+
if (activeIdDesired === void 0) {
|
|
3412
|
+
const rpcUrl = this.requireRpc();
|
|
3413
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3414
|
+
const activeId = await client.readContract({
|
|
3415
|
+
address: params.pool,
|
|
3416
|
+
abi: lbPairAbi,
|
|
3417
|
+
functionName: "getActiveId"
|
|
3418
|
+
});
|
|
3419
|
+
activeIdDesired = activeId;
|
|
3420
|
+
}
|
|
3421
|
+
const deltaIds = [];
|
|
3422
|
+
for (let d = -numBins; d <= numBins; d++) {
|
|
3423
|
+
deltaIds.push(d);
|
|
3424
|
+
}
|
|
3425
|
+
const { distributionX, distributionY } = buildUniformDistribution(deltaIds);
|
|
3426
|
+
const data = encodeFunctionData10({
|
|
3427
|
+
abi: lbRouterAbi,
|
|
3428
|
+
functionName: "addLiquidity",
|
|
3429
|
+
args: [
|
|
3430
|
+
{
|
|
3431
|
+
tokenX: params.tokenX,
|
|
3432
|
+
tokenY: params.tokenY,
|
|
3433
|
+
binStep: BigInt(params.binStep),
|
|
3434
|
+
amountX: params.amountX,
|
|
3435
|
+
amountY: params.amountY,
|
|
3436
|
+
amountXMin: 0n,
|
|
3437
|
+
amountYMin: 0n,
|
|
3438
|
+
activeIdDesired: BigInt(activeIdDesired),
|
|
3439
|
+
idSlippage: BigInt(numBins + 2),
|
|
3440
|
+
deltaIds: deltaIds.map(BigInt),
|
|
3441
|
+
distributionX,
|
|
3442
|
+
distributionY,
|
|
3443
|
+
to: params.recipient,
|
|
3444
|
+
refundTo: params.recipient,
|
|
3445
|
+
deadline
|
|
3446
|
+
}
|
|
3447
|
+
]
|
|
3448
|
+
});
|
|
3449
|
+
return {
|
|
3450
|
+
description: `[${this.protocolName}] LB addLiquidity ${params.amountX} tokenX + ${params.amountY} tokenY across ${deltaIds.length} bins`,
|
|
3451
|
+
to: this.lbRouter,
|
|
3452
|
+
data,
|
|
3453
|
+
value: 0n,
|
|
3454
|
+
gas_estimate: 8e5,
|
|
3455
|
+
approvals: [
|
|
3456
|
+
{ token: params.tokenX, spender: this.lbRouter, amount: params.amountX },
|
|
3457
|
+
{ token: params.tokenY, spender: this.lbRouter, amount: params.amountY }
|
|
3458
|
+
]
|
|
3459
|
+
};
|
|
3460
|
+
}
|
|
3461
|
+
/**
|
|
3462
|
+
* Build a removeLiquidity transaction for specific LB bins.
|
|
3463
|
+
*/
|
|
3464
|
+
async buildRemoveLiquidity(params) {
|
|
3465
|
+
const deadline = params.deadline ?? BigInt("18446744073709551615");
|
|
3466
|
+
const data = encodeFunctionData10({
|
|
3467
|
+
abi: lbRouterAbi,
|
|
3468
|
+
functionName: "removeLiquidity",
|
|
3469
|
+
args: [
|
|
3470
|
+
params.tokenX,
|
|
3471
|
+
params.tokenY,
|
|
3472
|
+
params.binStep,
|
|
3473
|
+
params.amountXMin ?? 0n,
|
|
3474
|
+
params.amountYMin ?? 0n,
|
|
3475
|
+
params.binIds.map(BigInt),
|
|
3476
|
+
params.amounts,
|
|
3477
|
+
params.recipient,
|
|
3478
|
+
deadline
|
|
3479
|
+
]
|
|
3480
|
+
});
|
|
3481
|
+
return {
|
|
3482
|
+
description: `[${this.protocolName}] LB removeLiquidity from ${params.binIds.length} bins`,
|
|
3483
|
+
to: this.lbRouter,
|
|
3484
|
+
data,
|
|
3485
|
+
value: 0n,
|
|
3486
|
+
gas_estimate: 6e5
|
|
3487
|
+
};
|
|
3488
|
+
}
|
|
3489
|
+
/**
|
|
3490
|
+
* Auto-detect bin IDs for a pool from the rewarder's rewarded range.
|
|
3491
|
+
* Falls back to active bin ± 50 scan if no rewarder exists.
|
|
3492
|
+
*/
|
|
3493
|
+
async autoDetectBins(pool) {
|
|
3494
|
+
const rpcUrl = this.requireRpc();
|
|
3495
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3496
|
+
const hooksParams = await client.readContract({
|
|
3497
|
+
address: pool,
|
|
3498
|
+
abi: lbPairAbi,
|
|
3499
|
+
functionName: "getLBHooksParameters"
|
|
3500
|
+
});
|
|
3501
|
+
const rewarder = extractRewarderAddress(hooksParams);
|
|
3502
|
+
if (rewarder) {
|
|
3503
|
+
const range = await client.readContract({
|
|
3504
|
+
address: rewarder,
|
|
3505
|
+
abi: lbRewarderAbi,
|
|
3506
|
+
functionName: "getRewardedRange"
|
|
3507
|
+
});
|
|
3508
|
+
const min = Number(range[0]);
|
|
3509
|
+
const max = Number(range[1]);
|
|
3510
|
+
const ids2 = [];
|
|
3511
|
+
for (let b = min; b <= max; b++) ids2.push(b);
|
|
3512
|
+
return ids2;
|
|
3513
|
+
}
|
|
3514
|
+
const activeId = await client.readContract({
|
|
3515
|
+
address: pool,
|
|
3516
|
+
abi: lbPairAbi,
|
|
3517
|
+
functionName: "getActiveId"
|
|
3518
|
+
});
|
|
3519
|
+
const ids = [];
|
|
3520
|
+
for (let b = activeId - 50; b <= activeId + 50; b++) ids.push(b);
|
|
3521
|
+
return ids;
|
|
3522
|
+
}
|
|
3523
|
+
/**
|
|
3524
|
+
* Get pending MOE rewards for a user across specified bin IDs.
|
|
3525
|
+
* If binIds is omitted, auto-detects from the rewarder's rewarded range.
|
|
3526
|
+
* Reads the rewarder address from the pool's hooks parameters.
|
|
3527
|
+
*/
|
|
3528
|
+
async getPendingRewards(user, pool, binIds) {
|
|
3529
|
+
const rpcUrl = this.requireRpc();
|
|
3530
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3531
|
+
const hooksParams = await client.readContract({
|
|
3532
|
+
address: pool,
|
|
3533
|
+
abi: lbPairAbi,
|
|
3534
|
+
functionName: "getLBHooksParameters"
|
|
3535
|
+
});
|
|
3536
|
+
const rewarder = extractRewarderAddress(hooksParams);
|
|
3537
|
+
if (!rewarder) {
|
|
3538
|
+
return [];
|
|
3539
|
+
}
|
|
3540
|
+
let resolvedBinIds = binIds;
|
|
3541
|
+
if (!resolvedBinIds || resolvedBinIds.length === 0) {
|
|
3542
|
+
const range = await client.readContract({
|
|
3543
|
+
address: rewarder,
|
|
3544
|
+
abi: lbRewarderAbi,
|
|
3545
|
+
functionName: "getRewardedRange"
|
|
3546
|
+
});
|
|
3547
|
+
const min = Number(range[0]);
|
|
3548
|
+
const max = Number(range[1]);
|
|
3549
|
+
resolvedBinIds = [];
|
|
3550
|
+
for (let b = min; b <= max; b++) resolvedBinIds.push(b);
|
|
3551
|
+
}
|
|
3552
|
+
const [pending, rewardToken] = await Promise.all([
|
|
3553
|
+
client.readContract({
|
|
3554
|
+
address: rewarder,
|
|
3555
|
+
abi: lbRewarderAbi,
|
|
3556
|
+
functionName: "getPendingRewards",
|
|
3557
|
+
args: [user, resolvedBinIds.map(BigInt)]
|
|
3558
|
+
}),
|
|
3559
|
+
client.readContract({
|
|
3560
|
+
address: rewarder,
|
|
3561
|
+
abi: lbRewarderAbi,
|
|
3562
|
+
functionName: "getRewardToken"
|
|
3563
|
+
})
|
|
3564
|
+
]);
|
|
3565
|
+
return [
|
|
3566
|
+
{
|
|
3567
|
+
token: rewardToken,
|
|
3568
|
+
symbol: "MOE",
|
|
3569
|
+
amount: pending
|
|
3570
|
+
}
|
|
3571
|
+
];
|
|
3572
|
+
}
|
|
3573
|
+
/**
|
|
3574
|
+
* Build a claim rewards transaction for specific LB bins.
|
|
3575
|
+
* If binIds is omitted, auto-detects from the rewarder's rewarded range.
|
|
3576
|
+
*/
|
|
3577
|
+
async buildClaimRewards(user, pool, binIds) {
|
|
3578
|
+
const rpcUrl = this.requireRpc();
|
|
3579
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3580
|
+
const hooksParams = await client.readContract({
|
|
3581
|
+
address: pool,
|
|
3582
|
+
abi: lbPairAbi,
|
|
3583
|
+
functionName: "getLBHooksParameters"
|
|
3584
|
+
});
|
|
3585
|
+
const rewarder = extractRewarderAddress(hooksParams);
|
|
3586
|
+
if (!rewarder) {
|
|
3587
|
+
throw new DefiError("CONTRACT_ERROR", `[${this.protocolName}] Pool ${pool} has no active rewarder`);
|
|
3588
|
+
}
|
|
3589
|
+
let resolvedBinIds = binIds;
|
|
3590
|
+
if (!resolvedBinIds || resolvedBinIds.length === 0) {
|
|
3591
|
+
const range = await client.readContract({
|
|
3592
|
+
address: rewarder,
|
|
3593
|
+
abi: lbRewarderAbi,
|
|
3594
|
+
functionName: "getRewardedRange"
|
|
3595
|
+
});
|
|
3596
|
+
const min = Number(range[0]);
|
|
3597
|
+
const max = Number(range[1]);
|
|
3598
|
+
resolvedBinIds = [];
|
|
3599
|
+
for (let b = min; b <= max; b++) resolvedBinIds.push(b);
|
|
3600
|
+
}
|
|
3601
|
+
const data = encodeFunctionData10({
|
|
3602
|
+
abi: lbRewarderAbi,
|
|
3603
|
+
functionName: "claim",
|
|
3604
|
+
args: [user, resolvedBinIds.map(BigInt)]
|
|
3605
|
+
});
|
|
3606
|
+
return {
|
|
3607
|
+
description: `[${this.protocolName}] LB claim rewards for ${resolvedBinIds.length} bins`,
|
|
3608
|
+
to: rewarder,
|
|
3609
|
+
data,
|
|
3610
|
+
value: 0n,
|
|
3611
|
+
gas_estimate: 3e5
|
|
3612
|
+
};
|
|
3613
|
+
}
|
|
3614
|
+
/**
|
|
3615
|
+
* Discover all active rewarded LB pools by iterating the factory.
|
|
3616
|
+
* Uses 7 multicall batches to minimise RPC round-trips and avoid 429s.
|
|
3617
|
+
*
|
|
3618
|
+
* Batch 1: getNumberOfLBPairs(), then getLBPairAtIndex(i) for all i
|
|
3619
|
+
* Batch 2: getLBHooksParameters() for all pairs → extract rewarder addresses
|
|
3620
|
+
* Batch 3: isStopped/getRewardedRange/getRewardToken/getPid/getMasterChef for each rewarder
|
|
3621
|
+
* Batch 4: getTokenX/getTokenY for each rewarded pair, then symbol() for unique tokens
|
|
3622
|
+
* Batch 5: Bootstrap MasterChef→VeMoe, then getMoePerSecond/getTreasuryShare/getStaticShare/getTotalWeight/getTopPoolIds
|
|
3623
|
+
* Batch 6: VeMoe.getWeight(pid) for each rewarded pool
|
|
3624
|
+
* Batch 7: Pool.getBin(binId) for all bins in rewarded range of each pool
|
|
3625
|
+
* Price: LB Quoter findBestPathFromAmountIn for MOE/WMNT and WMNT/USDT prices
|
|
3626
|
+
*/
|
|
3627
|
+
async discoverRewardedPools() {
|
|
3628
|
+
const rpcUrl = this.requireRpc();
|
|
3629
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3630
|
+
const pairCount = await client.readContract({
|
|
3631
|
+
address: this.lbFactory,
|
|
3632
|
+
abi: lbFactoryAbi,
|
|
3633
|
+
functionName: "getNumberOfLBPairs"
|
|
3634
|
+
});
|
|
3635
|
+
const count = Number(pairCount);
|
|
3636
|
+
if (count === 0) return [];
|
|
3637
|
+
const batch1Calls = Array.from({ length: count }, (_, i) => [
|
|
3638
|
+
this.lbFactory,
|
|
3639
|
+
encodeFunctionData10({ abi: lbFactoryAbi, functionName: "getLBPairAtIndex", args: [BigInt(i)] })
|
|
3640
|
+
]);
|
|
3641
|
+
const batch1Results = await multicallRead(rpcUrl, batch1Calls);
|
|
3642
|
+
const pairAddresses = batch1Results.map((r) => decodeAddressResult(r)).filter((a) => a !== null);
|
|
3643
|
+
if (pairAddresses.length === 0) return [];
|
|
3644
|
+
const batch2Calls = pairAddresses.map((pair) => [
|
|
3645
|
+
pair,
|
|
3646
|
+
encodeFunctionData10({ abi: lbPairAbi, functionName: "getLBHooksParameters" })
|
|
3647
|
+
]);
|
|
3648
|
+
const batch2Results = await multicallRead(rpcUrl, batch2Calls);
|
|
3649
|
+
const rewardedPairs = [];
|
|
3650
|
+
for (let i = 0; i < pairAddresses.length; i++) {
|
|
3651
|
+
const raw = batch2Results[i];
|
|
3652
|
+
if (!raw) continue;
|
|
3653
|
+
let hooksBytes;
|
|
3654
|
+
try {
|
|
3655
|
+
const _bytes32Abi = parseAbi10(["function f() external view returns (bytes32)"]);
|
|
3656
|
+
hooksBytes = decodeFunctionResult22({ abi: _bytes32Abi, functionName: "f", data: raw });
|
|
3657
|
+
} catch {
|
|
3658
|
+
continue;
|
|
3659
|
+
}
|
|
3660
|
+
const rewarder = extractRewarderAddress(hooksBytes);
|
|
3661
|
+
if (rewarder) {
|
|
3662
|
+
rewardedPairs.push({ pool: pairAddresses[i], rewarder });
|
|
3663
|
+
}
|
|
3664
|
+
}
|
|
3665
|
+
if (rewardedPairs.length === 0) return [];
|
|
3666
|
+
const batch3Calls = [];
|
|
3667
|
+
for (const { rewarder } of rewardedPairs) {
|
|
3668
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "isStopped" })]);
|
|
3669
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getRewardedRange" })]);
|
|
3670
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getRewardToken" })]);
|
|
3671
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getPid" })]);
|
|
3672
|
+
batch3Calls.push([rewarder, encodeFunctionData10({ abi: lbRewarderAbi, functionName: "getMasterChef" })]);
|
|
3673
|
+
}
|
|
3674
|
+
const batch3Results = await multicallRead(rpcUrl, batch3Calls);
|
|
3675
|
+
const batch4aCalls = [];
|
|
3676
|
+
for (const { pool } of rewardedPairs) {
|
|
3677
|
+
batch4aCalls.push([pool, encodeFunctionData10({ abi: lbPairAbi, functionName: "getTokenX" })]);
|
|
3678
|
+
batch4aCalls.push([pool, encodeFunctionData10({ abi: lbPairAbi, functionName: "getTokenY" })]);
|
|
3679
|
+
}
|
|
3680
|
+
const batch4aResults = await multicallRead(rpcUrl, batch4aCalls);
|
|
3681
|
+
const tokenXAddresses = [];
|
|
3682
|
+
const tokenYAddresses = [];
|
|
3683
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3684
|
+
tokenXAddresses.push(decodeAddressResult(batch4aResults[i * 2] ?? null));
|
|
3685
|
+
tokenYAddresses.push(decodeAddressResult(batch4aResults[i * 2 + 1] ?? null));
|
|
3686
|
+
}
|
|
3687
|
+
const uniqueTokens = Array.from(
|
|
3688
|
+
new Set([...tokenXAddresses, ...tokenYAddresses].filter((a) => a !== null))
|
|
3689
|
+
);
|
|
3690
|
+
const batch4bCalls = uniqueTokens.map((token) => [
|
|
3691
|
+
token,
|
|
3692
|
+
encodeFunctionData10({ abi: erc20Abi2, functionName: "symbol" })
|
|
3693
|
+
]);
|
|
3694
|
+
const batch4bResults = await multicallRead(rpcUrl, batch4bCalls);
|
|
3695
|
+
const symbolMap = /* @__PURE__ */ new Map();
|
|
3696
|
+
for (let i = 0; i < uniqueTokens.length; i++) {
|
|
3697
|
+
symbolMap.set(uniqueTokens[i], decodeStringResult(batch4bResults[i] ?? null));
|
|
3698
|
+
}
|
|
3699
|
+
const STRIDE3 = 5;
|
|
3700
|
+
const poolData = [];
|
|
3701
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3702
|
+
const base = i * STRIDE3;
|
|
3703
|
+
poolData.push({
|
|
3704
|
+
stopped: decodeBoolResult(batch3Results[base] ?? null) ?? false,
|
|
3705
|
+
range: decodeRangeResult(batch3Results[base + 1] ?? null),
|
|
3706
|
+
rewardToken: decodeAddressResult(batch3Results[base + 2] ?? null),
|
|
3707
|
+
pid: Number(decodeUint256Result(batch3Results[base + 3] ?? null) ?? 0n),
|
|
3708
|
+
masterChef: decodeAddressResult(batch3Results[base + 4] ?? null)
|
|
3709
|
+
});
|
|
3710
|
+
}
|
|
3711
|
+
const masterChefAddr = poolData.map((d) => d.masterChef).find((a) => a !== null) ?? null;
|
|
3712
|
+
let moePerDay = 0;
|
|
3713
|
+
let topPoolIds = /* @__PURE__ */ new Set();
|
|
3714
|
+
let totalWeightRaw = 0n;
|
|
3715
|
+
let veMoeAddr = null;
|
|
3716
|
+
if (masterChefAddr) {
|
|
3717
|
+
veMoeAddr = await client.readContract({
|
|
3718
|
+
address: masterChefAddr,
|
|
3719
|
+
abi: masterChefAbi,
|
|
3720
|
+
functionName: "getVeMoe"
|
|
3721
|
+
});
|
|
3722
|
+
const batch5Calls = [
|
|
3723
|
+
[masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getMoePerSecond" })],
|
|
3724
|
+
[masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getTreasuryShare" })],
|
|
3725
|
+
[masterChefAddr, encodeFunctionData10({ abi: masterChefAbi, functionName: "getStaticShare" })],
|
|
3726
|
+
[veMoeAddr, encodeFunctionData10({ abi: veMoeAbi, functionName: "getTotalWeight" })],
|
|
3727
|
+
[veMoeAddr, encodeFunctionData10({ abi: veMoeAbi, functionName: "getTopPoolIds" })]
|
|
3728
|
+
];
|
|
3729
|
+
const batch5Results = await multicallRead(rpcUrl, batch5Calls);
|
|
3730
|
+
const moePerSecRaw = decodeUint256Result(batch5Results[0] ?? null) ?? 0n;
|
|
3731
|
+
const treasuryShareRaw = decodeUint256Result(batch5Results[1] ?? null) ?? 0n;
|
|
3732
|
+
const staticShareRaw = decodeUint256Result(batch5Results[2] ?? null) ?? 0n;
|
|
3733
|
+
totalWeightRaw = decodeUint256Result(batch5Results[3] ?? null) ?? 0n;
|
|
3734
|
+
const topPoolIdsRaw = decodeUint256ArrayResult(batch5Results[4] ?? null) ?? [];
|
|
3735
|
+
topPoolIds = new Set(topPoolIdsRaw.map(Number));
|
|
3736
|
+
const PRECISION = 10n ** 18n;
|
|
3737
|
+
const netPerSec = moePerSecRaw * (PRECISION - treasuryShareRaw) / PRECISION * (PRECISION - staticShareRaw) / PRECISION;
|
|
3738
|
+
moePerDay = Number(netPerSec * 86400n) / 1e18;
|
|
3739
|
+
}
|
|
3740
|
+
const weightByPid = /* @__PURE__ */ new Map();
|
|
3741
|
+
if (veMoeAddr && rewardedPairs.length > 0) {
|
|
3742
|
+
const batch6Calls = poolData.map((d) => [
|
|
3743
|
+
veMoeAddr,
|
|
3744
|
+
encodeFunctionData10({ abi: veMoeAbi, functionName: "getWeight", args: [BigInt(d.pid)] })
|
|
3745
|
+
]);
|
|
3746
|
+
const batch6Results = await multicallRead(rpcUrl, batch6Calls);
|
|
3747
|
+
for (let i = 0; i < poolData.length; i++) {
|
|
3748
|
+
weightByPid.set(poolData[i].pid, decodeUint256Result(batch6Results[i] ?? null) ?? 0n);
|
|
3749
|
+
}
|
|
3750
|
+
}
|
|
3751
|
+
let moePriceUsd = 0;
|
|
3752
|
+
let wmntPriceUsd = 0;
|
|
3753
|
+
const MOE_ADDR = "0x4515A45337F461A11Ff0FE8aBF3c606AE5dC00c9";
|
|
3754
|
+
if (this.lbQuoter && this.wmnt && this.usdt) {
|
|
3755
|
+
try {
|
|
3756
|
+
const [moeWmntQuote, wmntUsdtQuote] = await Promise.all([
|
|
3757
|
+
client.readContract({
|
|
3758
|
+
address: this.lbQuoter,
|
|
3759
|
+
abi: lbQuoterAbi2,
|
|
3760
|
+
functionName: "findBestPathFromAmountIn",
|
|
3761
|
+
args: [[MOE_ADDR, this.wmnt], 10n ** 18n]
|
|
3762
|
+
}),
|
|
3763
|
+
client.readContract({
|
|
3764
|
+
address: this.lbQuoter,
|
|
3765
|
+
abi: lbQuoterAbi2,
|
|
3766
|
+
functionName: "findBestPathFromAmountIn",
|
|
3767
|
+
args: [[this.wmnt, this.usdt], 10n ** 18n]
|
|
3768
|
+
})
|
|
3769
|
+
]);
|
|
3770
|
+
const moeInWmnt = Number(moeWmntQuote.amounts.at(-1) ?? 0n) / 1e18;
|
|
3771
|
+
wmntPriceUsd = Number(wmntUsdtQuote.amounts.at(-1) ?? 0n) / 1e6;
|
|
3772
|
+
moePriceUsd = moeInWmnt * wmntPriceUsd;
|
|
3773
|
+
} catch {
|
|
3774
|
+
}
|
|
3775
|
+
}
|
|
3776
|
+
const binRequests = [];
|
|
3777
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3778
|
+
const range = poolData[i].range;
|
|
3779
|
+
if (!range) continue;
|
|
3780
|
+
const minBin = Number(range[0]);
|
|
3781
|
+
const maxBin = Number(range[1]);
|
|
3782
|
+
for (let b = minBin; b <= maxBin; b++) {
|
|
3783
|
+
binRequests.push({ poolIdx: i, binId: b });
|
|
3784
|
+
}
|
|
3785
|
+
}
|
|
3786
|
+
const binReservesX = /* @__PURE__ */ new Map();
|
|
3787
|
+
const binReservesY = /* @__PURE__ */ new Map();
|
|
3788
|
+
if (binRequests.length > 0) {
|
|
3789
|
+
const batch7Calls = binRequests.map(({ poolIdx, binId }) => [
|
|
3790
|
+
rewardedPairs[poolIdx].pool,
|
|
3791
|
+
encodeFunctionData10({ abi: lbPairBinAbi, functionName: "getBin", args: [binId] })
|
|
3792
|
+
]);
|
|
3793
|
+
const batch7Results = await multicallRead(rpcUrl, batch7Calls);
|
|
3794
|
+
for (let j = 0; j < binRequests.length; j++) {
|
|
3795
|
+
const { poolIdx, binId } = binRequests[j];
|
|
3796
|
+
const decoded = decodeBinResult(batch7Results[j] ?? null);
|
|
3797
|
+
if (!decoded) continue;
|
|
3798
|
+
if (!binReservesX.has(poolIdx)) {
|
|
3799
|
+
binReservesX.set(poolIdx, /* @__PURE__ */ new Map());
|
|
3800
|
+
binReservesY.set(poolIdx, /* @__PURE__ */ new Map());
|
|
3801
|
+
}
|
|
3802
|
+
binReservesX.get(poolIdx).set(binId, decoded[0]);
|
|
3803
|
+
binReservesY.get(poolIdx).set(binId, decoded[1]);
|
|
3804
|
+
}
|
|
3805
|
+
}
|
|
3806
|
+
const stableSymbols = /* @__PURE__ */ new Set(["USDT", "USDC", "MUSD", "AUSD", "USDY", "FDUSD"]);
|
|
3807
|
+
const mntSymbols = /* @__PURE__ */ new Set(["WMNT", "MNT"]);
|
|
3808
|
+
const moeSymbols = /* @__PURE__ */ new Set(["MOE"]);
|
|
3809
|
+
const sixDecimalStables = /* @__PURE__ */ new Set(["USDT", "USDC", "FDUSD"]);
|
|
3810
|
+
const getTokenPriceUsd = (sym) => {
|
|
3811
|
+
if (stableSymbols.has(sym)) return 1;
|
|
3812
|
+
if (mntSymbols.has(sym)) return wmntPriceUsd;
|
|
3813
|
+
if (moeSymbols.has(sym)) return moePriceUsd;
|
|
3814
|
+
return 0;
|
|
3815
|
+
};
|
|
3816
|
+
const getTokenDecimals = (sym) => {
|
|
3817
|
+
return sixDecimalStables.has(sym) ? 6 : 18;
|
|
3818
|
+
};
|
|
3819
|
+
const results = [];
|
|
3820
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3821
|
+
const { pool, rewarder } = rewardedPairs[i];
|
|
3822
|
+
const data = poolData[i];
|
|
3823
|
+
const tokenX = tokenXAddresses[i] ?? "0x0000000000000000000000000000000000000000";
|
|
3824
|
+
const tokenY = tokenYAddresses[i] ?? "0x0000000000000000000000000000000000000000";
|
|
3825
|
+
const symX = symbolMap.get(tokenX) ?? "?";
|
|
3826
|
+
const symY = symbolMap.get(tokenY) ?? "?";
|
|
3827
|
+
const isTopPool = topPoolIds.has(data.pid);
|
|
3828
|
+
const weight = weightByPid.get(data.pid) ?? 0n;
|
|
3829
|
+
let poolMoePerDay = 0;
|
|
3830
|
+
if (isTopPool && totalWeightRaw > 0n && weight > 0n) {
|
|
3831
|
+
poolMoePerDay = moePerDay * (Number(weight) / Number(totalWeightRaw));
|
|
3832
|
+
}
|
|
3833
|
+
const rxMap = binReservesX.get(i);
|
|
3834
|
+
const ryMap = binReservesY.get(i);
|
|
3835
|
+
const range = data.range;
|
|
3836
|
+
let rangeTvlUsd = 0;
|
|
3837
|
+
let rewardedBins = 0;
|
|
3838
|
+
if (range) {
|
|
3839
|
+
const minBin = Number(range[0]);
|
|
3840
|
+
const maxBin = Number(range[1]);
|
|
3841
|
+
rewardedBins = maxBin - minBin + 1;
|
|
3842
|
+
if (rxMap && ryMap) {
|
|
3843
|
+
const priceX = getTokenPriceUsd(symX);
|
|
3844
|
+
const priceY = getTokenPriceUsd(symY);
|
|
3845
|
+
const decX = getTokenDecimals(symX);
|
|
3846
|
+
const decY = getTokenDecimals(symY);
|
|
3847
|
+
for (let b = minBin; b <= maxBin; b++) {
|
|
3848
|
+
const rx = rxMap.get(b) ?? 0n;
|
|
3849
|
+
const ry = ryMap.get(b) ?? 0n;
|
|
3850
|
+
rangeTvlUsd += Number(rx) / 10 ** decX * priceX;
|
|
3851
|
+
rangeTvlUsd += Number(ry) / 10 ** decY * priceY;
|
|
3852
|
+
}
|
|
3853
|
+
}
|
|
3854
|
+
}
|
|
3855
|
+
const aprPercent = rangeTvlUsd > 0 && moePriceUsd > 0 ? poolMoePerDay * moePriceUsd * 365 / rangeTvlUsd * 100 : 0;
|
|
3856
|
+
results.push({
|
|
3857
|
+
pool,
|
|
3858
|
+
rewarder,
|
|
3859
|
+
rewardToken: data.rewardToken ?? "0x0000000000000000000000000000000000000000",
|
|
3860
|
+
minBinId: range ? Number(range[0]) : 0,
|
|
3861
|
+
maxBinId: range ? Number(range[1]) : 0,
|
|
3862
|
+
pid: data.pid,
|
|
3863
|
+
stopped: data.stopped,
|
|
3864
|
+
tokenX,
|
|
3865
|
+
tokenY,
|
|
3866
|
+
symbolX: symX,
|
|
3867
|
+
symbolY: symY,
|
|
3868
|
+
isTopPool,
|
|
3869
|
+
moePerDay: poolMoePerDay,
|
|
3870
|
+
rangeTvlUsd,
|
|
3871
|
+
aprPercent,
|
|
3872
|
+
rewardedBins
|
|
3873
|
+
});
|
|
3874
|
+
}
|
|
3875
|
+
return results;
|
|
3876
|
+
}
|
|
3877
|
+
/**
|
|
3878
|
+
* Get a user's LB positions (bin balances) across a range of bin IDs.
|
|
3879
|
+
* If binIds is omitted, auto-detects from the rewarder's rewarded range (or active ± 50).
|
|
3880
|
+
*/
|
|
3881
|
+
async getUserPositions(user, pool, binIds) {
|
|
3882
|
+
const rpcUrl = this.requireRpc();
|
|
3883
|
+
const client = createPublicClient6({ transport: http6(rpcUrl) });
|
|
3884
|
+
const resolvedBinIds = binIds && binIds.length > 0 ? binIds : await this.autoDetectBins(pool);
|
|
3885
|
+
const accounts = resolvedBinIds.map(() => user);
|
|
3886
|
+
const ids = resolvedBinIds.map(BigInt);
|
|
3887
|
+
const balances = await client.readContract({
|
|
3888
|
+
address: pool,
|
|
3889
|
+
abi: lbPairAbi,
|
|
3890
|
+
functionName: "balanceOfBatch",
|
|
3891
|
+
args: [accounts, ids]
|
|
3892
|
+
});
|
|
3893
|
+
return resolvedBinIds.map((binId, i) => ({ binId, balance: balances[i] ?? 0n })).filter((p) => p.balance > 0n);
|
|
3894
|
+
}
|
|
3895
|
+
};
|
|
3896
|
+
var POOL_ABI = parseAbi11([
|
|
3063
3897
|
"function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
|
|
3064
3898
|
"function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
|
|
3065
3899
|
"function repay(address asset, uint256 amount, uint256 interestRateMode, address onBehalfOf) external returns (uint256)",
|
|
@@ -3067,27 +3901,27 @@ var POOL_ABI = parseAbi10([
|
|
|
3067
3901
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)",
|
|
3068
3902
|
"function getReserveData(address asset) external view returns (uint256 configuration, uint128 liquidityIndex, uint128 currentLiquidityRate, uint128 variableBorrowIndex, uint128 currentVariableBorrowRate, uint128 currentStableBorrowRate, uint40 lastUpdateTimestamp, uint16 id, address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress, address interestRateStrategyAddress, uint128 accruedToTreasury, uint128 unbacked, uint128 isolationModeTotalDebt)"
|
|
3069
3903
|
]);
|
|
3070
|
-
var
|
|
3904
|
+
var ERC20_ABI2 = parseAbi11([
|
|
3071
3905
|
"function totalSupply() external view returns (uint256)"
|
|
3072
3906
|
]);
|
|
3073
|
-
var INCENTIVES_ABI =
|
|
3907
|
+
var INCENTIVES_ABI = parseAbi11([
|
|
3074
3908
|
"function getIncentivesController() external view returns (address)"
|
|
3075
3909
|
]);
|
|
3076
|
-
var REWARDS_CONTROLLER_ABI =
|
|
3910
|
+
var REWARDS_CONTROLLER_ABI = parseAbi11([
|
|
3077
3911
|
"function getRewardsByAsset(address asset) external view returns (address[])",
|
|
3078
3912
|
"function getRewardsData(address asset, address reward) external view returns (uint256 index, uint256 emissionsPerSecond, uint256 lastUpdateTimestamp, uint256 distributionEnd)"
|
|
3079
3913
|
]);
|
|
3080
|
-
var POOL_PROVIDER_ABI =
|
|
3914
|
+
var POOL_PROVIDER_ABI = parseAbi11([
|
|
3081
3915
|
"function ADDRESSES_PROVIDER() external view returns (address)"
|
|
3082
3916
|
]);
|
|
3083
|
-
var ADDRESSES_PROVIDER_ABI =
|
|
3917
|
+
var ADDRESSES_PROVIDER_ABI = parseAbi11([
|
|
3084
3918
|
"function getPriceOracle() external view returns (address)"
|
|
3085
3919
|
]);
|
|
3086
|
-
var ORACLE_ABI =
|
|
3920
|
+
var ORACLE_ABI = parseAbi11([
|
|
3087
3921
|
"function getAssetPrice(address asset) external view returns (uint256)",
|
|
3088
3922
|
"function BASE_CURRENCY_UNIT() external view returns (uint256)"
|
|
3089
3923
|
]);
|
|
3090
|
-
var ERC20_DECIMALS_ABI =
|
|
3924
|
+
var ERC20_DECIMALS_ABI = parseAbi11([
|
|
3091
3925
|
"function decimals() external view returns (uint8)"
|
|
3092
3926
|
]);
|
|
3093
3927
|
function u256ToF64(v) {
|
|
@@ -3095,6 +3929,46 @@ function u256ToF64(v) {
|
|
|
3095
3929
|
if (v > MAX_U128) return Infinity;
|
|
3096
3930
|
return Number(v);
|
|
3097
3931
|
}
|
|
3932
|
+
function decodeAddress(data) {
|
|
3933
|
+
if (!data || data.length < 66) return null;
|
|
3934
|
+
return `0x${data.slice(26, 66)}`;
|
|
3935
|
+
}
|
|
3936
|
+
function decodeAddressArray(data) {
|
|
3937
|
+
if (!data) return [];
|
|
3938
|
+
try {
|
|
3939
|
+
return decodeFunctionResult3({
|
|
3940
|
+
abi: REWARDS_CONTROLLER_ABI,
|
|
3941
|
+
functionName: "getRewardsByAsset",
|
|
3942
|
+
data
|
|
3943
|
+
});
|
|
3944
|
+
} catch {
|
|
3945
|
+
return [];
|
|
3946
|
+
}
|
|
3947
|
+
}
|
|
3948
|
+
function decodeReserveData(data) {
|
|
3949
|
+
if (!data) return null;
|
|
3950
|
+
try {
|
|
3951
|
+
return decodeFunctionResult3({
|
|
3952
|
+
abi: POOL_ABI,
|
|
3953
|
+
functionName: "getReserveData",
|
|
3954
|
+
data
|
|
3955
|
+
});
|
|
3956
|
+
} catch {
|
|
3957
|
+
return null;
|
|
3958
|
+
}
|
|
3959
|
+
}
|
|
3960
|
+
function decodeRewardsData(data) {
|
|
3961
|
+
if (!data) return null;
|
|
3962
|
+
try {
|
|
3963
|
+
return decodeFunctionResult3({
|
|
3964
|
+
abi: REWARDS_CONTROLLER_ABI,
|
|
3965
|
+
functionName: "getRewardsData",
|
|
3966
|
+
data
|
|
3967
|
+
});
|
|
3968
|
+
} catch {
|
|
3969
|
+
return null;
|
|
3970
|
+
}
|
|
3971
|
+
}
|
|
3098
3972
|
var AaveV3Adapter = class {
|
|
3099
3973
|
protocolName;
|
|
3100
3974
|
pool;
|
|
@@ -3110,7 +3984,7 @@ var AaveV3Adapter = class {
|
|
|
3110
3984
|
return this.protocolName;
|
|
3111
3985
|
}
|
|
3112
3986
|
async buildSupply(params) {
|
|
3113
|
-
const data =
|
|
3987
|
+
const data = encodeFunctionData11({
|
|
3114
3988
|
abi: POOL_ABI,
|
|
3115
3989
|
functionName: "supply",
|
|
3116
3990
|
args: [params.asset, params.amount, params.on_behalf_of, 0]
|
|
@@ -3120,12 +3994,13 @@ var AaveV3Adapter = class {
|
|
|
3120
3994
|
to: this.pool,
|
|
3121
3995
|
data,
|
|
3122
3996
|
value: 0n,
|
|
3123
|
-
gas_estimate: 3e5
|
|
3997
|
+
gas_estimate: 3e5,
|
|
3998
|
+
approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
|
|
3124
3999
|
};
|
|
3125
4000
|
}
|
|
3126
4001
|
async buildBorrow(params) {
|
|
3127
4002
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
3128
|
-
const data =
|
|
4003
|
+
const data = encodeFunctionData11({
|
|
3129
4004
|
abi: POOL_ABI,
|
|
3130
4005
|
functionName: "borrow",
|
|
3131
4006
|
args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
|
|
@@ -3140,7 +4015,7 @@ var AaveV3Adapter = class {
|
|
|
3140
4015
|
}
|
|
3141
4016
|
async buildRepay(params) {
|
|
3142
4017
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
3143
|
-
const data =
|
|
4018
|
+
const data = encodeFunctionData11({
|
|
3144
4019
|
abi: POOL_ABI,
|
|
3145
4020
|
functionName: "repay",
|
|
3146
4021
|
args: [params.asset, params.amount, rateMode, params.on_behalf_of]
|
|
@@ -3150,11 +4025,12 @@ var AaveV3Adapter = class {
|
|
|
3150
4025
|
to: this.pool,
|
|
3151
4026
|
data,
|
|
3152
4027
|
value: 0n,
|
|
3153
|
-
gas_estimate: 3e5
|
|
4028
|
+
gas_estimate: 3e5,
|
|
4029
|
+
approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
|
|
3154
4030
|
};
|
|
3155
4031
|
}
|
|
3156
4032
|
async buildWithdraw(params) {
|
|
3157
|
-
const data =
|
|
4033
|
+
const data = encodeFunctionData11({
|
|
3158
4034
|
abi: POOL_ABI,
|
|
3159
4035
|
functionName: "withdraw",
|
|
3160
4036
|
args: [params.asset, params.amount, params.to]
|
|
@@ -3169,15 +4045,21 @@ var AaveV3Adapter = class {
|
|
|
3169
4045
|
}
|
|
3170
4046
|
async getRates(asset) {
|
|
3171
4047
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
3172
|
-
const
|
|
3173
|
-
const result = await client.readContract({
|
|
3174
|
-
address: this.pool,
|
|
4048
|
+
const reserveCallData = encodeFunctionData11({
|
|
3175
4049
|
abi: POOL_ABI,
|
|
3176
4050
|
functionName: "getReserveData",
|
|
3177
4051
|
args: [asset]
|
|
3178
|
-
})
|
|
4052
|
+
});
|
|
4053
|
+
const [reserveRaw] = await multicallRead(this.rpcUrl, [
|
|
4054
|
+
[this.pool, reserveCallData]
|
|
4055
|
+
]).catch((e) => {
|
|
3179
4056
|
throw DefiError.rpcError(`[${this.protocolName}] getReserveData failed: ${e}`);
|
|
3180
4057
|
});
|
|
4058
|
+
const reserveDecoded = decodeReserveData(reserveRaw ?? null);
|
|
4059
|
+
if (!reserveDecoded) {
|
|
4060
|
+
throw DefiError.rpcError(`[${this.protocolName}] getReserveData returned no data`);
|
|
4061
|
+
}
|
|
4062
|
+
const result = reserveDecoded;
|
|
3181
4063
|
const RAY = 1e27;
|
|
3182
4064
|
const SECONDS_PER_YEAR4 = 31536e3;
|
|
3183
4065
|
const toApy = (rayRate) => {
|
|
@@ -3189,74 +4071,56 @@ var AaveV3Adapter = class {
|
|
|
3189
4071
|
const stableRate = toApy(result[5]);
|
|
3190
4072
|
const aTokenAddress = result[8];
|
|
3191
4073
|
const variableDebtTokenAddress = result[10];
|
|
3192
|
-
const [
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
abi: ERC20_ABI,
|
|
3196
|
-
functionName: "totalSupply"
|
|
3197
|
-
}).catch(() => 0n),
|
|
3198
|
-
client.readContract({
|
|
3199
|
-
address: variableDebtTokenAddress,
|
|
3200
|
-
abi: ERC20_ABI,
|
|
3201
|
-
functionName: "totalSupply"
|
|
3202
|
-
}).catch(() => 0n)
|
|
4074
|
+
const [supplyRaw, borrowRaw] = await multicallRead(this.rpcUrl, [
|
|
4075
|
+
[aTokenAddress, encodeFunctionData11({ abi: ERC20_ABI2, functionName: "totalSupply" })],
|
|
4076
|
+
[variableDebtTokenAddress, encodeFunctionData11({ abi: ERC20_ABI2, functionName: "totalSupply" })]
|
|
3203
4077
|
]);
|
|
4078
|
+
const totalSupply = decodeU256(supplyRaw ?? null);
|
|
4079
|
+
const totalBorrow = decodeU256(borrowRaw ?? null);
|
|
3204
4080
|
const utilization = totalSupply > 0n ? Number(totalBorrow * 10000n / totalSupply) / 100 : 0;
|
|
3205
4081
|
const supplyRewardTokens = [];
|
|
3206
4082
|
const borrowRewardTokens = [];
|
|
3207
4083
|
const supplyEmissions = [];
|
|
3208
4084
|
const borrowEmissions = [];
|
|
3209
4085
|
try {
|
|
3210
|
-
const
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
});
|
|
4086
|
+
const [controllerRaw] = await multicallRead(this.rpcUrl, [
|
|
4087
|
+
[aTokenAddress, encodeFunctionData11({ abi: INCENTIVES_ABI, functionName: "getIncentivesController" })]
|
|
4088
|
+
]);
|
|
4089
|
+
const controllerAddr = decodeAddress(controllerRaw ?? null);
|
|
3215
4090
|
if (controllerAddr && controllerAddr !== zeroAddress5) {
|
|
3216
|
-
const [
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
abi: REWARDS_CONTROLLER_ABI,
|
|
3220
|
-
functionName: "getRewardsByAsset",
|
|
3221
|
-
args: [aTokenAddress]
|
|
3222
|
-
}).catch(() => []),
|
|
3223
|
-
client.readContract({
|
|
3224
|
-
address: controllerAddr,
|
|
3225
|
-
abi: REWARDS_CONTROLLER_ABI,
|
|
3226
|
-
functionName: "getRewardsByAsset",
|
|
3227
|
-
args: [variableDebtTokenAddress]
|
|
3228
|
-
}).catch(() => [])
|
|
4091
|
+
const [supplyRewardsRaw, borrowRewardsRaw] = await multicallRead(this.rpcUrl, [
|
|
4092
|
+
[controllerAddr, encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [aTokenAddress] })],
|
|
4093
|
+
[controllerAddr, encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsByAsset", args: [variableDebtTokenAddress] })]
|
|
3229
4094
|
]);
|
|
3230
|
-
const
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
args: [aTokenAddress, reward]
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
4095
|
+
const supplyRewards = decodeAddressArray(supplyRewardsRaw ?? null);
|
|
4096
|
+
const borrowRewards = decodeAddressArray(borrowRewardsRaw ?? null);
|
|
4097
|
+
const rewardsDataCalls = [
|
|
4098
|
+
...supplyRewards.map((reward) => [
|
|
4099
|
+
controllerAddr,
|
|
4100
|
+
encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [aTokenAddress, reward] })
|
|
4101
|
+
]),
|
|
4102
|
+
...borrowRewards.map((reward) => [
|
|
4103
|
+
controllerAddr,
|
|
4104
|
+
encodeFunctionData11({ abi: REWARDS_CONTROLLER_ABI, functionName: "getRewardsData", args: [variableDebtTokenAddress, reward] })
|
|
4105
|
+
])
|
|
4106
|
+
];
|
|
4107
|
+
if (rewardsDataCalls.length > 0) {
|
|
4108
|
+
const rewardsDataResults = await multicallRead(this.rpcUrl, rewardsDataCalls);
|
|
4109
|
+
const supplyDataResults = rewardsDataResults.slice(0, supplyRewards.length);
|
|
4110
|
+
const borrowDataResults = rewardsDataResults.slice(supplyRewards.length);
|
|
4111
|
+
for (let i = 0; i < supplyRewards.length; i++) {
|
|
4112
|
+
const data = decodeRewardsData(supplyDataResults[i] ?? null);
|
|
4113
|
+
if (data && data[1] > 0n) {
|
|
4114
|
+
supplyRewardTokens.push(supplyRewards[i]);
|
|
4115
|
+
supplyEmissions.push(data[1].toString());
|
|
4116
|
+
}
|
|
3244
4117
|
}
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
args: [variableDebtTokenAddress, reward]
|
|
3252
|
-
}).catch(() => null)
|
|
3253
|
-
);
|
|
3254
|
-
const borrowData = await Promise.all(borrowDataPromises);
|
|
3255
|
-
for (let i = 0; i < borrowRewards.length; i++) {
|
|
3256
|
-
const data = borrowData[i];
|
|
3257
|
-
if (data && data[1] > 0n) {
|
|
3258
|
-
borrowRewardTokens.push(borrowRewards[i]);
|
|
3259
|
-
borrowEmissions.push(data[1].toString());
|
|
4118
|
+
for (let i = 0; i < borrowRewards.length; i++) {
|
|
4119
|
+
const data = decodeRewardsData(borrowDataResults[i] ?? null);
|
|
4120
|
+
if (data && data[1] > 0n) {
|
|
4121
|
+
borrowRewardTokens.push(borrowRewards[i]);
|
|
4122
|
+
borrowEmissions.push(data[1].toString());
|
|
4123
|
+
}
|
|
3260
4124
|
}
|
|
3261
4125
|
}
|
|
3262
4126
|
}
|
|
@@ -3268,55 +4132,49 @@ var AaveV3Adapter = class {
|
|
|
3268
4132
|
const hasBorrowRewards = borrowRewardTokens.length > 0;
|
|
3269
4133
|
if ((hasSupplyRewards || hasBorrowRewards) && totalSupply > 0n) {
|
|
3270
4134
|
try {
|
|
3271
|
-
const
|
|
3272
|
-
|
|
3273
|
-
abi: POOL_PROVIDER_ABI,
|
|
3274
|
-
functionName: "ADDRESSES_PROVIDER"
|
|
3275
|
-
});
|
|
3276
|
-
const oracleAddr = await client.readContract({
|
|
3277
|
-
address: providerAddr,
|
|
3278
|
-
abi: ADDRESSES_PROVIDER_ABI,
|
|
3279
|
-
functionName: "getPriceOracle"
|
|
3280
|
-
});
|
|
3281
|
-
const [assetPrice, baseCurrencyUnit, assetDecimals] = await Promise.all([
|
|
3282
|
-
client.readContract({
|
|
3283
|
-
address: oracleAddr,
|
|
3284
|
-
abi: ORACLE_ABI,
|
|
3285
|
-
functionName: "getAssetPrice",
|
|
3286
|
-
args: [asset]
|
|
3287
|
-
}),
|
|
3288
|
-
client.readContract({
|
|
3289
|
-
address: oracleAddr,
|
|
3290
|
-
abi: ORACLE_ABI,
|
|
3291
|
-
functionName: "BASE_CURRENCY_UNIT"
|
|
3292
|
-
}),
|
|
3293
|
-
client.readContract({
|
|
3294
|
-
address: asset,
|
|
3295
|
-
abi: ERC20_DECIMALS_ABI,
|
|
3296
|
-
functionName: "decimals"
|
|
3297
|
-
}).catch(() => 18)
|
|
4135
|
+
const [providerRaw] = await multicallRead(this.rpcUrl, [
|
|
4136
|
+
[this.pool, encodeFunctionData11({ abi: POOL_PROVIDER_ABI, functionName: "ADDRESSES_PROVIDER" })]
|
|
3298
4137
|
]);
|
|
3299
|
-
const
|
|
4138
|
+
const providerAddr = decodeAddress(providerRaw ?? null);
|
|
4139
|
+
if (!providerAddr) throw new Error("No provider address");
|
|
4140
|
+
const [oracleRaw] = await multicallRead(this.rpcUrl, [
|
|
4141
|
+
[providerAddr, encodeFunctionData11({ abi: ADDRESSES_PROVIDER_ABI, functionName: "getPriceOracle" })]
|
|
4142
|
+
]);
|
|
4143
|
+
const oracleAddr = decodeAddress(oracleRaw ?? null);
|
|
4144
|
+
if (!oracleAddr) throw new Error("No oracle address");
|
|
4145
|
+
const [assetPriceRaw, baseCurrencyUnitRaw, assetDecimalsRaw] = await multicallRead(this.rpcUrl, [
|
|
4146
|
+
[oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [asset] })],
|
|
4147
|
+
[oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "BASE_CURRENCY_UNIT" })],
|
|
4148
|
+
[asset, encodeFunctionData11({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
|
|
4149
|
+
]);
|
|
4150
|
+
const assetPrice = decodeU256(assetPriceRaw ?? null);
|
|
4151
|
+
const baseCurrencyUnit = decodeU256(baseCurrencyUnitRaw ?? null);
|
|
4152
|
+
const assetDecimals = assetDecimalsRaw ? Number(decodeU256(assetDecimalsRaw)) : 18;
|
|
4153
|
+
const priceUnit = Number(baseCurrencyUnit) || 1e8;
|
|
3300
4154
|
const assetPriceF = Number(assetPrice) / priceUnit;
|
|
3301
4155
|
const assetDecimalsDivisor = 10 ** assetDecimals;
|
|
4156
|
+
const allRewardTokens = Array.from(/* @__PURE__ */ new Set([...supplyRewardTokens, ...borrowRewardTokens]));
|
|
4157
|
+
const rewardPriceCalls = allRewardTokens.flatMap((token) => [
|
|
4158
|
+
[oracleAddr, encodeFunctionData11({ abi: ORACLE_ABI, functionName: "getAssetPrice", args: [token] })],
|
|
4159
|
+
[token, encodeFunctionData11({ abi: ERC20_DECIMALS_ABI, functionName: "decimals" })]
|
|
4160
|
+
]);
|
|
4161
|
+
const rewardPriceResults = rewardPriceCalls.length > 0 ? await multicallRead(this.rpcUrl, rewardPriceCalls) : [];
|
|
4162
|
+
const rewardPriceMap = /* @__PURE__ */ new Map();
|
|
4163
|
+
for (let i = 0; i < allRewardTokens.length; i++) {
|
|
4164
|
+
const priceRaw = rewardPriceResults[i * 2] ?? null;
|
|
4165
|
+
const decimalsRaw = rewardPriceResults[i * 2 + 1] ?? null;
|
|
4166
|
+
const price = decodeU256(priceRaw);
|
|
4167
|
+
const decimals = decimalsRaw ? Number(decodeU256(decimalsRaw)) : 18;
|
|
4168
|
+
rewardPriceMap.set(allRewardTokens[i].toLowerCase(), { price, decimals });
|
|
4169
|
+
}
|
|
3302
4170
|
if (hasSupplyRewards) {
|
|
3303
4171
|
let totalSupplyIncentiveUsdPerYear = 0;
|
|
3304
4172
|
const totalSupplyUsd = Number(totalSupply) / assetDecimalsDivisor * assetPriceF;
|
|
3305
4173
|
for (let i = 0; i < supplyRewardTokens.length; i++) {
|
|
3306
4174
|
const emissionPerSec = BigInt(supplyEmissions[i]);
|
|
3307
|
-
const
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
abi: ORACLE_ABI,
|
|
3311
|
-
functionName: "getAssetPrice",
|
|
3312
|
-
args: [supplyRewardTokens[i]]
|
|
3313
|
-
}).catch(() => 0n),
|
|
3314
|
-
client.readContract({
|
|
3315
|
-
address: supplyRewardTokens[i],
|
|
3316
|
-
abi: ERC20_DECIMALS_ABI,
|
|
3317
|
-
functionName: "decimals"
|
|
3318
|
-
}).catch(() => 18)
|
|
3319
|
-
]);
|
|
4175
|
+
const entry = rewardPriceMap.get(supplyRewardTokens[i].toLowerCase());
|
|
4176
|
+
const rewardPrice = entry?.price ?? 0n;
|
|
4177
|
+
const rewardDecimals = entry?.decimals ?? 18;
|
|
3320
4178
|
if (rewardPrice > 0n) {
|
|
3321
4179
|
const rewardPriceF = Number(rewardPrice) / priceUnit;
|
|
3322
4180
|
const emissionPerYear = Number(emissionPerSec) / 10 ** rewardDecimals * SECONDS_PER_YEAR4;
|
|
@@ -3332,19 +4190,9 @@ var AaveV3Adapter = class {
|
|
|
3332
4190
|
const totalBorrowUsd = Number(totalBorrow) / assetDecimalsDivisor * assetPriceF;
|
|
3333
4191
|
for (let i = 0; i < borrowRewardTokens.length; i++) {
|
|
3334
4192
|
const emissionPerSec = BigInt(borrowEmissions[i]);
|
|
3335
|
-
const
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
abi: ORACLE_ABI,
|
|
3339
|
-
functionName: "getAssetPrice",
|
|
3340
|
-
args: [borrowRewardTokens[i]]
|
|
3341
|
-
}).catch(() => 0n),
|
|
3342
|
-
client.readContract({
|
|
3343
|
-
address: borrowRewardTokens[i],
|
|
3344
|
-
abi: ERC20_DECIMALS_ABI,
|
|
3345
|
-
functionName: "decimals"
|
|
3346
|
-
}).catch(() => 18)
|
|
3347
|
-
]);
|
|
4193
|
+
const entry = rewardPriceMap.get(borrowRewardTokens[i].toLowerCase());
|
|
4194
|
+
const rewardPrice = entry?.price ?? 0n;
|
|
4195
|
+
const rewardDecimals = entry?.decimals ?? 18;
|
|
3348
4196
|
if (rewardPrice > 0n) {
|
|
3349
4197
|
const rewardPriceF = Number(rewardPrice) / priceUnit;
|
|
3350
4198
|
const emissionPerYear = Number(emissionPerSec) / 10 ** rewardDecimals * SECONDS_PER_YEAR4;
|
|
@@ -3408,7 +4256,7 @@ var AaveV3Adapter = class {
|
|
|
3408
4256
|
};
|
|
3409
4257
|
}
|
|
3410
4258
|
};
|
|
3411
|
-
var POOL_ABI2 =
|
|
4259
|
+
var POOL_ABI2 = parseAbi12([
|
|
3412
4260
|
"function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external",
|
|
3413
4261
|
"function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external",
|
|
3414
4262
|
"function repay(address asset, uint256 amount, uint256 rateMode, address onBehalfOf) external returns (uint256)",
|
|
@@ -3421,7 +4269,7 @@ var POOL_ABI2 = parseAbi11([
|
|
|
3421
4269
|
// [9]=variableDebtTokenAddress, [10]=interestRateStrategyAddress, [11]=id
|
|
3422
4270
|
"function getReserveData(address asset) external view returns (uint256 configuration, uint128 liquidityIndex, uint128 variableBorrowIndex, uint128 currentLiquidityRate, uint128 currentVariableBorrowRate, uint128 currentStableBorrowRate, uint40 lastUpdateTimestamp, address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress, address interestRateStrategyAddress, uint8 id)"
|
|
3423
4271
|
]);
|
|
3424
|
-
var
|
|
4272
|
+
var ERC20_ABI22 = parseAbi12([
|
|
3425
4273
|
"function totalSupply() external view returns (uint256)"
|
|
3426
4274
|
]);
|
|
3427
4275
|
function u256ToF642(v) {
|
|
@@ -3444,7 +4292,7 @@ var AaveV2Adapter = class {
|
|
|
3444
4292
|
return this.protocolName;
|
|
3445
4293
|
}
|
|
3446
4294
|
async buildSupply(params) {
|
|
3447
|
-
const data =
|
|
4295
|
+
const data = encodeFunctionData12({
|
|
3448
4296
|
abi: POOL_ABI2,
|
|
3449
4297
|
functionName: "deposit",
|
|
3450
4298
|
args: [params.asset, params.amount, params.on_behalf_of, 0]
|
|
@@ -3454,12 +4302,13 @@ var AaveV2Adapter = class {
|
|
|
3454
4302
|
to: this.pool,
|
|
3455
4303
|
data,
|
|
3456
4304
|
value: 0n,
|
|
3457
|
-
gas_estimate: 3e5
|
|
4305
|
+
gas_estimate: 3e5,
|
|
4306
|
+
approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
|
|
3458
4307
|
};
|
|
3459
4308
|
}
|
|
3460
4309
|
async buildBorrow(params) {
|
|
3461
4310
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
3462
|
-
const data =
|
|
4311
|
+
const data = encodeFunctionData12({
|
|
3463
4312
|
abi: POOL_ABI2,
|
|
3464
4313
|
functionName: "borrow",
|
|
3465
4314
|
args: [params.asset, params.amount, rateMode, 0, params.on_behalf_of]
|
|
@@ -3474,7 +4323,7 @@ var AaveV2Adapter = class {
|
|
|
3474
4323
|
}
|
|
3475
4324
|
async buildRepay(params) {
|
|
3476
4325
|
const rateMode = params.interest_rate_mode === InterestRateMode.Stable ? 1n : 2n;
|
|
3477
|
-
const data =
|
|
4326
|
+
const data = encodeFunctionData12({
|
|
3478
4327
|
abi: POOL_ABI2,
|
|
3479
4328
|
functionName: "repay",
|
|
3480
4329
|
args: [params.asset, params.amount, rateMode, params.on_behalf_of]
|
|
@@ -3484,11 +4333,12 @@ var AaveV2Adapter = class {
|
|
|
3484
4333
|
to: this.pool,
|
|
3485
4334
|
data,
|
|
3486
4335
|
value: 0n,
|
|
3487
|
-
gas_estimate: 3e5
|
|
4336
|
+
gas_estimate: 3e5,
|
|
4337
|
+
approvals: [{ token: params.asset, spender: this.pool, amount: params.amount }]
|
|
3488
4338
|
};
|
|
3489
4339
|
}
|
|
3490
4340
|
async buildWithdraw(params) {
|
|
3491
|
-
const data =
|
|
4341
|
+
const data = encodeFunctionData12({
|
|
3492
4342
|
abi: POOL_ABI2,
|
|
3493
4343
|
functionName: "withdraw",
|
|
3494
4344
|
args: [params.asset, params.amount, params.to]
|
|
@@ -3526,12 +4376,12 @@ var AaveV2Adapter = class {
|
|
|
3526
4376
|
const [totalSupply, totalBorrow] = await Promise.all([
|
|
3527
4377
|
client.readContract({
|
|
3528
4378
|
address: aTokenAddress,
|
|
3529
|
-
abi:
|
|
4379
|
+
abi: ERC20_ABI22,
|
|
3530
4380
|
functionName: "totalSupply"
|
|
3531
4381
|
}).catch(() => 0n),
|
|
3532
4382
|
client.readContract({
|
|
3533
4383
|
address: variableDebtTokenAddress,
|
|
3534
|
-
abi:
|
|
4384
|
+
abi: ERC20_ABI22,
|
|
3535
4385
|
functionName: "totalSupply"
|
|
3536
4386
|
}).catch(() => 0n)
|
|
3537
4387
|
]);
|
|
@@ -3576,7 +4426,7 @@ var AaveV2Adapter = class {
|
|
|
3576
4426
|
};
|
|
3577
4427
|
}
|
|
3578
4428
|
};
|
|
3579
|
-
var ORACLE_ABI2 =
|
|
4429
|
+
var ORACLE_ABI2 = parseAbi13([
|
|
3580
4430
|
"function getAssetPrice(address asset) external view returns (uint256)",
|
|
3581
4431
|
"function getAssetsPrices(address[] calldata assets) external view returns (uint256[] memory)",
|
|
3582
4432
|
"function BASE_CURRENCY_UNIT() external view returns (uint256)"
|
|
@@ -3653,7 +4503,7 @@ var AaveOracleAdapter = class {
|
|
|
3653
4503
|
});
|
|
3654
4504
|
}
|
|
3655
4505
|
};
|
|
3656
|
-
var CTOKEN_ABI =
|
|
4506
|
+
var CTOKEN_ABI = parseAbi14([
|
|
3657
4507
|
"function supplyRatePerBlock() external view returns (uint256)",
|
|
3658
4508
|
"function borrowRatePerBlock() external view returns (uint256)",
|
|
3659
4509
|
"function totalSupply() external view returns (uint256)",
|
|
@@ -3680,7 +4530,7 @@ var CompoundV2Adapter = class {
|
|
|
3680
4530
|
return this.protocolName;
|
|
3681
4531
|
}
|
|
3682
4532
|
async buildSupply(params) {
|
|
3683
|
-
const data =
|
|
4533
|
+
const data = encodeFunctionData13({
|
|
3684
4534
|
abi: CTOKEN_ABI,
|
|
3685
4535
|
functionName: "mint",
|
|
3686
4536
|
args: [params.amount]
|
|
@@ -3694,7 +4544,7 @@ var CompoundV2Adapter = class {
|
|
|
3694
4544
|
};
|
|
3695
4545
|
}
|
|
3696
4546
|
async buildBorrow(params) {
|
|
3697
|
-
const data =
|
|
4547
|
+
const data = encodeFunctionData13({
|
|
3698
4548
|
abi: CTOKEN_ABI,
|
|
3699
4549
|
functionName: "borrow",
|
|
3700
4550
|
args: [params.amount]
|
|
@@ -3708,7 +4558,7 @@ var CompoundV2Adapter = class {
|
|
|
3708
4558
|
};
|
|
3709
4559
|
}
|
|
3710
4560
|
async buildRepay(params) {
|
|
3711
|
-
const data =
|
|
4561
|
+
const data = encodeFunctionData13({
|
|
3712
4562
|
abi: CTOKEN_ABI,
|
|
3713
4563
|
functionName: "repayBorrow",
|
|
3714
4564
|
args: [params.amount]
|
|
@@ -3722,7 +4572,7 @@ var CompoundV2Adapter = class {
|
|
|
3722
4572
|
};
|
|
3723
4573
|
}
|
|
3724
4574
|
async buildWithdraw(params) {
|
|
3725
|
-
const data =
|
|
4575
|
+
const data = encodeFunctionData13({
|
|
3726
4576
|
abi: CTOKEN_ABI,
|
|
3727
4577
|
functionName: "redeem",
|
|
3728
4578
|
args: [params.amount]
|
|
@@ -3771,7 +4621,7 @@ var CompoundV2Adapter = class {
|
|
|
3771
4621
|
);
|
|
3772
4622
|
}
|
|
3773
4623
|
};
|
|
3774
|
-
var COMET_ABI =
|
|
4624
|
+
var COMET_ABI = parseAbi15([
|
|
3775
4625
|
"function getUtilization() external view returns (uint256)",
|
|
3776
4626
|
"function getSupplyRate(uint256 utilization) external view returns (uint64)",
|
|
3777
4627
|
"function getBorrowRate(uint256 utilization) external view returns (uint64)",
|
|
@@ -3797,7 +4647,7 @@ var CompoundV3Adapter = class {
|
|
|
3797
4647
|
return this.protocolName;
|
|
3798
4648
|
}
|
|
3799
4649
|
async buildSupply(params) {
|
|
3800
|
-
const data =
|
|
4650
|
+
const data = encodeFunctionData14({
|
|
3801
4651
|
abi: COMET_ABI,
|
|
3802
4652
|
functionName: "supply",
|
|
3803
4653
|
args: [params.asset, params.amount]
|
|
@@ -3811,7 +4661,7 @@ var CompoundV3Adapter = class {
|
|
|
3811
4661
|
};
|
|
3812
4662
|
}
|
|
3813
4663
|
async buildBorrow(params) {
|
|
3814
|
-
const data =
|
|
4664
|
+
const data = encodeFunctionData14({
|
|
3815
4665
|
abi: COMET_ABI,
|
|
3816
4666
|
functionName: "withdraw",
|
|
3817
4667
|
args: [params.asset, params.amount]
|
|
@@ -3825,7 +4675,7 @@ var CompoundV3Adapter = class {
|
|
|
3825
4675
|
};
|
|
3826
4676
|
}
|
|
3827
4677
|
async buildRepay(params) {
|
|
3828
|
-
const data =
|
|
4678
|
+
const data = encodeFunctionData14({
|
|
3829
4679
|
abi: COMET_ABI,
|
|
3830
4680
|
functionName: "supply",
|
|
3831
4681
|
args: [params.asset, params.amount]
|
|
@@ -3839,7 +4689,7 @@ var CompoundV3Adapter = class {
|
|
|
3839
4689
|
};
|
|
3840
4690
|
}
|
|
3841
4691
|
async buildWithdraw(params) {
|
|
3842
|
-
const data =
|
|
4692
|
+
const data = encodeFunctionData14({
|
|
3843
4693
|
abi: COMET_ABI,
|
|
3844
4694
|
functionName: "withdraw",
|
|
3845
4695
|
args: [params.asset, params.amount]
|
|
@@ -3893,7 +4743,7 @@ var CompoundV3Adapter = class {
|
|
|
3893
4743
|
);
|
|
3894
4744
|
}
|
|
3895
4745
|
};
|
|
3896
|
-
var EULER_VAULT_ABI =
|
|
4746
|
+
var EULER_VAULT_ABI = parseAbi16([
|
|
3897
4747
|
"function deposit(uint256 amount, address receiver) external returns (uint256)",
|
|
3898
4748
|
"function withdraw(uint256 amount, address receiver, address owner) external returns (uint256)",
|
|
3899
4749
|
"function borrow(uint256 amount, address receiver) external returns (uint256)",
|
|
@@ -3919,7 +4769,7 @@ var EulerV2Adapter = class {
|
|
|
3919
4769
|
return this.protocolName;
|
|
3920
4770
|
}
|
|
3921
4771
|
async buildSupply(params) {
|
|
3922
|
-
const data =
|
|
4772
|
+
const data = encodeFunctionData15({
|
|
3923
4773
|
abi: EULER_VAULT_ABI,
|
|
3924
4774
|
functionName: "deposit",
|
|
3925
4775
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -3933,7 +4783,7 @@ var EulerV2Adapter = class {
|
|
|
3933
4783
|
};
|
|
3934
4784
|
}
|
|
3935
4785
|
async buildBorrow(params) {
|
|
3936
|
-
const data =
|
|
4786
|
+
const data = encodeFunctionData15({
|
|
3937
4787
|
abi: EULER_VAULT_ABI,
|
|
3938
4788
|
functionName: "borrow",
|
|
3939
4789
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -3947,7 +4797,7 @@ var EulerV2Adapter = class {
|
|
|
3947
4797
|
};
|
|
3948
4798
|
}
|
|
3949
4799
|
async buildRepay(params) {
|
|
3950
|
-
const data =
|
|
4800
|
+
const data = encodeFunctionData15({
|
|
3951
4801
|
abi: EULER_VAULT_ABI,
|
|
3952
4802
|
functionName: "repay",
|
|
3953
4803
|
args: [params.amount, params.on_behalf_of]
|
|
@@ -3961,7 +4811,7 @@ var EulerV2Adapter = class {
|
|
|
3961
4811
|
};
|
|
3962
4812
|
}
|
|
3963
4813
|
async buildWithdraw(params) {
|
|
3964
|
-
const data =
|
|
4814
|
+
const data = encodeFunctionData15({
|
|
3965
4815
|
abi: EULER_VAULT_ABI,
|
|
3966
4816
|
functionName: "withdraw",
|
|
3967
4817
|
args: [params.amount, params.to, params.to]
|
|
@@ -4010,7 +4860,7 @@ var EulerV2Adapter = class {
|
|
|
4010
4860
|
);
|
|
4011
4861
|
}
|
|
4012
4862
|
};
|
|
4013
|
-
var MORPHO_ABI =
|
|
4863
|
+
var MORPHO_ABI = parseAbi17([
|
|
4014
4864
|
"function market(bytes32 id) external view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)",
|
|
4015
4865
|
"function idToMarketParams(bytes32 id) external view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)",
|
|
4016
4866
|
"function supply((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, uint256 shares, address onBehalf, bytes data) external returns (uint256 assetsSupplied, uint256 sharesSupplied)",
|
|
@@ -4018,13 +4868,13 @@ var MORPHO_ABI = parseAbi16([
|
|
|
4018
4868
|
"function repay((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, uint256 shares, address onBehalf, bytes data) external returns (uint256 assetsRepaid, uint256 sharesRepaid)",
|
|
4019
4869
|
"function withdraw((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, uint256 shares, address onBehalf, address receiver) external returns (uint256 assetsWithdrawn, uint256 sharesWithdrawn)"
|
|
4020
4870
|
]);
|
|
4021
|
-
var META_MORPHO_ABI =
|
|
4871
|
+
var META_MORPHO_ABI = parseAbi17([
|
|
4022
4872
|
"function supplyQueueLength() external view returns (uint256)",
|
|
4023
4873
|
"function supplyQueue(uint256 index) external view returns (bytes32)",
|
|
4024
4874
|
"function totalAssets() external view returns (uint256)",
|
|
4025
4875
|
"function totalSupply() external view returns (uint256)"
|
|
4026
4876
|
]);
|
|
4027
|
-
var IRM_ABI =
|
|
4877
|
+
var IRM_ABI = parseAbi17([
|
|
4028
4878
|
"function borrowRateView((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee) market) external view returns (uint256)"
|
|
4029
4879
|
]);
|
|
4030
4880
|
var SECONDS_PER_YEAR3 = 365.25 * 24 * 3600;
|
|
@@ -4037,6 +4887,30 @@ function defaultMarketParams(loanToken = zeroAddress7) {
|
|
|
4037
4887
|
lltv: 0n
|
|
4038
4888
|
};
|
|
4039
4889
|
}
|
|
4890
|
+
function decodeMarket(data) {
|
|
4891
|
+
if (!data) return null;
|
|
4892
|
+
try {
|
|
4893
|
+
return decodeFunctionResult4({
|
|
4894
|
+
abi: MORPHO_ABI,
|
|
4895
|
+
functionName: "market",
|
|
4896
|
+
data
|
|
4897
|
+
});
|
|
4898
|
+
} catch {
|
|
4899
|
+
return null;
|
|
4900
|
+
}
|
|
4901
|
+
}
|
|
4902
|
+
function decodeMarketParams(data) {
|
|
4903
|
+
if (!data) return null;
|
|
4904
|
+
try {
|
|
4905
|
+
return decodeFunctionResult4({
|
|
4906
|
+
abi: MORPHO_ABI,
|
|
4907
|
+
functionName: "idToMarketParams",
|
|
4908
|
+
data
|
|
4909
|
+
});
|
|
4910
|
+
} catch {
|
|
4911
|
+
return null;
|
|
4912
|
+
}
|
|
4913
|
+
}
|
|
4040
4914
|
var MorphoBlueAdapter = class {
|
|
4041
4915
|
protocolName;
|
|
4042
4916
|
morpho;
|
|
@@ -4056,7 +4930,7 @@ var MorphoBlueAdapter = class {
|
|
|
4056
4930
|
}
|
|
4057
4931
|
async buildSupply(params) {
|
|
4058
4932
|
const market = defaultMarketParams(params.asset);
|
|
4059
|
-
const data =
|
|
4933
|
+
const data = encodeFunctionData16({
|
|
4060
4934
|
abi: MORPHO_ABI,
|
|
4061
4935
|
functionName: "supply",
|
|
4062
4936
|
args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
|
|
@@ -4071,7 +4945,7 @@ var MorphoBlueAdapter = class {
|
|
|
4071
4945
|
}
|
|
4072
4946
|
async buildBorrow(params) {
|
|
4073
4947
|
const market = defaultMarketParams(params.asset);
|
|
4074
|
-
const data =
|
|
4948
|
+
const data = encodeFunctionData16({
|
|
4075
4949
|
abi: MORPHO_ABI,
|
|
4076
4950
|
functionName: "borrow",
|
|
4077
4951
|
args: [market, params.amount, 0n, params.on_behalf_of, params.on_behalf_of]
|
|
@@ -4086,7 +4960,7 @@ var MorphoBlueAdapter = class {
|
|
|
4086
4960
|
}
|
|
4087
4961
|
async buildRepay(params) {
|
|
4088
4962
|
const market = defaultMarketParams(params.asset);
|
|
4089
|
-
const data =
|
|
4963
|
+
const data = encodeFunctionData16({
|
|
4090
4964
|
abi: MORPHO_ABI,
|
|
4091
4965
|
functionName: "repay",
|
|
4092
4966
|
args: [market, params.amount, 0n, params.on_behalf_of, "0x"]
|
|
@@ -4101,7 +4975,7 @@ var MorphoBlueAdapter = class {
|
|
|
4101
4975
|
}
|
|
4102
4976
|
async buildWithdraw(params) {
|
|
4103
4977
|
const market = defaultMarketParams(params.asset);
|
|
4104
|
-
const data =
|
|
4978
|
+
const data = encodeFunctionData16({
|
|
4105
4979
|
abi: MORPHO_ABI,
|
|
4106
4980
|
functionName: "withdraw",
|
|
4107
4981
|
args: [market, params.amount, 0n, params.to, params.to]
|
|
@@ -4119,14 +4993,12 @@ var MorphoBlueAdapter = class {
|
|
|
4119
4993
|
if (!this.defaultVault) {
|
|
4120
4994
|
throw DefiError.contractError(`[${this.protocolName}] No MetaMorpho vault configured for rate query`);
|
|
4121
4995
|
}
|
|
4122
|
-
const
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
abi: META_MORPHO_ABI,
|
|
4126
|
-
functionName: "supplyQueueLength"
|
|
4127
|
-
}).catch((e) => {
|
|
4996
|
+
const [queueLenRaw] = await multicallRead(this.rpcUrl, [
|
|
4997
|
+
[this.defaultVault, encodeFunctionData16({ abi: META_MORPHO_ABI, functionName: "supplyQueueLength" })]
|
|
4998
|
+
]).catch((e) => {
|
|
4128
4999
|
throw DefiError.rpcError(`[${this.protocolName}] supplyQueueLength failed: ${e}`);
|
|
4129
5000
|
});
|
|
5001
|
+
const queueLen = decodeU256(queueLenRaw ?? null);
|
|
4130
5002
|
if (queueLen === 0n) {
|
|
4131
5003
|
return {
|
|
4132
5004
|
protocol: this.protocolName,
|
|
@@ -4138,45 +5010,40 @@ var MorphoBlueAdapter = class {
|
|
|
4138
5010
|
total_borrow: 0n
|
|
4139
5011
|
};
|
|
4140
5012
|
}
|
|
4141
|
-
const
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
functionName: "supplyQueue",
|
|
4145
|
-
args: [0n]
|
|
4146
|
-
}).catch((e) => {
|
|
5013
|
+
const [marketIdRaw] = await multicallRead(this.rpcUrl, [
|
|
5014
|
+
[this.defaultVault, encodeFunctionData16({ abi: META_MORPHO_ABI, functionName: "supplyQueue", args: [0n] })]
|
|
5015
|
+
]).catch((e) => {
|
|
4147
5016
|
throw DefiError.rpcError(`[${this.protocolName}] supplyQueue(0) failed: ${e}`);
|
|
4148
5017
|
});
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
5018
|
+
if (!marketIdRaw || marketIdRaw.length < 66) {
|
|
5019
|
+
throw DefiError.rpcError(`[${this.protocolName}] supplyQueue(0) returned no data`);
|
|
5020
|
+
}
|
|
5021
|
+
const marketId = marketIdRaw.slice(0, 66);
|
|
5022
|
+
const [marketRaw, paramsRaw] = await multicallRead(this.rpcUrl, [
|
|
5023
|
+
[this.morpho, encodeFunctionData16({ abi: MORPHO_ABI, functionName: "market", args: [marketId] })],
|
|
5024
|
+
[this.morpho, encodeFunctionData16({ abi: MORPHO_ABI, functionName: "idToMarketParams", args: [marketId] })]
|
|
5025
|
+
]).catch((e) => {
|
|
5026
|
+
throw DefiError.rpcError(`[${this.protocolName}] market/idToMarketParams failed: ${e}`);
|
|
4156
5027
|
});
|
|
4157
|
-
const
|
|
5028
|
+
const mktDecoded = decodeMarket(marketRaw ?? null);
|
|
5029
|
+
if (!mktDecoded) throw DefiError.rpcError(`[${this.protocolName}] market() returned no data`);
|
|
5030
|
+
const [totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee] = mktDecoded;
|
|
5031
|
+
const paramsDecoded = decodeMarketParams(paramsRaw ?? null);
|
|
5032
|
+
if (!paramsDecoded) throw DefiError.rpcError(`[${this.protocolName}] idToMarketParams returned no data`);
|
|
5033
|
+
const [loanToken, collateralToken, oracle, irm, lltv] = paramsDecoded;
|
|
4158
5034
|
const supplyF = Number(totalSupplyAssets);
|
|
4159
5035
|
const borrowF = Number(totalBorrowAssets);
|
|
4160
5036
|
const util = supplyF > 0 ? borrowF / supplyF : 0;
|
|
4161
|
-
const params2 = await client.readContract({
|
|
4162
|
-
address: this.morpho,
|
|
4163
|
-
abi: MORPHO_ABI,
|
|
4164
|
-
functionName: "idToMarketParams",
|
|
4165
|
-
args: [marketId]
|
|
4166
|
-
}).catch((e) => {
|
|
4167
|
-
throw DefiError.rpcError(`[${this.protocolName}] idToMarketParams failed: ${e}`);
|
|
4168
|
-
});
|
|
4169
|
-
const [loanToken, collateralToken, oracle, irm, lltv] = params2;
|
|
4170
5037
|
const irmMarketParams = { loanToken, collateralToken, oracle, irm, lltv };
|
|
4171
5038
|
const irmMarket = { totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee };
|
|
4172
|
-
const borrowRatePerSec = await
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
});
|
|
5039
|
+
const borrowRatePerSec = await (async () => {
|
|
5040
|
+
const [borrowRateRaw] = await multicallRead(this.rpcUrl, [
|
|
5041
|
+
[irm, encodeFunctionData16({ abi: IRM_ABI, functionName: "borrowRateView", args: [irmMarketParams, irmMarket] })]
|
|
5042
|
+
]).catch((e) => {
|
|
5043
|
+
throw DefiError.rpcError(`[${this.protocolName}] borrowRateView failed: ${e}`);
|
|
5044
|
+
});
|
|
5045
|
+
return decodeU256(borrowRateRaw ?? null);
|
|
5046
|
+
})();
|
|
4180
5047
|
const ratePerSec = Number(borrowRatePerSec) / 1e18;
|
|
4181
5048
|
const borrowApy = ratePerSec * SECONDS_PER_YEAR3 * 100;
|
|
4182
5049
|
const feePct = Number(fee) / 1e18;
|
|
@@ -4197,18 +5064,18 @@ var MorphoBlueAdapter = class {
|
|
|
4197
5064
|
);
|
|
4198
5065
|
}
|
|
4199
5066
|
};
|
|
4200
|
-
var BORROWER_OPS_ABI =
|
|
5067
|
+
var BORROWER_OPS_ABI = parseAbi18([
|
|
4201
5068
|
"function openTrove(address _owner, uint256 _ownerIndex, uint256 _collAmount, uint256 _boldAmount, uint256 _upperHint, uint256 _lowerHint, uint256 _annualInterestRate, uint256 _maxUpfrontFee, address _addManager, address _removeManager, address _receiver) external returns (uint256)",
|
|
4202
5069
|
"function adjustTrove(uint256 _troveId, uint256 _collChange, bool _isCollIncrease, uint256 _debtChange, bool _isDebtIncrease, uint256 _upperHint, uint256 _lowerHint, uint256 _maxUpfrontFee) external",
|
|
4203
5070
|
"function closeTrove(uint256 _troveId) external"
|
|
4204
5071
|
]);
|
|
4205
|
-
var TROVE_MANAGER_ABI =
|
|
5072
|
+
var TROVE_MANAGER_ABI = parseAbi18([
|
|
4206
5073
|
"function getLatestTroveData(uint256 _troveId) external view returns (uint256 entireDebt, uint256 entireColl, uint256 redistDebtGain, uint256 redistCollGain, uint256 accruedInterest, uint256 recordedDebt, uint256 annualInterestRate, uint256 accruedBatchManagementFee, uint256 weightedRecordedDebt, uint256 lastInterestRateAdjTime)"
|
|
4207
5074
|
]);
|
|
4208
|
-
var HINT_HELPERS_ABI =
|
|
5075
|
+
var HINT_HELPERS_ABI = parseAbi18([
|
|
4209
5076
|
"function getApproxHint(uint256 _collIndex, uint256 _interestRate, uint256 _numTrials, uint256 _inputRandomSeed) external view returns (uint256 hintId, uint256 diff, uint256 latestRandomSeed)"
|
|
4210
5077
|
]);
|
|
4211
|
-
var SORTED_TROVES_ABI =
|
|
5078
|
+
var SORTED_TROVES_ABI = parseAbi18([
|
|
4212
5079
|
"function findInsertPosition(uint256 _annualInterestRate, uint256 _prevId, uint256 _nextId) external view returns (uint256 prevId, uint256 nextId)"
|
|
4213
5080
|
]);
|
|
4214
5081
|
var FelixCdpAdapter = class {
|
|
@@ -4236,7 +5103,7 @@ var FelixCdpAdapter = class {
|
|
|
4236
5103
|
if (!this.hintHelpers || !this.sortedTroves || !this.rpcUrl) {
|
|
4237
5104
|
return [0n, 0n];
|
|
4238
5105
|
}
|
|
4239
|
-
const client =
|
|
5106
|
+
const client = createPublicClient13({ transport: http13(this.rpcUrl) });
|
|
4240
5107
|
const approxResult = await client.readContract({
|
|
4241
5108
|
address: this.hintHelpers,
|
|
4242
5109
|
abi: HINT_HELPERS_ABI,
|
|
@@ -4259,7 +5126,7 @@ var FelixCdpAdapter = class {
|
|
|
4259
5126
|
const interestRate = 50000000000000000n;
|
|
4260
5127
|
const [upperHint, lowerHint] = await this.getHints(interestRate);
|
|
4261
5128
|
const hasHints = upperHint !== 0n || lowerHint !== 0n;
|
|
4262
|
-
const data =
|
|
5129
|
+
const data = encodeFunctionData17({
|
|
4263
5130
|
abi: BORROWER_OPS_ABI,
|
|
4264
5131
|
functionName: "openTrove",
|
|
4265
5132
|
args: [
|
|
@@ -4288,7 +5155,7 @@ var FelixCdpAdapter = class {
|
|
|
4288
5155
|
async buildAdjust(params) {
|
|
4289
5156
|
const collChange = params.collateral_delta ?? 0n;
|
|
4290
5157
|
const debtChange = params.debt_delta ?? 0n;
|
|
4291
|
-
const data =
|
|
5158
|
+
const data = encodeFunctionData17({
|
|
4292
5159
|
abi: BORROWER_OPS_ABI,
|
|
4293
5160
|
functionName: "adjustTrove",
|
|
4294
5161
|
args: [
|
|
@@ -4311,7 +5178,7 @@ var FelixCdpAdapter = class {
|
|
|
4311
5178
|
};
|
|
4312
5179
|
}
|
|
4313
5180
|
async buildClose(params) {
|
|
4314
|
-
const data =
|
|
5181
|
+
const data = encodeFunctionData17({
|
|
4315
5182
|
abi: BORROWER_OPS_ABI,
|
|
4316
5183
|
functionName: "closeTrove",
|
|
4317
5184
|
args: [params.cdp_id]
|
|
@@ -4327,7 +5194,7 @@ var FelixCdpAdapter = class {
|
|
|
4327
5194
|
async getCdpInfo(cdpId) {
|
|
4328
5195
|
if (!this.rpcUrl) throw DefiError.rpcError(`[${this.protocolName}] getCdpInfo requires RPC \u2014 set HYPEREVM_RPC_URL`);
|
|
4329
5196
|
if (!this.troveManager) throw DefiError.contractError(`[${this.protocolName}] trove_manager contract not configured`);
|
|
4330
|
-
const client =
|
|
5197
|
+
const client = createPublicClient13({ transport: http13(this.rpcUrl) });
|
|
4331
5198
|
const data = await client.readContract({
|
|
4332
5199
|
address: this.troveManager,
|
|
4333
5200
|
abi: TROVE_MANAGER_ABI,
|
|
@@ -4360,7 +5227,7 @@ var FelixCdpAdapter = class {
|
|
|
4360
5227
|
};
|
|
4361
5228
|
}
|
|
4362
5229
|
};
|
|
4363
|
-
var PRICE_FEED_ABI =
|
|
5230
|
+
var PRICE_FEED_ABI = parseAbi19([
|
|
4364
5231
|
"function fetchPrice() external view returns (uint256 price, bool isNewOracleFailureDetected)",
|
|
4365
5232
|
"function lastGoodPrice() external view returns (uint256)"
|
|
4366
5233
|
]);
|
|
@@ -4386,7 +5253,7 @@ var FelixOracleAdapter = class {
|
|
|
4386
5253
|
if (asset !== this.asset && this.asset !== "0x0000000000000000000000000000000000000000") {
|
|
4387
5254
|
throw DefiError.unsupported(`[${this.protocolName}] Felix PriceFeed only supports asset ${this.asset}`);
|
|
4388
5255
|
}
|
|
4389
|
-
const client =
|
|
5256
|
+
const client = createPublicClient14({ transport: http14(this.rpcUrl) });
|
|
4390
5257
|
let priceVal;
|
|
4391
5258
|
try {
|
|
4392
5259
|
const result = await client.readContract({
|
|
@@ -4425,7 +5292,7 @@ var FelixOracleAdapter = class {
|
|
|
4425
5292
|
return results;
|
|
4426
5293
|
}
|
|
4427
5294
|
};
|
|
4428
|
-
var ERC4626_ABI =
|
|
5295
|
+
var ERC4626_ABI = parseAbi20([
|
|
4429
5296
|
"function asset() external view returns (address)",
|
|
4430
5297
|
"function totalAssets() external view returns (uint256)",
|
|
4431
5298
|
"function totalSupply() external view returns (uint256)",
|
|
@@ -4449,7 +5316,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4449
5316
|
return this.protocolName;
|
|
4450
5317
|
}
|
|
4451
5318
|
async buildDeposit(assets, receiver) {
|
|
4452
|
-
const data =
|
|
5319
|
+
const data = encodeFunctionData18({
|
|
4453
5320
|
abi: ERC4626_ABI,
|
|
4454
5321
|
functionName: "deposit",
|
|
4455
5322
|
args: [assets, receiver]
|
|
@@ -4463,7 +5330,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4463
5330
|
};
|
|
4464
5331
|
}
|
|
4465
5332
|
async buildWithdraw(assets, receiver, owner) {
|
|
4466
|
-
const data =
|
|
5333
|
+
const data = encodeFunctionData18({
|
|
4467
5334
|
abi: ERC4626_ABI,
|
|
4468
5335
|
functionName: "withdraw",
|
|
4469
5336
|
args: [assets, receiver, owner]
|
|
@@ -4478,7 +5345,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4478
5345
|
}
|
|
4479
5346
|
async totalAssets() {
|
|
4480
5347
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4481
|
-
const client =
|
|
5348
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4482
5349
|
return client.readContract({
|
|
4483
5350
|
address: this.vaultAddress,
|
|
4484
5351
|
abi: ERC4626_ABI,
|
|
@@ -4489,7 +5356,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4489
5356
|
}
|
|
4490
5357
|
async convertToShares(assets) {
|
|
4491
5358
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4492
|
-
const client =
|
|
5359
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4493
5360
|
return client.readContract({
|
|
4494
5361
|
address: this.vaultAddress,
|
|
4495
5362
|
abi: ERC4626_ABI,
|
|
@@ -4501,7 +5368,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4501
5368
|
}
|
|
4502
5369
|
async convertToAssets(shares) {
|
|
4503
5370
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4504
|
-
const client =
|
|
5371
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4505
5372
|
return client.readContract({
|
|
4506
5373
|
address: this.vaultAddress,
|
|
4507
5374
|
abi: ERC4626_ABI,
|
|
@@ -4513,7 +5380,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4513
5380
|
}
|
|
4514
5381
|
async getVaultInfo() {
|
|
4515
5382
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4516
|
-
const client =
|
|
5383
|
+
const client = createPublicClient15({ transport: http15(this.rpcUrl) });
|
|
4517
5384
|
const [totalAssets, totalSupply, asset] = await Promise.all([
|
|
4518
5385
|
client.readContract({ address: this.vaultAddress, abi: ERC4626_ABI, functionName: "totalAssets" }).catch((e) => {
|
|
4519
5386
|
throw DefiError.rpcError(`[${this.protocolName}] totalAssets failed: ${e}`);
|
|
@@ -4534,7 +5401,7 @@ var ERC4626VaultAdapter = class {
|
|
|
4534
5401
|
};
|
|
4535
5402
|
}
|
|
4536
5403
|
};
|
|
4537
|
-
var GENERIC_LST_ABI =
|
|
5404
|
+
var GENERIC_LST_ABI = parseAbi21([
|
|
4538
5405
|
"function stake() external payable returns (uint256)",
|
|
4539
5406
|
"function unstake(uint256 amount) external returns (uint256)"
|
|
4540
5407
|
]);
|
|
@@ -4551,7 +5418,7 @@ var GenericLstAdapter = class {
|
|
|
4551
5418
|
return this.protocolName;
|
|
4552
5419
|
}
|
|
4553
5420
|
async buildStake(params) {
|
|
4554
|
-
const data =
|
|
5421
|
+
const data = encodeFunctionData19({ abi: GENERIC_LST_ABI, functionName: "stake" });
|
|
4555
5422
|
return {
|
|
4556
5423
|
description: `[${this.protocolName}] Stake ${params.amount} HYPE`,
|
|
4557
5424
|
to: this.staking,
|
|
@@ -4561,7 +5428,7 @@ var GenericLstAdapter = class {
|
|
|
4561
5428
|
};
|
|
4562
5429
|
}
|
|
4563
5430
|
async buildUnstake(params) {
|
|
4564
|
-
const data =
|
|
5431
|
+
const data = encodeFunctionData19({
|
|
4565
5432
|
abi: GENERIC_LST_ABI,
|
|
4566
5433
|
functionName: "unstake",
|
|
4567
5434
|
args: [params.amount]
|
|
@@ -4578,11 +5445,11 @@ var GenericLstAdapter = class {
|
|
|
4578
5445
|
throw DefiError.unsupported(`[${this.protocolName}] getInfo requires RPC`);
|
|
4579
5446
|
}
|
|
4580
5447
|
};
|
|
4581
|
-
var STHYPE_ABI =
|
|
5448
|
+
var STHYPE_ABI = parseAbi222([
|
|
4582
5449
|
"function submit(address referral) external payable returns (uint256)",
|
|
4583
5450
|
"function requestWithdrawals(uint256[] amounts, address owner) external returns (uint256[] requestIds)"
|
|
4584
5451
|
]);
|
|
4585
|
-
var ERC20_ABI3 =
|
|
5452
|
+
var ERC20_ABI3 = parseAbi222([
|
|
4586
5453
|
"function totalSupply() external view returns (uint256)"
|
|
4587
5454
|
]);
|
|
4588
5455
|
var StHypeAdapter = class {
|
|
@@ -4602,7 +5469,7 @@ var StHypeAdapter = class {
|
|
|
4602
5469
|
return this.protocolName;
|
|
4603
5470
|
}
|
|
4604
5471
|
async buildStake(params) {
|
|
4605
|
-
const data =
|
|
5472
|
+
const data = encodeFunctionData20({
|
|
4606
5473
|
abi: STHYPE_ABI,
|
|
4607
5474
|
functionName: "submit",
|
|
4608
5475
|
args: [zeroAddress9]
|
|
@@ -4616,7 +5483,7 @@ var StHypeAdapter = class {
|
|
|
4616
5483
|
};
|
|
4617
5484
|
}
|
|
4618
5485
|
async buildUnstake(params) {
|
|
4619
|
-
const data =
|
|
5486
|
+
const data = encodeFunctionData20({
|
|
4620
5487
|
abi: STHYPE_ABI,
|
|
4621
5488
|
functionName: "requestWithdrawals",
|
|
4622
5489
|
args: [[params.amount], params.recipient]
|
|
@@ -4631,7 +5498,7 @@ var StHypeAdapter = class {
|
|
|
4631
5498
|
}
|
|
4632
5499
|
async getInfo() {
|
|
4633
5500
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4634
|
-
const client =
|
|
5501
|
+
const client = createPublicClient16({ transport: http16(this.rpcUrl) });
|
|
4635
5502
|
const tokenAddr = this.sthypeToken ?? this.staking;
|
|
4636
5503
|
const totalSupply = await client.readContract({
|
|
4637
5504
|
address: tokenAddr,
|
|
@@ -4649,12 +5516,12 @@ var StHypeAdapter = class {
|
|
|
4649
5516
|
};
|
|
4650
5517
|
}
|
|
4651
5518
|
};
|
|
4652
|
-
var KINETIQ_ABI =
|
|
5519
|
+
var KINETIQ_ABI = parseAbi23([
|
|
4653
5520
|
"function stake() external payable returns (uint256)",
|
|
4654
5521
|
"function requestUnstake(uint256 amount) external returns (uint256)",
|
|
4655
5522
|
"function totalStaked() external view returns (uint256)"
|
|
4656
5523
|
]);
|
|
4657
|
-
var ORACLE_ABI3 =
|
|
5524
|
+
var ORACLE_ABI3 = parseAbi23([
|
|
4658
5525
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
4659
5526
|
]);
|
|
4660
5527
|
var WHYPE = "0x5555555555555555555555555555555555555555";
|
|
@@ -4676,7 +5543,7 @@ var KinetiqAdapter = class {
|
|
|
4676
5543
|
return this.protocolName;
|
|
4677
5544
|
}
|
|
4678
5545
|
async buildStake(params) {
|
|
4679
|
-
const data =
|
|
5546
|
+
const data = encodeFunctionData21({ abi: KINETIQ_ABI, functionName: "stake" });
|
|
4680
5547
|
return {
|
|
4681
5548
|
description: `[${this.protocolName}] Stake ${params.amount} HYPE for kHYPE`,
|
|
4682
5549
|
to: this.staking,
|
|
@@ -4686,7 +5553,7 @@ var KinetiqAdapter = class {
|
|
|
4686
5553
|
};
|
|
4687
5554
|
}
|
|
4688
5555
|
async buildUnstake(params) {
|
|
4689
|
-
const data =
|
|
5556
|
+
const data = encodeFunctionData21({
|
|
4690
5557
|
abi: KINETIQ_ABI,
|
|
4691
5558
|
functionName: "requestUnstake",
|
|
4692
5559
|
args: [params.amount]
|
|
@@ -4701,7 +5568,7 @@ var KinetiqAdapter = class {
|
|
|
4701
5568
|
}
|
|
4702
5569
|
async getInfo() {
|
|
4703
5570
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4704
|
-
const client =
|
|
5571
|
+
const client = createPublicClient17({ transport: http17(this.rpcUrl) });
|
|
4705
5572
|
const totalStaked = await client.readContract({
|
|
4706
5573
|
address: this.staking,
|
|
4707
5574
|
abi: KINETIQ_ABI,
|
|
@@ -4723,15 +5590,15 @@ var KinetiqAdapter = class {
|
|
|
4723
5590
|
};
|
|
4724
5591
|
}
|
|
4725
5592
|
};
|
|
4726
|
-
var HLP_ABI =
|
|
5593
|
+
var HLP_ABI = parseAbi24([
|
|
4727
5594
|
"function deposit(uint256 amount) external returns (uint256)",
|
|
4728
5595
|
"function withdraw(uint256 shares) external returns (uint256)"
|
|
4729
5596
|
]);
|
|
4730
|
-
var RYSK_ABI =
|
|
5597
|
+
var RYSK_ABI = parseAbi25([
|
|
4731
5598
|
"function openOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 premium)",
|
|
4732
5599
|
"function closeOption(address underlying, uint256 strikePrice, uint256 expiry, bool isCall, uint256 amount) external returns (uint256 payout)"
|
|
4733
5600
|
]);
|
|
4734
|
-
var ERC721_ABI =
|
|
5601
|
+
var ERC721_ABI = parseAbi26([
|
|
4735
5602
|
"function name() returns (string)",
|
|
4736
5603
|
"function symbol() returns (string)",
|
|
4737
5604
|
"function totalSupply() returns (uint256)",
|
|
@@ -4751,7 +5618,7 @@ var ERC721Adapter = class {
|
|
|
4751
5618
|
}
|
|
4752
5619
|
async getCollectionInfo(collection) {
|
|
4753
5620
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4754
|
-
const client =
|
|
5621
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
4755
5622
|
const [collectionName, symbol, totalSupply] = await Promise.all([
|
|
4756
5623
|
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "name" }).catch((e) => {
|
|
4757
5624
|
throw DefiError.rpcError(`[${this.protocolName}] name failed: ${e}`);
|
|
@@ -4770,7 +5637,7 @@ var ERC721Adapter = class {
|
|
|
4770
5637
|
}
|
|
4771
5638
|
async getTokenInfo(collection, tokenId) {
|
|
4772
5639
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4773
|
-
const client =
|
|
5640
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
4774
5641
|
const [owner, tokenUri] = await Promise.all([
|
|
4775
5642
|
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "ownerOf", args: [tokenId] }).catch((e) => {
|
|
4776
5643
|
throw DefiError.rpcError(`[${this.protocolName}] ownerOf failed: ${e}`);
|
|
@@ -4786,7 +5653,7 @@ var ERC721Adapter = class {
|
|
|
4786
5653
|
}
|
|
4787
5654
|
async getBalance(owner, collection) {
|
|
4788
5655
|
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
4789
|
-
const client =
|
|
5656
|
+
const client = createPublicClient18({ transport: http18(this.rpcUrl) });
|
|
4790
5657
|
return client.readContract({ address: collection, abi: ERC721_ABI, functionName: "balanceOf", args: [owner] }).catch((e) => {
|
|
4791
5658
|
throw DefiError.rpcError(`[${this.protocolName}] balanceOf failed: ${e}`);
|
|
4792
5659
|
});
|
|
@@ -4907,6 +5774,9 @@ function createOracleFromCdp(entry, _asset, rpcUrl) {
|
|
|
4907
5774
|
throw DefiError.unsupported(`Oracle not available for CDP interface '${entry.interface}'`);
|
|
4908
5775
|
}
|
|
4909
5776
|
}
|
|
5777
|
+
function createMerchantMoeLB(entry, rpcUrl) {
|
|
5778
|
+
return new MerchantMoeLBAdapter(entry, rpcUrl);
|
|
5779
|
+
}
|
|
4910
5780
|
var DexSpotPrice = class {
|
|
4911
5781
|
/**
|
|
4912
5782
|
* Get the spot price for `token` denominated in `quoteToken` (e.g. USDC).
|
|
@@ -5914,20 +6784,20 @@ function registerYield(parent, getOpts, makeExecutor2) {
|
|
|
5914
6784
|
}
|
|
5915
6785
|
|
|
5916
6786
|
// src/commands/portfolio.ts
|
|
5917
|
-
import { encodeFunctionData as
|
|
6787
|
+
import { encodeFunctionData as encodeFunctionData25, parseAbi as parseAbi28 } from "viem";
|
|
5918
6788
|
|
|
5919
6789
|
// src/portfolio-tracker.ts
|
|
5920
6790
|
import { mkdirSync, writeFileSync, readdirSync as readdirSync2, readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
5921
6791
|
import { homedir } from "os";
|
|
5922
6792
|
import { resolve as resolve2 } from "path";
|
|
5923
|
-
import { encodeFunctionData as
|
|
5924
|
-
var ERC20_ABI4 =
|
|
6793
|
+
import { encodeFunctionData as encodeFunctionData24, parseAbi as parseAbi27 } from "viem";
|
|
6794
|
+
var ERC20_ABI4 = parseAbi27([
|
|
5925
6795
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
5926
6796
|
]);
|
|
5927
|
-
var ORACLE_ABI4 =
|
|
6797
|
+
var ORACLE_ABI4 = parseAbi27([
|
|
5928
6798
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
5929
6799
|
]);
|
|
5930
|
-
var POOL_ABI3 =
|
|
6800
|
+
var POOL_ABI3 = parseAbi27([
|
|
5931
6801
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
5932
6802
|
]);
|
|
5933
6803
|
function decodeU256Word(data, wordOffset = 0) {
|
|
@@ -5956,7 +6826,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
5956
6826
|
tokenEntries.push({ symbol: t.symbol, address: entry.address, decimals: entry.decimals });
|
|
5957
6827
|
calls.push([
|
|
5958
6828
|
entry.address,
|
|
5959
|
-
|
|
6829
|
+
encodeFunctionData24({ abi: ERC20_ABI4, functionName: "balanceOf", args: [user] })
|
|
5960
6830
|
]);
|
|
5961
6831
|
callLabels.push(`balance:${t.symbol}`);
|
|
5962
6832
|
}
|
|
@@ -5964,7 +6834,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
5964
6834
|
for (const p of lendingProtocols) {
|
|
5965
6835
|
calls.push([
|
|
5966
6836
|
p.contracts["pool"],
|
|
5967
|
-
|
|
6837
|
+
encodeFunctionData24({ abi: POOL_ABI3, functionName: "getUserAccountData", args: [user] })
|
|
5968
6838
|
]);
|
|
5969
6839
|
callLabels.push(`lending:${p.name}`);
|
|
5970
6840
|
}
|
|
@@ -5974,7 +6844,7 @@ async function takeSnapshot(chainName, wallet, registry) {
|
|
|
5974
6844
|
if (oracleAddr) {
|
|
5975
6845
|
calls.push([
|
|
5976
6846
|
oracleAddr,
|
|
5977
|
-
|
|
6847
|
+
encodeFunctionData24({ abi: ORACLE_ABI4, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
5978
6848
|
]);
|
|
5979
6849
|
callLabels.push("price:native");
|
|
5980
6850
|
}
|
|
@@ -6112,16 +6982,16 @@ function calculatePnL(current, previous) {
|
|
|
6112
6982
|
}
|
|
6113
6983
|
|
|
6114
6984
|
// src/commands/portfolio.ts
|
|
6115
|
-
var ERC20_ABI5 =
|
|
6985
|
+
var ERC20_ABI5 = parseAbi28([
|
|
6116
6986
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
6117
6987
|
]);
|
|
6118
|
-
var POOL_ABI4 =
|
|
6988
|
+
var POOL_ABI4 = parseAbi28([
|
|
6119
6989
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
6120
6990
|
]);
|
|
6121
|
-
var ORACLE_ABI5 =
|
|
6991
|
+
var ORACLE_ABI5 = parseAbi28([
|
|
6122
6992
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
6123
6993
|
]);
|
|
6124
|
-
function
|
|
6994
|
+
function decodeU2562(data, wordOffset = 0) {
|
|
6125
6995
|
if (!data || data.length < 2 + (wordOffset + 1) * 64) return 0n;
|
|
6126
6996
|
const hex = data.slice(2 + wordOffset * 64, 2 + wordOffset * 64 + 64);
|
|
6127
6997
|
return BigInt("0x" + hex);
|
|
@@ -6158,7 +7028,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6158
7028
|
if (entry.address === "0x0000000000000000000000000000000000000000") continue;
|
|
6159
7029
|
calls.push([
|
|
6160
7030
|
entry.address,
|
|
6161
|
-
|
|
7031
|
+
encodeFunctionData25({ abi: ERC20_ABI5, functionName: "balanceOf", args: [user] })
|
|
6162
7032
|
]);
|
|
6163
7033
|
callLabels.push(`balance:${symbol}`);
|
|
6164
7034
|
}
|
|
@@ -6166,7 +7036,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6166
7036
|
for (const p of lendingProtocols) {
|
|
6167
7037
|
calls.push([
|
|
6168
7038
|
p.contracts["pool"],
|
|
6169
|
-
|
|
7039
|
+
encodeFunctionData25({ abi: POOL_ABI4, functionName: "getUserAccountData", args: [user] })
|
|
6170
7040
|
]);
|
|
6171
7041
|
callLabels.push(`lending:${p.name}`);
|
|
6172
7042
|
}
|
|
@@ -6176,7 +7046,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6176
7046
|
if (oracleAddr) {
|
|
6177
7047
|
calls.push([
|
|
6178
7048
|
oracleAddr,
|
|
6179
|
-
|
|
7049
|
+
encodeFunctionData25({ abi: ORACLE_ABI5, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
6180
7050
|
]);
|
|
6181
7051
|
callLabels.push("price:native");
|
|
6182
7052
|
}
|
|
@@ -6201,7 +7071,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6201
7071
|
let nativePriceUsd = 0;
|
|
6202
7072
|
if (oracleAddr) {
|
|
6203
7073
|
const priceData = results[results.length - 1] ?? null;
|
|
6204
|
-
nativePriceUsd = Number(
|
|
7074
|
+
nativePriceUsd = Number(decodeU2562(priceData)) / 1e8;
|
|
6205
7075
|
}
|
|
6206
7076
|
let totalValueUsd = 0;
|
|
6207
7077
|
let idx = 0;
|
|
@@ -6215,7 +7085,7 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6215
7085
|
}
|
|
6216
7086
|
if (entry.address === "0x0000000000000000000000000000000000000000") continue;
|
|
6217
7087
|
if (idx >= results.length) break;
|
|
6218
|
-
const balance =
|
|
7088
|
+
const balance = decodeU2562(results[idx] ?? null);
|
|
6219
7089
|
if (balance > 0n) {
|
|
6220
7090
|
const decimals = entry.decimals;
|
|
6221
7091
|
const balF64 = Number(balance) / 10 ** decimals;
|
|
@@ -6235,9 +7105,9 @@ function registerPortfolio(parent, getOpts) {
|
|
|
6235
7105
|
if (idx >= results.length) break;
|
|
6236
7106
|
const data = results[idx] ?? null;
|
|
6237
7107
|
if (data && data.length >= 2 + 192 * 2) {
|
|
6238
|
-
const collateral = Number(
|
|
6239
|
-
const debt = Number(
|
|
6240
|
-
const hfRaw =
|
|
7108
|
+
const collateral = Number(decodeU2562(data, 0)) / 1e8;
|
|
7109
|
+
const debt = Number(decodeU2562(data, 1)) / 1e8;
|
|
7110
|
+
const hfRaw = decodeU2562(data, 5);
|
|
6241
7111
|
let hf = null;
|
|
6242
7112
|
if (hfRaw <= BigInt("0xffffffffffffffffffffffffffffffff")) {
|
|
6243
7113
|
const v = Number(hfRaw) / 1e18;
|
|
@@ -6538,14 +7408,14 @@ function registerAlert(parent, getOpts) {
|
|
|
6538
7408
|
}
|
|
6539
7409
|
|
|
6540
7410
|
// src/commands/scan.ts
|
|
6541
|
-
import { encodeFunctionData as
|
|
6542
|
-
var AAVE_ORACLE_ABI =
|
|
7411
|
+
import { encodeFunctionData as encodeFunctionData26, parseAbi as parseAbi29 } from "viem";
|
|
7412
|
+
var AAVE_ORACLE_ABI = parseAbi29([
|
|
6543
7413
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
6544
7414
|
]);
|
|
6545
|
-
var UNIV2_ROUTER_ABI =
|
|
7415
|
+
var UNIV2_ROUTER_ABI = parseAbi29([
|
|
6546
7416
|
"function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory)"
|
|
6547
7417
|
]);
|
|
6548
|
-
var VTOKEN_ABI =
|
|
7418
|
+
var VTOKEN_ABI = parseAbi29([
|
|
6549
7419
|
"function exchangeRateStored() external view returns (uint256)"
|
|
6550
7420
|
]);
|
|
6551
7421
|
var STABLECOINS = /* @__PURE__ */ new Set(["USDC", "USDT", "DAI", "USDT0"]);
|
|
@@ -6655,7 +7525,7 @@ function registerScan(parent, getOpts) {
|
|
|
6655
7525
|
callTypes.push({ kind: "oracle", oracle: oracle.name, token: token.symbol, oracleDecimals: oracle.decimals });
|
|
6656
7526
|
calls.push([
|
|
6657
7527
|
oracle.addr,
|
|
6658
|
-
|
|
7528
|
+
encodeFunctionData26({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })
|
|
6659
7529
|
]);
|
|
6660
7530
|
}
|
|
6661
7531
|
}
|
|
@@ -6666,7 +7536,7 @@ function registerScan(parent, getOpts) {
|
|
|
6666
7536
|
callTypes.push({ kind: "dex", token: token.symbol, outDecimals: quoteStable.decimals });
|
|
6667
7537
|
calls.push([
|
|
6668
7538
|
dexRouter,
|
|
6669
|
-
|
|
7539
|
+
encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [amountIn, path] })
|
|
6670
7540
|
]);
|
|
6671
7541
|
}
|
|
6672
7542
|
}
|
|
@@ -6675,7 +7545,7 @@ function registerScan(parent, getOpts) {
|
|
|
6675
7545
|
callTypes.push({ kind: "stable", from: "USDC", to: "USDT", outDecimals: usdt.decimals });
|
|
6676
7546
|
calls.push([
|
|
6677
7547
|
dexRouter,
|
|
6678
|
-
|
|
7548
|
+
encodeFunctionData26({
|
|
6679
7549
|
abi: UNIV2_ROUTER_ABI,
|
|
6680
7550
|
functionName: "getAmountsOut",
|
|
6681
7551
|
args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]]
|
|
@@ -6684,7 +7554,7 @@ function registerScan(parent, getOpts) {
|
|
|
6684
7554
|
callTypes.push({ kind: "stable", from: "USDT", to: "USDC", outDecimals: usdc.decimals });
|
|
6685
7555
|
calls.push([
|
|
6686
7556
|
dexRouter,
|
|
6687
|
-
|
|
7557
|
+
encodeFunctionData26({
|
|
6688
7558
|
abi: UNIV2_ROUTER_ABI,
|
|
6689
7559
|
functionName: "getAmountsOut",
|
|
6690
7560
|
args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]]
|
|
@@ -6695,7 +7565,7 @@ function registerScan(parent, getOpts) {
|
|
|
6695
7565
|
for (const fork of compoundForks) {
|
|
6696
7566
|
for (const { key, addr } of fork.vtokens) {
|
|
6697
7567
|
callTypes.push({ kind: "exchangeRate", protocol: fork.name, vtoken: key });
|
|
6698
|
-
calls.push([addr,
|
|
7568
|
+
calls.push([addr, encodeFunctionData26({ abi: VTOKEN_ABI, functionName: "exchangeRateStored", args: [] })]);
|
|
6699
7569
|
}
|
|
6700
7570
|
}
|
|
6701
7571
|
}
|
|
@@ -6913,22 +7783,22 @@ async function runAllChains(registry, patterns, oracleThreshold, stableThreshold
|
|
|
6913
7783
|
for (const oracle of oracles) {
|
|
6914
7784
|
for (const token of scanTokens) {
|
|
6915
7785
|
cts.push({ kind: "oracle", oracle: oracle.name, token: token.symbol, dec: oracle.decimals });
|
|
6916
|
-
calls.push([oracle.addr,
|
|
7786
|
+
calls.push([oracle.addr, encodeFunctionData26({ abi: AAVE_ORACLE_ABI, functionName: "getAssetPrice", args: [token.address] })]);
|
|
6917
7787
|
}
|
|
6918
7788
|
}
|
|
6919
7789
|
if (dexRouter) {
|
|
6920
7790
|
for (const token of scanTokens) {
|
|
6921
7791
|
const path = wrappedNative && token.address.toLowerCase() === wrappedNative.toLowerCase() ? [token.address, quoteStable.address] : wrappedNative ? [token.address, wrappedNative, quoteStable.address] : [token.address, quoteStable.address];
|
|
6922
7792
|
cts.push({ kind: "dex", token: token.symbol, dec: quoteStable.decimals });
|
|
6923
|
-
calls.push([dexRouter,
|
|
7793
|
+
calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(token.decimals), path] })]);
|
|
6924
7794
|
}
|
|
6925
7795
|
}
|
|
6926
7796
|
}
|
|
6927
7797
|
if (doStable && usdc && usdt && dexRouter) {
|
|
6928
7798
|
cts.push({ kind: "stable", from: "USDC", to: "USDT", dec: usdt.decimals });
|
|
6929
|
-
calls.push([dexRouter,
|
|
7799
|
+
calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdc.decimals), [usdc.address, usdt.address]] })]);
|
|
6930
7800
|
cts.push({ kind: "stable", from: "USDT", to: "USDC", dec: usdc.decimals });
|
|
6931
|
-
calls.push([dexRouter,
|
|
7801
|
+
calls.push([dexRouter, encodeFunctionData26({ abi: UNIV2_ROUTER_ABI, functionName: "getAmountsOut", args: [BigInt(10) ** BigInt(usdt.decimals), [usdt.address, usdc.address]] })]);
|
|
6932
7802
|
}
|
|
6933
7803
|
if (calls.length === 0) return null;
|
|
6934
7804
|
const ct0 = Date.now();
|
|
@@ -7056,14 +7926,14 @@ function registerArb(parent, getOpts, makeExecutor2) {
|
|
|
7056
7926
|
}
|
|
7057
7927
|
|
|
7058
7928
|
// src/commands/positions.ts
|
|
7059
|
-
import { encodeFunctionData as
|
|
7060
|
-
var ERC20_ABI6 =
|
|
7929
|
+
import { encodeFunctionData as encodeFunctionData27, parseAbi as parseAbi30 } from "viem";
|
|
7930
|
+
var ERC20_ABI6 = parseAbi30([
|
|
7061
7931
|
"function balanceOf(address owner) external view returns (uint256)"
|
|
7062
7932
|
]);
|
|
7063
|
-
var POOL_ABI5 =
|
|
7933
|
+
var POOL_ABI5 = parseAbi30([
|
|
7064
7934
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
7065
7935
|
]);
|
|
7066
|
-
var ORACLE_ABI6 =
|
|
7936
|
+
var ORACLE_ABI6 = parseAbi30([
|
|
7067
7937
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
7068
7938
|
]);
|
|
7069
7939
|
function round22(x) {
|
|
@@ -7079,7 +7949,7 @@ function estimateTokenValue(symbol, balance, nativePrice) {
|
|
|
7079
7949
|
if (["WETH", "ETH", "METH", "CBETH", "WSTETH"].includes(s)) return balance * 2350;
|
|
7080
7950
|
return balance * nativePrice;
|
|
7081
7951
|
}
|
|
7082
|
-
function
|
|
7952
|
+
function decodeU2563(data, offset = 0) {
|
|
7083
7953
|
if (!data || data.length < 2 + (offset + 32) * 2) return 0n;
|
|
7084
7954
|
const hex = data.slice(2 + offset * 64, 2 + offset * 64 + 64);
|
|
7085
7955
|
return BigInt("0x" + hex);
|
|
@@ -7092,7 +7962,7 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7092
7962
|
callTypes.push({ kind: "token", symbol: token.symbol, decimals: token.decimals });
|
|
7093
7963
|
calls.push([
|
|
7094
7964
|
token.address,
|
|
7095
|
-
|
|
7965
|
+
encodeFunctionData27({ abi: ERC20_ABI6, functionName: "balanceOf", args: [user] })
|
|
7096
7966
|
]);
|
|
7097
7967
|
}
|
|
7098
7968
|
}
|
|
@@ -7100,14 +7970,14 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7100
7970
|
callTypes.push({ kind: "lending", protocol: name, iface });
|
|
7101
7971
|
calls.push([
|
|
7102
7972
|
pool,
|
|
7103
|
-
|
|
7973
|
+
encodeFunctionData27({ abi: POOL_ABI5, functionName: "getUserAccountData", args: [user] })
|
|
7104
7974
|
]);
|
|
7105
7975
|
}
|
|
7106
7976
|
if (oracleAddr) {
|
|
7107
7977
|
callTypes.push({ kind: "native_price" });
|
|
7108
7978
|
calls.push([
|
|
7109
7979
|
oracleAddr,
|
|
7110
|
-
|
|
7980
|
+
encodeFunctionData27({ abi: ORACLE_ABI6, functionName: "getAssetPrice", args: [wrappedNative] })
|
|
7111
7981
|
]);
|
|
7112
7982
|
}
|
|
7113
7983
|
if (calls.length === 0) return null;
|
|
@@ -7117,7 +7987,7 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7117
7987
|
} catch {
|
|
7118
7988
|
return null;
|
|
7119
7989
|
}
|
|
7120
|
-
const nativePrice = oracleAddr ? Number(
|
|
7990
|
+
const nativePrice = oracleAddr ? Number(decodeU2563(results[results.length - 1])) / 1e8 : 0;
|
|
7121
7991
|
const tokenBalances = [];
|
|
7122
7992
|
const lendingPositions = [];
|
|
7123
7993
|
let chainValue = 0;
|
|
@@ -7127,7 +7997,7 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7127
7997
|
const ct = callTypes[i];
|
|
7128
7998
|
const data = results[i] ?? null;
|
|
7129
7999
|
if (ct.kind === "token") {
|
|
7130
|
-
const balance =
|
|
8000
|
+
const balance = decodeU2563(data);
|
|
7131
8001
|
if (balance > 0n) {
|
|
7132
8002
|
const balF64 = Number(balance) / 10 ** ct.decimals;
|
|
7133
8003
|
const valueUsd = estimateTokenValue(ct.symbol, balF64, nativePrice);
|
|
@@ -7144,9 +8014,9 @@ async function scanSingleChain(chainName, rpc, user, tokens, lendingPools, oracl
|
|
|
7144
8014
|
if (data && data.length >= 2 + 192 * 2) {
|
|
7145
8015
|
const priceDecimals = ct.iface === "aave_v2" ? 18 : 8;
|
|
7146
8016
|
const divisor = 10 ** priceDecimals;
|
|
7147
|
-
const collateral = Number(
|
|
7148
|
-
const debt = Number(
|
|
7149
|
-
const hfRaw =
|
|
8017
|
+
const collateral = Number(decodeU2563(data, 0)) / divisor;
|
|
8018
|
+
const debt = Number(decodeU2563(data, 1)) / divisor;
|
|
8019
|
+
const hfRaw = decodeU2563(data, 5);
|
|
7150
8020
|
let hf = null;
|
|
7151
8021
|
if (hfRaw <= BigInt("0xffffffffffffffffffffffffffffffff")) {
|
|
7152
8022
|
const v = Number(hfRaw) / 1e18;
|
|
@@ -7400,14 +8270,14 @@ function registerPrice(parent, getOpts) {
|
|
|
7400
8270
|
}
|
|
7401
8271
|
|
|
7402
8272
|
// src/commands/wallet.ts
|
|
7403
|
-
import { createPublicClient as
|
|
8273
|
+
import { createPublicClient as createPublicClient19, http as http19, formatEther } from "viem";
|
|
7404
8274
|
function registerWallet(parent, getOpts) {
|
|
7405
8275
|
const wallet = parent.command("wallet").description("Wallet management");
|
|
7406
8276
|
wallet.command("balance").description("Show native token balance").requiredOption("--address <address>", "Wallet address to query").action(async (opts) => {
|
|
7407
8277
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7408
8278
|
const registry = Registry.loadEmbedded();
|
|
7409
8279
|
const chain = registry.getChain(chainName);
|
|
7410
|
-
const client =
|
|
8280
|
+
const client = createPublicClient19({ transport: http19(chain.effectiveRpcUrl()) });
|
|
7411
8281
|
const balance = await client.getBalance({ address: opts.address });
|
|
7412
8282
|
printOutput({
|
|
7413
8283
|
chain: chain.name,
|
|
@@ -7424,14 +8294,14 @@ function registerWallet(parent, getOpts) {
|
|
|
7424
8294
|
}
|
|
7425
8295
|
|
|
7426
8296
|
// src/commands/token.ts
|
|
7427
|
-
import { createPublicClient as
|
|
8297
|
+
import { createPublicClient as createPublicClient20, http as http20, maxUint256 } from "viem";
|
|
7428
8298
|
function registerToken(parent, getOpts, makeExecutor2) {
|
|
7429
8299
|
const token = parent.command("token").description("Token operations: approve, allowance, transfer, balance");
|
|
7430
8300
|
token.command("balance").description("Query token balance for an address").requiredOption("--token <token>", "Token symbol or address").requiredOption("--owner <address>", "Wallet address to query").action(async (opts) => {
|
|
7431
8301
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7432
8302
|
const registry = Registry.loadEmbedded();
|
|
7433
8303
|
const chain = registry.getChain(chainName);
|
|
7434
|
-
const client =
|
|
8304
|
+
const client = createPublicClient20({ transport: http20(chain.effectiveRpcUrl()) });
|
|
7435
8305
|
const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
|
|
7436
8306
|
const [balance, symbol, decimals] = await Promise.all([
|
|
7437
8307
|
client.readContract({ address: tokenAddr, abi: erc20Abi, functionName: "balanceOf", args: [opts.owner] }),
|
|
@@ -7460,7 +8330,7 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
7460
8330
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7461
8331
|
const registry = Registry.loadEmbedded();
|
|
7462
8332
|
const chain = registry.getChain(chainName);
|
|
7463
|
-
const client =
|
|
8333
|
+
const client = createPublicClient20({ transport: http20(chain.effectiveRpcUrl()) });
|
|
7464
8334
|
const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
|
|
7465
8335
|
const allowance = await client.readContract({
|
|
7466
8336
|
address: tokenAddr,
|
|
@@ -7482,8 +8352,8 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
7482
8352
|
}
|
|
7483
8353
|
|
|
7484
8354
|
// src/commands/whales.ts
|
|
7485
|
-
import { encodeFunctionData as
|
|
7486
|
-
var POOL_ABI6 =
|
|
8355
|
+
import { encodeFunctionData as encodeFunctionData28, parseAbi as parseAbi31 } from "viem";
|
|
8356
|
+
var POOL_ABI6 = parseAbi31([
|
|
7487
8357
|
"function getUserAccountData(address user) external view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor)"
|
|
7488
8358
|
]);
|
|
7489
8359
|
function round24(x) {
|
|
@@ -7492,7 +8362,7 @@ function round24(x) {
|
|
|
7492
8362
|
function round43(x) {
|
|
7493
8363
|
return Math.round(x * 1e4) / 1e4;
|
|
7494
8364
|
}
|
|
7495
|
-
function
|
|
8365
|
+
function decodeU2564(data, wordOffset = 0) {
|
|
7496
8366
|
if (!data || data.length < 2 + (wordOffset + 1) * 64) return 0n;
|
|
7497
8367
|
const hex = data.slice(2 + wordOffset * 64, 2 + wordOffset * 64 + 64);
|
|
7498
8368
|
return BigInt("0x" + hex);
|
|
@@ -7594,7 +8464,7 @@ function registerWhales(parent, getOpts) {
|
|
|
7594
8464
|
for (const { pool } of lendingPools) {
|
|
7595
8465
|
calls.push([
|
|
7596
8466
|
pool,
|
|
7597
|
-
|
|
8467
|
+
encodeFunctionData28({ abi: POOL_ABI6, functionName: "getUserAccountData", args: [whale.address] })
|
|
7598
8468
|
]);
|
|
7599
8469
|
}
|
|
7600
8470
|
}
|
|
@@ -7617,9 +8487,9 @@ function registerWhales(parent, getOpts) {
|
|
|
7617
8487
|
if (data && data.length >= 2 + 192 * 2) {
|
|
7618
8488
|
const dec = iface === "aave_v2" ? 18 : 8;
|
|
7619
8489
|
const divisor = 10 ** dec;
|
|
7620
|
-
const collateral = Number(
|
|
7621
|
-
const debt = Number(
|
|
7622
|
-
const hfRaw =
|
|
8490
|
+
const collateral = Number(decodeU2564(data, 0)) / divisor;
|
|
8491
|
+
const debt = Number(decodeU2564(data, 1)) / divisor;
|
|
8492
|
+
const hfRaw = decodeU2564(data, 5);
|
|
7623
8493
|
let hf = null;
|
|
7624
8494
|
if (hfRaw <= BigInt("0xffffffffffffffffffffffffffffffff")) {
|
|
7625
8495
|
const v = Number(hfRaw) / 1e18;
|
|
@@ -8022,11 +8892,11 @@ function registerBridge(parent, getOpts) {
|
|
|
8022
8892
|
const amountUsdc = Number(BigInt(opts.amount)) / 1e6;
|
|
8023
8893
|
const { fee, maxFeeSubunits } = await getCctpFeeEstimate(srcDomain, dstDomain, amountUsdc);
|
|
8024
8894
|
const recipientPadded = `0x${"0".repeat(24)}${recipient.replace("0x", "").toLowerCase()}`;
|
|
8025
|
-
const { encodeFunctionData:
|
|
8026
|
-
const tokenMessengerAbi =
|
|
8895
|
+
const { encodeFunctionData: encodeFunctionData29, parseAbi: parseAbi33 } = await import("viem");
|
|
8896
|
+
const tokenMessengerAbi = parseAbi33([
|
|
8027
8897
|
"function depositForBurn(uint256 amount, uint32 destinationDomain, bytes32 mintRecipient, address burnToken, bytes32 destinationCaller, uint256 maxFee, uint32 minFinalityThreshold) external returns (uint64 nonce)"
|
|
8028
8898
|
]);
|
|
8029
|
-
const data =
|
|
8899
|
+
const data = encodeFunctionData29({
|
|
8030
8900
|
abi: tokenMessengerAbi,
|
|
8031
8901
|
functionName: "depositForBurn",
|
|
8032
8902
|
args: [
|
|
@@ -8363,6 +9233,107 @@ function registerSetup(program2) {
|
|
|
8363
9233
|
});
|
|
8364
9234
|
}
|
|
8365
9235
|
|
|
9236
|
+
// src/commands/lb.ts
|
|
9237
|
+
function registerLB(parent, getOpts, makeExecutor2) {
|
|
9238
|
+
const lb = parent.command("lb").description("Merchant Moe Liquidity Book: add/remove liquidity, rewards, positions");
|
|
9239
|
+
lb.command("add").description("Add liquidity to a Liquidity Book pair").requiredOption("--protocol <protocol>", "Protocol slug (e.g. merchantmoe-mantle)").requiredOption("--pool <address>", "LB pair address").requiredOption("--token-x <address>", "Token X address").requiredOption("--token-y <address>", "Token Y address").requiredOption("--bin-step <step>", "Bin step of the pair").option("--amount-x <wei>", "Amount of token X in wei", "0").option("--amount-y <wei>", "Amount of token Y in wei", "0").option("--bins <N>", "Number of bins on each side of active bin", "5").option("--active-id <id>", "Active bin id (defaults to on-chain query)").option("--recipient <address>", "Recipient address").action(async (opts) => {
|
|
9240
|
+
const executor = makeExecutor2();
|
|
9241
|
+
const registry = Registry.loadEmbedded();
|
|
9242
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9243
|
+
const chainName = parent.opts().chain;
|
|
9244
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9245
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9246
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9247
|
+
const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
|
|
9248
|
+
const tx = await adapter.buildAddLiquidity({
|
|
9249
|
+
pool: opts.pool,
|
|
9250
|
+
tokenX: opts.tokenX,
|
|
9251
|
+
tokenY: opts.tokenY,
|
|
9252
|
+
binStep: parseInt(opts.binStep),
|
|
9253
|
+
amountX: BigInt(opts.amountX),
|
|
9254
|
+
amountY: BigInt(opts.amountY),
|
|
9255
|
+
numBins: parseInt(opts.bins),
|
|
9256
|
+
activeIdDesired: opts.activeId ? parseInt(opts.activeId) : void 0,
|
|
9257
|
+
recipient
|
|
9258
|
+
});
|
|
9259
|
+
const result = await executor.execute(tx);
|
|
9260
|
+
printOutput(result, getOpts());
|
|
9261
|
+
});
|
|
9262
|
+
lb.command("remove").description("Remove liquidity from Liquidity Book bins").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--token-x <address>", "Token X address").requiredOption("--token-y <address>", "Token Y address").requiredOption("--bin-step <step>", "Bin step of the pair").requiredOption("--bins <binIds>", "Comma-separated bin IDs to remove from").requiredOption("--amounts <amounts>", "Comma-separated LB token amounts to remove per bin (wei)").option("--recipient <address>", "Recipient address").action(async (opts) => {
|
|
9263
|
+
const executor = makeExecutor2();
|
|
9264
|
+
const registry = Registry.loadEmbedded();
|
|
9265
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9266
|
+
const adapter = createMerchantMoeLB(protocol);
|
|
9267
|
+
const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
|
|
9268
|
+
const binIds = opts.bins.split(",").map((s) => parseInt(s.trim()));
|
|
9269
|
+
const amounts = opts.amounts.split(",").map((s) => BigInt(s.trim()));
|
|
9270
|
+
const tx = await adapter.buildRemoveLiquidity({
|
|
9271
|
+
tokenX: opts.tokenX,
|
|
9272
|
+
tokenY: opts.tokenY,
|
|
9273
|
+
binStep: parseInt(opts.binStep),
|
|
9274
|
+
binIds,
|
|
9275
|
+
amounts,
|
|
9276
|
+
recipient
|
|
9277
|
+
});
|
|
9278
|
+
const result = await executor.execute(tx);
|
|
9279
|
+
printOutput(result, getOpts());
|
|
9280
|
+
});
|
|
9281
|
+
lb.command("rewards").description("Show pending MOE rewards for a pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "LB pair address").option("--bins <binIds>", "Comma-separated bin IDs to check (auto-detected from rewarder range if omitted)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
|
|
9282
|
+
const registry = Registry.loadEmbedded();
|
|
9283
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9284
|
+
const chainName = parent.opts().chain;
|
|
9285
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9286
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9287
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9288
|
+
const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
|
|
9289
|
+
if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
|
|
9290
|
+
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
9291
|
+
const rewards = await adapter.getPendingRewards(user, opts.pool, binIds);
|
|
9292
|
+
printOutput(rewards, getOpts());
|
|
9293
|
+
});
|
|
9294
|
+
lb.command("claim").description("Claim pending MOE rewards from a pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "LB pair address").option("--bins <binIds>", "Comma-separated bin IDs to claim from (auto-detected from rewarder range if omitted)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
|
|
9295
|
+
const executor = makeExecutor2();
|
|
9296
|
+
const registry = Registry.loadEmbedded();
|
|
9297
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9298
|
+
const chainName = parent.opts().chain;
|
|
9299
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9300
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9301
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9302
|
+
const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
|
|
9303
|
+
if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
|
|
9304
|
+
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
9305
|
+
const tx = await adapter.buildClaimRewards(user, opts.pool, binIds);
|
|
9306
|
+
const result = await executor.execute(tx);
|
|
9307
|
+
printOutput(result, getOpts());
|
|
9308
|
+
});
|
|
9309
|
+
lb.command("discover").description("Find all rewarded LB pools on chain").requiredOption("--protocol <protocol>", "Protocol slug").option("--active-only", "Only show non-stopped pools").action(async (opts) => {
|
|
9310
|
+
const registry = Registry.loadEmbedded();
|
|
9311
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9312
|
+
const chainName = parent.opts().chain;
|
|
9313
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9314
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9315
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9316
|
+
let pools = await adapter.discoverRewardedPools();
|
|
9317
|
+
if (opts.activeOnly) {
|
|
9318
|
+
pools = pools.filter((p) => !p.stopped);
|
|
9319
|
+
}
|
|
9320
|
+
printOutput(pools, getOpts());
|
|
9321
|
+
});
|
|
9322
|
+
lb.command("positions").description("Show user positions per bin in a LB pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "LB pair address").option("--bins <binIds>", "Comma-separated bin IDs to query (auto-detected from rewarder range or active \xB1 50 if omitted)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
|
|
9323
|
+
const registry = Registry.loadEmbedded();
|
|
9324
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
9325
|
+
const chainName = parent.opts().chain;
|
|
9326
|
+
const chain = registry.getChain(chainName ?? "mantle");
|
|
9327
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
9328
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9329
|
+
const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
|
|
9330
|
+
if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
|
|
9331
|
+
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
9332
|
+
const positions = await adapter.getUserPositions(user, opts.pool, binIds);
|
|
9333
|
+
printOutput(positions, getOpts());
|
|
9334
|
+
});
|
|
9335
|
+
}
|
|
9336
|
+
|
|
8366
9337
|
// src/cli.ts
|
|
8367
9338
|
var _require = createRequire(import.meta.url);
|
|
8368
9339
|
var _pkg = _require("../package.json");
|
|
@@ -8374,7 +9345,7 @@ var BANNER = `
|
|
|
8374
9345
|
\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551
|
|
8375
9346
|
\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D
|
|
8376
9347
|
|
|
8377
|
-
2 chains \xB7
|
|
9348
|
+
2 chains \xB7 30 protocols \xB7 by HypurrQuant
|
|
8378
9349
|
|
|
8379
9350
|
Scan exploits, swap tokens, bridge assets, track whales,
|
|
8380
9351
|
compare yields \u2014 all from your terminal.
|
|
@@ -8414,6 +9385,7 @@ registerSwap(program, getOutputMode, makeExecutor);
|
|
|
8414
9385
|
registerBridge(program, getOutputMode);
|
|
8415
9386
|
registerNft(program, getOutputMode);
|
|
8416
9387
|
registerFarm(program, getOutputMode, makeExecutor);
|
|
9388
|
+
registerLB(program, getOutputMode, makeExecutor);
|
|
8417
9389
|
registerSetup(program);
|
|
8418
9390
|
program.command("agent").description("Agent mode: read JSON commands from stdin (for AI agents)").action(async () => {
|
|
8419
9391
|
const executor = makeExecutor();
|