@hypurrquant/defi-cli 0.4.0 → 0.4.1
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/README.md +38 -39
- package/dist/index.js +346 -101
- package/dist/index.js.map +1 -1
- package/dist/main.js +346 -101
- package/dist/main.js.map +1 -1
- package/dist/mcp-server.js +104 -21
- package/dist/mcp-server.js.map +1 -1
- package/package.json +2 -1
- package/skills/defi-cli/SKILL.md +181 -0
- package/skills/defi-cli/package.json +38 -0
- package/skills/defi-cli/references/commands.md +162 -0
- package/skills/defi-cli/references/protocols.md +115 -0
- package/skills/defi-cli/scripts/exploit-scan.sh +10 -0
- package/skills/defi-cli/scripts/portfolio-snapshot.sh +19 -0
- package/skills/defi-cli/scripts/preflight.sh +14 -0
- package/skills/defi-cli/scripts/yield-scan.sh +10 -0
package/dist/main.js
CHANGED
|
@@ -1012,8 +1012,25 @@ function isPlaceholder(addr) {
|
|
|
1012
1012
|
function registerStatus(parent, getOpts) {
|
|
1013
1013
|
parent.command("status").description("Show chain and protocol status").option("--verify", "Verify contract addresses on-chain").action(async (opts) => {
|
|
1014
1014
|
const globalOpts = parent.opts();
|
|
1015
|
-
const chainName = globalOpts.chain ?? "hyperevm";
|
|
1016
1015
|
const registry = Registry.loadEmbedded();
|
|
1016
|
+
const chainKeys = globalOpts.chain ? [globalOpts.chain] : Array.from(registry.chains.keys());
|
|
1017
|
+
if (chainKeys.length > 1) {
|
|
1018
|
+
const summary = [];
|
|
1019
|
+
for (const ck of chainKeys) {
|
|
1020
|
+
const cc = registry.getChain(ck);
|
|
1021
|
+
const protos = registry.getProtocolsForChain(ck);
|
|
1022
|
+
summary.push({
|
|
1023
|
+
chain: cc.name,
|
|
1024
|
+
chain_id: cc.chain_id,
|
|
1025
|
+
rpc_url: cc.effectiveRpcUrl(),
|
|
1026
|
+
protocols: protos.map((p) => ({ slug: p.slug, name: p.name, category: p.category, interface: p.interface })),
|
|
1027
|
+
summary: { total_protocols: protos.length }
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1030
|
+
printOutput(summary, getOpts());
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
const chainName = chainKeys[0];
|
|
1017
1034
|
const chainConfig = registry.getChain(chainName);
|
|
1018
1035
|
const chainProtocols = registry.getProtocolsForChain(chainName);
|
|
1019
1036
|
let blockNumber;
|
|
@@ -1117,27 +1134,34 @@ function registerStatus(parent, getOpts) {
|
|
|
1117
1134
|
function handleSchema(params) {
|
|
1118
1135
|
const action = typeof params["action"] === "string" ? params["action"] : "all";
|
|
1119
1136
|
switch (action) {
|
|
1120
|
-
case "
|
|
1137
|
+
case "status":
|
|
1138
|
+
return { action: "status", params: {}, cli: "defi status" };
|
|
1139
|
+
case "list_protocols":
|
|
1121
1140
|
return {
|
|
1122
|
-
action: "
|
|
1141
|
+
action: "list_protocols",
|
|
1123
1142
|
params: {
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
amount: { type: "string", required: true, description: "Amount (human-readable, e.g. '1.5')" },
|
|
1128
|
-
slippage_bps: { type: "number", required: false, default: 50, description: "Slippage in basis points" },
|
|
1129
|
-
recipient: { type: "string", required: false, description: "Recipient address" }
|
|
1130
|
-
}
|
|
1143
|
+
category: { type: "string", required: false, description: "Filter by category (e.g. dex, lending)" }
|
|
1144
|
+
},
|
|
1145
|
+
cli: "defi status"
|
|
1131
1146
|
};
|
|
1132
|
-
case "
|
|
1147
|
+
case "yield":
|
|
1133
1148
|
return {
|
|
1134
|
-
action: "
|
|
1149
|
+
action: "yield",
|
|
1135
1150
|
params: {
|
|
1151
|
+
chain: { type: "string", required: false, description: "Target chain (omit for all chains)" },
|
|
1152
|
+
asset: { type: "string", required: false, default: "USDC", description: "Token symbol" }
|
|
1153
|
+
},
|
|
1154
|
+
cli: "defi yield --asset USDC"
|
|
1155
|
+
};
|
|
1156
|
+
case "lending.rates":
|
|
1157
|
+
return {
|
|
1158
|
+
action: "lending.rates",
|
|
1159
|
+
params: {
|
|
1160
|
+
chain: { type: "string", required: true, description: "Target chain" },
|
|
1136
1161
|
protocol: { type: "string", required: true, description: "Protocol slug" },
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
}
|
|
1162
|
+
asset: { type: "string", required: true, description: "Token symbol or address" }
|
|
1163
|
+
},
|
|
1164
|
+
cli: "defi --chain hyperevm lending rates --protocol hypurrfi --asset USDC"
|
|
1141
1165
|
};
|
|
1142
1166
|
case "lending.supply":
|
|
1143
1167
|
case "lending.borrow":
|
|
@@ -1146,47 +1170,54 @@ function handleSchema(params) {
|
|
|
1146
1170
|
return {
|
|
1147
1171
|
action,
|
|
1148
1172
|
params: {
|
|
1173
|
+
chain: { type: "string", required: true, description: "Target chain" },
|
|
1149
1174
|
protocol: { type: "string", required: true, description: "Protocol slug" },
|
|
1150
1175
|
asset: { type: "string", required: true, description: "Token symbol or address" },
|
|
1151
|
-
amount: { type: "string", required: true, description: "Amount
|
|
1152
|
-
}
|
|
1176
|
+
amount: { type: "string", required: true, description: "Amount in wei" }
|
|
1177
|
+
},
|
|
1178
|
+
cli: `defi --chain hyperevm lending ${action.split(".")[1]} --protocol hypurrfi --asset USDC --amount 1000000`
|
|
1153
1179
|
};
|
|
1154
|
-
case "
|
|
1155
|
-
case "staking.unstake":
|
|
1180
|
+
case "lp.discover":
|
|
1156
1181
|
return {
|
|
1157
|
-
action,
|
|
1182
|
+
action: "lp.discover",
|
|
1158
1183
|
params: {
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
}
|
|
1184
|
+
chain: { type: "string", required: true, description: "Target chain" },
|
|
1185
|
+
protocol: { type: "string", required: false, description: "Filter by protocol slug" }
|
|
1186
|
+
},
|
|
1187
|
+
cli: "defi --chain hyperevm lp discover"
|
|
1162
1188
|
};
|
|
1163
|
-
case "
|
|
1164
|
-
case "vault.withdraw":
|
|
1189
|
+
case "swap":
|
|
1165
1190
|
return {
|
|
1166
|
-
action,
|
|
1191
|
+
action: "swap",
|
|
1167
1192
|
params: {
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1193
|
+
chain: { type: "string", required: true, description: "Target chain" },
|
|
1194
|
+
from: { type: "string", required: true, description: "Input token symbol or address" },
|
|
1195
|
+
to: { type: "string", required: true, description: "Output token symbol or address" },
|
|
1196
|
+
amount: { type: "string", required: true, description: "Amount in wei" },
|
|
1197
|
+
provider: { type: "string", required: false, default: "kyber", description: "Aggregator: kyber, openocean, liquid" },
|
|
1198
|
+
slippage: { type: "string", required: false, default: "50", description: "Slippage in bps" }
|
|
1199
|
+
},
|
|
1200
|
+
cli: "defi --chain hyperevm swap --from USDC --to WHYPE --amount 1000000"
|
|
1171
1201
|
};
|
|
1172
|
-
case "
|
|
1202
|
+
case "price":
|
|
1173
1203
|
return {
|
|
1174
|
-
action: "
|
|
1204
|
+
action: "price",
|
|
1175
1205
|
params: {
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
}
|
|
1206
|
+
chain: { type: "string", required: true, description: "Target chain" },
|
|
1207
|
+
asset: { type: "string", required: true, description: "Token symbol or address" }
|
|
1208
|
+
},
|
|
1209
|
+
cli: "defi --chain hyperevm price --asset WHYPE"
|
|
1181
1210
|
};
|
|
1182
|
-
case "
|
|
1183
|
-
return { action: "status", params: {} };
|
|
1184
|
-
case "list_protocols":
|
|
1211
|
+
case "bridge":
|
|
1185
1212
|
return {
|
|
1186
|
-
action: "
|
|
1213
|
+
action: "bridge",
|
|
1187
1214
|
params: {
|
|
1188
|
-
|
|
1189
|
-
|
|
1215
|
+
chain: { type: "string", required: true, description: "Source chain" },
|
|
1216
|
+
token: { type: "string", required: true, description: "Token symbol or address" },
|
|
1217
|
+
amount: { type: "string", required: true, description: "Amount in wei" },
|
|
1218
|
+
to_chain: { type: "string", required: true, description: "Destination chain" }
|
|
1219
|
+
},
|
|
1220
|
+
cli: "defi --chain hyperevm bridge --token USDC --amount 1000000 --to-chain mantle"
|
|
1190
1221
|
};
|
|
1191
1222
|
default:
|
|
1192
1223
|
return {
|
|
@@ -1194,17 +1225,25 @@ function handleSchema(params) {
|
|
|
1194
1225
|
"status",
|
|
1195
1226
|
"list_protocols",
|
|
1196
1227
|
"schema",
|
|
1197
|
-
"
|
|
1198
|
-
"
|
|
1228
|
+
"yield",
|
|
1229
|
+
"lending.rates",
|
|
1199
1230
|
"lending.supply",
|
|
1200
1231
|
"lending.borrow",
|
|
1201
1232
|
"lending.repay",
|
|
1202
1233
|
"lending.withdraw",
|
|
1203
|
-
"
|
|
1204
|
-
"
|
|
1205
|
-
"
|
|
1206
|
-
"
|
|
1207
|
-
"
|
|
1234
|
+
"lp.discover",
|
|
1235
|
+
"lp.add",
|
|
1236
|
+
"lp.farm",
|
|
1237
|
+
"lp.claim",
|
|
1238
|
+
"lp.remove",
|
|
1239
|
+
"swap",
|
|
1240
|
+
"price",
|
|
1241
|
+
"token.balance",
|
|
1242
|
+
"token.approve",
|
|
1243
|
+
"token.transfer",
|
|
1244
|
+
"wallet.balance",
|
|
1245
|
+
"portfolio.show",
|
|
1246
|
+
"bridge"
|
|
1208
1247
|
]
|
|
1209
1248
|
};
|
|
1210
1249
|
}
|
|
@@ -3459,7 +3498,8 @@ var lbQuoterAbi2 = parseAbi12([
|
|
|
3459
3498
|
"function findBestPathFromAmountIn(address[] calldata route, uint128 amountIn) external view returns ((address[] route, address[] pairs, uint256[] binSteps, uint256[] versions, uint128[] amounts, uint128[] virtualAmountsWithoutSlippage, uint128[] fees))"
|
|
3460
3499
|
]);
|
|
3461
3500
|
var erc20Abi2 = parseAbi12([
|
|
3462
|
-
"function symbol() external view returns (string)"
|
|
3501
|
+
"function symbol() external view returns (string)",
|
|
3502
|
+
"function balanceOf(address account) external view returns (uint256)"
|
|
3463
3503
|
]);
|
|
3464
3504
|
var _addressAbi = parseAbi12(["function f() external view returns (address)"]);
|
|
3465
3505
|
function decodeAddressResult(data) {
|
|
@@ -3967,6 +4007,74 @@ var MerchantMoeLBAdapter = class {
|
|
|
3967
4007
|
} catch {
|
|
3968
4008
|
}
|
|
3969
4009
|
}
|
|
4010
|
+
const stableSymbols = /* @__PURE__ */ new Set(["USDT", "USDC", "USDT0", "MUSD", "AUSD", "USDY", "FDUSD", "USDe", "sUSDe"]);
|
|
4011
|
+
const mntSymbols = /* @__PURE__ */ new Set(["WMNT", "MNT"]);
|
|
4012
|
+
const moeSymbols = /* @__PURE__ */ new Set(["MOE"]);
|
|
4013
|
+
const sixDecimalStables = /* @__PURE__ */ new Set(["USDT", "USDC", "USDT0", "FDUSD"]);
|
|
4014
|
+
const tokenPriceMap = /* @__PURE__ */ new Map();
|
|
4015
|
+
const tokenDecimalsMap = /* @__PURE__ */ new Map();
|
|
4016
|
+
for (const [addr, sym] of symbolMap) {
|
|
4017
|
+
const key = addr.toLowerCase();
|
|
4018
|
+
if (stableSymbols.has(sym)) {
|
|
4019
|
+
tokenPriceMap.set(key, 1);
|
|
4020
|
+
tokenDecimalsMap.set(key, sixDecimalStables.has(sym) ? 6 : 18);
|
|
4021
|
+
} else if (mntSymbols.has(sym)) {
|
|
4022
|
+
tokenPriceMap.set(key, wmntPriceUsd);
|
|
4023
|
+
tokenDecimalsMap.set(key, 18);
|
|
4024
|
+
} else if (moeSymbols.has(sym)) {
|
|
4025
|
+
tokenPriceMap.set(key, moePriceUsd);
|
|
4026
|
+
tokenDecimalsMap.set(key, 18);
|
|
4027
|
+
}
|
|
4028
|
+
}
|
|
4029
|
+
const unknownTokenAddrs = [];
|
|
4030
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
4031
|
+
for (const addr of [tokenXAddresses[i], tokenYAddresses[i]]) {
|
|
4032
|
+
if (addr && !tokenPriceMap.has(addr.toLowerCase())) {
|
|
4033
|
+
if (!unknownTokenAddrs.some((a) => a.toLowerCase() === addr.toLowerCase())) {
|
|
4034
|
+
unknownTokenAddrs.push(addr);
|
|
4035
|
+
}
|
|
4036
|
+
}
|
|
4037
|
+
}
|
|
4038
|
+
}
|
|
4039
|
+
if (unknownTokenAddrs.length > 0 && this.lbQuoter && this.wmnt && wmntPriceUsd > 0) {
|
|
4040
|
+
const erc20DecimalsAbi = parseAbi12(["function decimals() external view returns (uint8)"]);
|
|
4041
|
+
const decCalls = unknownTokenAddrs.map((addr) => [
|
|
4042
|
+
addr,
|
|
4043
|
+
encodeFunctionData12({ abi: erc20DecimalsAbi, functionName: "decimals" })
|
|
4044
|
+
]);
|
|
4045
|
+
const decResults = await multicallRead(rpcUrl, decCalls).catch(() => []);
|
|
4046
|
+
for (let i = 0; i < unknownTokenAddrs.length; i++) {
|
|
4047
|
+
const dec = decResults[i] ? Number(decodeUint256Result(decResults[i]) ?? 18n) : 18;
|
|
4048
|
+
tokenDecimalsMap.set(unknownTokenAddrs[i].toLowerCase(), dec);
|
|
4049
|
+
}
|
|
4050
|
+
const quotePromises = unknownTokenAddrs.map(async (tokenAddr) => {
|
|
4051
|
+
try {
|
|
4052
|
+
const dec = tokenDecimalsMap.get(tokenAddr.toLowerCase()) ?? 18;
|
|
4053
|
+
const quoteUnit = 10n ** BigInt(Math.max(dec - 2, 0));
|
|
4054
|
+
const quote = await client.readContract({
|
|
4055
|
+
address: this.lbQuoter,
|
|
4056
|
+
abi: lbQuoterAbi2,
|
|
4057
|
+
functionName: "findBestPathFromAmountIn",
|
|
4058
|
+
args: [[tokenAddr, this.wmnt], quoteUnit]
|
|
4059
|
+
});
|
|
4060
|
+
const amountOut = quote.amounts?.at(-1) ?? 0n;
|
|
4061
|
+
const priceInWmnt = Number(amountOut) / 1e18 * (10 ** dec / Number(quoteUnit));
|
|
4062
|
+
return { addr: tokenAddr, price: priceInWmnt * wmntPriceUsd };
|
|
4063
|
+
} catch {
|
|
4064
|
+
return { addr: tokenAddr, price: 0 };
|
|
4065
|
+
}
|
|
4066
|
+
});
|
|
4067
|
+
const priceResults = await Promise.all(quotePromises);
|
|
4068
|
+
for (const { addr, price } of priceResults) {
|
|
4069
|
+
if (price > 0) tokenPriceMap.set(addr.toLowerCase(), price);
|
|
4070
|
+
}
|
|
4071
|
+
}
|
|
4072
|
+
const getTokenPriceUsd = (_sym, addr) => {
|
|
4073
|
+
return tokenPriceMap.get(addr.toLowerCase()) ?? 0;
|
|
4074
|
+
};
|
|
4075
|
+
const getTokenDecimals = (_sym, addr) => {
|
|
4076
|
+
return tokenDecimalsMap.get(addr.toLowerCase()) ?? 18;
|
|
4077
|
+
};
|
|
3970
4078
|
const binRequests = [];
|
|
3971
4079
|
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3972
4080
|
const range = poolData[i].range;
|
|
@@ -3997,19 +4105,23 @@ var MerchantMoeLBAdapter = class {
|
|
|
3997
4105
|
binReservesY.get(poolIdx).set(binId, decoded[1]);
|
|
3998
4106
|
}
|
|
3999
4107
|
}
|
|
4000
|
-
const
|
|
4001
|
-
const
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4108
|
+
const poolBalanceX = /* @__PURE__ */ new Map();
|
|
4109
|
+
const poolBalanceY = /* @__PURE__ */ new Map();
|
|
4110
|
+
{
|
|
4111
|
+
const balCalls = [];
|
|
4112
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
4113
|
+
const tx = tokenXAddresses[i];
|
|
4114
|
+
const ty = tokenYAddresses[i];
|
|
4115
|
+
const pool = rewardedPairs[i].pool;
|
|
4116
|
+
balCalls.push([tx ?? "0x0000000000000000000000000000000000000000", encodeFunctionData12({ abi: erc20Abi2, functionName: "balanceOf", args: [pool] })]);
|
|
4117
|
+
balCalls.push([ty ?? "0x0000000000000000000000000000000000000000", encodeFunctionData12({ abi: erc20Abi2, functionName: "balanceOf", args: [pool] })]);
|
|
4118
|
+
}
|
|
4119
|
+
const balResults = await multicallRead(rpcUrl, balCalls).catch(() => []);
|
|
4120
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
4121
|
+
poolBalanceX.set(i, decodeUint256Result(balResults[i * 2] ?? null) ?? 0n);
|
|
4122
|
+
poolBalanceY.set(i, decodeUint256Result(balResults[i * 2 + 1] ?? null) ?? 0n);
|
|
4123
|
+
}
|
|
4124
|
+
}
|
|
4013
4125
|
const results = [];
|
|
4014
4126
|
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
4015
4127
|
const { pool, rewarder } = rewardedPairs[i];
|
|
@@ -4034,18 +4146,25 @@ var MerchantMoeLBAdapter = class {
|
|
|
4034
4146
|
const maxBin = Number(range[1]);
|
|
4035
4147
|
rewardedBins = maxBin - minBin + 1;
|
|
4036
4148
|
if (rxMap && ryMap) {
|
|
4037
|
-
const
|
|
4038
|
-
const
|
|
4039
|
-
const
|
|
4040
|
-
const
|
|
4149
|
+
const priceX2 = getTokenPriceUsd(symX, tokenX);
|
|
4150
|
+
const priceY2 = getTokenPriceUsd(symY, tokenY);
|
|
4151
|
+
const decX2 = getTokenDecimals(symX, tokenX);
|
|
4152
|
+
const decY2 = getTokenDecimals(symY, tokenY);
|
|
4041
4153
|
for (let b = minBin; b <= maxBin; b++) {
|
|
4042
4154
|
const rx = rxMap.get(b) ?? 0n;
|
|
4043
4155
|
const ry = ryMap.get(b) ?? 0n;
|
|
4044
|
-
rangeTvlUsd += Number(rx) / 10 **
|
|
4045
|
-
rangeTvlUsd += Number(ry) / 10 **
|
|
4156
|
+
rangeTvlUsd += Number(rx) / 10 ** decX2 * priceX2;
|
|
4157
|
+
rangeTvlUsd += Number(ry) / 10 ** decY2 * priceY2;
|
|
4046
4158
|
}
|
|
4047
4159
|
}
|
|
4048
4160
|
}
|
|
4161
|
+
const priceX = getTokenPriceUsd(symX, tokenX);
|
|
4162
|
+
const priceY = getTokenPriceUsd(symY, tokenY);
|
|
4163
|
+
const decX = getTokenDecimals(symX, tokenX);
|
|
4164
|
+
const decY = getTokenDecimals(symY, tokenY);
|
|
4165
|
+
const fullBalX = poolBalanceX.get(i) ?? 0n;
|
|
4166
|
+
const fullBalY = poolBalanceY.get(i) ?? 0n;
|
|
4167
|
+
const poolTvlUsd = Number(fullBalX) / 10 ** decX * priceX + Number(fullBalY) / 10 ** decY * priceY;
|
|
4049
4168
|
const aprPercent = rangeTvlUsd > 0 && moePriceUsd > 0 ? poolMoePerDay * moePriceUsd * 365 / rangeTvlUsd * 100 : 0;
|
|
4050
4169
|
results.push({
|
|
4051
4170
|
pool,
|
|
@@ -4062,8 +4181,11 @@ var MerchantMoeLBAdapter = class {
|
|
|
4062
4181
|
isTopPool,
|
|
4063
4182
|
moePerDay: poolMoePerDay,
|
|
4064
4183
|
rangeTvlUsd,
|
|
4184
|
+
poolTvlUsd,
|
|
4065
4185
|
aprPercent,
|
|
4066
|
-
rewardedBins
|
|
4186
|
+
rewardedBins,
|
|
4187
|
+
totalMoePerDay: moePerDay,
|
|
4188
|
+
moePriceUsd
|
|
4067
4189
|
});
|
|
4068
4190
|
}
|
|
4069
4191
|
return results;
|
|
@@ -6087,7 +6209,11 @@ function resolvePoolAddress(registry, protocolSlug, pool) {
|
|
|
6087
6209
|
function registerLP(parent, getOpts, makeExecutor2) {
|
|
6088
6210
|
const lp = parent.command("lp").description("Unified LP operations: discover, add, farm, claim, remove, positions");
|
|
6089
6211
|
lp.command("discover").description("Scan all protocols for fee + emission pools (gauges, farming, LB rewards)").option("--protocol <protocol>", "Filter to a single protocol slug").option("--emission-only", "Only show emission (gauge/farming) pools, skip fee-only").action(async (opts) => {
|
|
6090
|
-
const chainName = parent.opts().chain
|
|
6212
|
+
const chainName = parent.opts().chain;
|
|
6213
|
+
if (!chainName) {
|
|
6214
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6215
|
+
return;
|
|
6216
|
+
}
|
|
6091
6217
|
const registry = Registry.loadEmbedded();
|
|
6092
6218
|
const chain = registry.getChain(chainName);
|
|
6093
6219
|
const rpcUrl = chain.effectiveRpcUrl();
|
|
@@ -6142,7 +6268,13 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
6142
6268
|
moePerDay: p.moePerDay,
|
|
6143
6269
|
aprPercent: p.aprPercent,
|
|
6144
6270
|
rangeTvlUsd: p.rangeTvlUsd,
|
|
6145
|
-
|
|
6271
|
+
poolTvlUsd: p.poolTvlUsd,
|
|
6272
|
+
isTopPool: p.isTopPool,
|
|
6273
|
+
rewardedBins: p.rewardedBins,
|
|
6274
|
+
minBinId: p.minBinId,
|
|
6275
|
+
maxBinId: p.maxBinId,
|
|
6276
|
+
totalMoePerDay: p.totalMoePerDay,
|
|
6277
|
+
moePriceUsd: p.moePriceUsd
|
|
6146
6278
|
});
|
|
6147
6279
|
}
|
|
6148
6280
|
}
|
|
@@ -6159,7 +6291,11 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
6159
6291
|
});
|
|
6160
6292
|
lp.command("add").description("Add liquidity to a pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--token-a <token>", "First token symbol or address").requiredOption("--token-b <token>", "Second token symbol or address").requiredOption("--amount-a <amount>", "Amount of token A in wei").requiredOption("--amount-b <amount>", "Amount of token B in wei").option("--pool <name_or_address>", "Pool name (e.g. WHYPE/USDC) or address").option("--recipient <address>", "Recipient address").option("--tick-lower <tick>", "Lower tick for concentrated LP (default: full range)").option("--tick-upper <tick>", "Upper tick for concentrated LP (default: full range)").option("--range <percent>", "\xB1N% concentrated range around current price (e.g. --range 2)").action(async (opts) => {
|
|
6161
6293
|
const executor = makeExecutor2();
|
|
6162
|
-
const chainName = parent.opts().chain
|
|
6294
|
+
const chainName = parent.opts().chain;
|
|
6295
|
+
if (!chainName) {
|
|
6296
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6297
|
+
return;
|
|
6298
|
+
}
|
|
6163
6299
|
const registry = Registry.loadEmbedded();
|
|
6164
6300
|
const chain = registry.getChain(chainName);
|
|
6165
6301
|
const protocol = registry.getProtocol(opts.protocol);
|
|
@@ -6185,7 +6321,11 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
6185
6321
|
});
|
|
6186
6322
|
lp.command("farm").description("Add liquidity and auto-stake into gauge/farming for emissions").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--token-a <token>", "First token symbol or address").requiredOption("--token-b <token>", "Second token symbol or address").requiredOption("--amount-a <amount>", "Amount of token A in wei").requiredOption("--amount-b <amount>", "Amount of token B in wei").option("--pool <name_or_address>", "Pool name (e.g. WHYPE/USDC) or address").option("--gauge <address>", "Gauge address (required for solidly/hybra if not resolved automatically)").option("--recipient <address>", "Recipient / owner address").option("--tick-lower <tick>", "Lower tick for concentrated LP").option("--tick-upper <tick>", "Upper tick for concentrated LP").option("--range <percent>", "\xB1N% concentrated range around current price").action(async (opts) => {
|
|
6187
6323
|
const executor = makeExecutor2();
|
|
6188
|
-
const chainName = parent.opts().chain
|
|
6324
|
+
const chainName = parent.opts().chain;
|
|
6325
|
+
if (!chainName) {
|
|
6326
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6327
|
+
return;
|
|
6328
|
+
}
|
|
6189
6329
|
const registry = Registry.loadEmbedded();
|
|
6190
6330
|
const chain = registry.getChain(chainName);
|
|
6191
6331
|
const protocol = registry.getProtocol(opts.protocol);
|
|
@@ -6263,7 +6403,11 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
6263
6403
|
});
|
|
6264
6404
|
lp.command("claim").description("Claim rewards from a pool (fee or emission)").requiredOption("--protocol <protocol>", "Protocol slug").option("--pool <address>", "Pool address (required for farming/LB)").option("--gauge <address>", "Gauge contract address (required for solidly/hybra)").option("--token-id <id>", "NFT tokenId (for CL gauge or farming positions)").option("--bins <binIds>", "Comma-separated bin IDs (for Merchant Moe LB)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
|
|
6265
6405
|
const executor = makeExecutor2();
|
|
6266
|
-
const chainName = parent.opts().chain
|
|
6406
|
+
const chainName = parent.opts().chain;
|
|
6407
|
+
if (!chainName) {
|
|
6408
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6409
|
+
return;
|
|
6410
|
+
}
|
|
6267
6411
|
const registry = Registry.loadEmbedded();
|
|
6268
6412
|
const chain = registry.getChain(chainName);
|
|
6269
6413
|
const rpcUrl = chain.effectiveRpcUrl();
|
|
@@ -6310,7 +6454,11 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
6310
6454
|
});
|
|
6311
6455
|
lp.command("remove").description("Auto-unstake (if staked) and remove liquidity from a pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--token-a <token>", "First token symbol or address").requiredOption("--token-b <token>", "Second token symbol or address").requiredOption("--liquidity <amount>", "Liquidity amount to remove in wei").option("--pool <address>", "Pool address (needed to resolve gauge)").option("--gauge <address>", "Gauge contract address (for solidly/hybra unstake)").option("--token-id <id>", "NFT tokenId (for CL gauge or farming positions)").option("--recipient <address>", "Recipient address").action(async (opts) => {
|
|
6312
6456
|
const executor = makeExecutor2();
|
|
6313
|
-
const chainName = parent.opts().chain
|
|
6457
|
+
const chainName = parent.opts().chain;
|
|
6458
|
+
if (!chainName) {
|
|
6459
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6460
|
+
return;
|
|
6461
|
+
}
|
|
6314
6462
|
const registry = Registry.loadEmbedded();
|
|
6315
6463
|
const chain = registry.getChain(chainName);
|
|
6316
6464
|
const rpcUrl = chain.effectiveRpcUrl();
|
|
@@ -6373,7 +6521,11 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
6373
6521
|
printOutput({ step: "lp_remove", ...removeResult }, getOpts());
|
|
6374
6522
|
});
|
|
6375
6523
|
lp.command("positions").description("Show all LP positions across protocols").option("--protocol <protocol>", "Filter to a single protocol slug").option("--pool <address>", "Filter to a specific pool address").option("--bins <binIds>", "Comma-separated bin IDs (for Merchant Moe LB, auto-detected if omitted)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
|
|
6376
|
-
const chainName = parent.opts().chain
|
|
6524
|
+
const chainName = parent.opts().chain;
|
|
6525
|
+
if (!chainName) {
|
|
6526
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6527
|
+
return;
|
|
6528
|
+
}
|
|
6377
6529
|
const registry = Registry.loadEmbedded();
|
|
6378
6530
|
const chain = registry.getChain(chainName);
|
|
6379
6531
|
const rpcUrl = chain.effectiveRpcUrl();
|
|
@@ -6644,7 +6796,11 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
6644
6796
|
function registerLending(parent, getOpts, makeExecutor2) {
|
|
6645
6797
|
const lending = parent.command("lending").description("Lending operations: supply, borrow, repay, withdraw, rates, position");
|
|
6646
6798
|
lending.command("rates").description("Show current lending rates").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--asset <token>", "Token symbol or address").action(async (opts) => {
|
|
6647
|
-
const chainName = parent.opts().chain
|
|
6799
|
+
const chainName = parent.opts().chain;
|
|
6800
|
+
if (!chainName) {
|
|
6801
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6802
|
+
return;
|
|
6803
|
+
}
|
|
6648
6804
|
const registry = Registry.loadEmbedded();
|
|
6649
6805
|
const chain = registry.getChain(chainName);
|
|
6650
6806
|
const protocol = registry.getProtocol(opts.protocol);
|
|
@@ -6654,7 +6810,11 @@ function registerLending(parent, getOpts, makeExecutor2) {
|
|
|
6654
6810
|
printOutput(rates, getOpts());
|
|
6655
6811
|
});
|
|
6656
6812
|
lending.command("position").description("Show current lending position").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--address <address>", "Wallet address to query").action(async (opts) => {
|
|
6657
|
-
const chainName = parent.opts().chain
|
|
6813
|
+
const chainName = parent.opts().chain;
|
|
6814
|
+
if (!chainName) {
|
|
6815
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6816
|
+
return;
|
|
6817
|
+
}
|
|
6658
6818
|
const registry = Registry.loadEmbedded();
|
|
6659
6819
|
const chain = registry.getChain(chainName);
|
|
6660
6820
|
const protocol = registry.getProtocol(opts.protocol);
|
|
@@ -6664,7 +6824,11 @@ function registerLending(parent, getOpts, makeExecutor2) {
|
|
|
6664
6824
|
});
|
|
6665
6825
|
lending.command("supply").description("Supply an asset to a lending protocol").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--asset <token>", "Token symbol or address").requiredOption("--amount <amount>", "Amount to supply in wei").option("--on-behalf-of <address>", "On behalf of address").action(async (opts) => {
|
|
6666
6826
|
const executor = makeExecutor2();
|
|
6667
|
-
const chainName = parent.opts().chain
|
|
6827
|
+
const chainName = parent.opts().chain;
|
|
6828
|
+
if (!chainName) {
|
|
6829
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6830
|
+
return;
|
|
6831
|
+
}
|
|
6668
6832
|
const registry = Registry.loadEmbedded();
|
|
6669
6833
|
const chain = registry.getChain(chainName);
|
|
6670
6834
|
const protocol = registry.getProtocol(opts.protocol);
|
|
@@ -6677,7 +6841,11 @@ function registerLending(parent, getOpts, makeExecutor2) {
|
|
|
6677
6841
|
});
|
|
6678
6842
|
lending.command("borrow").description("Borrow an asset").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--asset <token>", "Token symbol or address").requiredOption("--amount <amount>", "Amount in wei").option("--rate-mode <mode>", "variable or stable", "variable").option("--on-behalf-of <address>", "On behalf of address").action(async (opts) => {
|
|
6679
6843
|
const executor = makeExecutor2();
|
|
6680
|
-
const chainName = parent.opts().chain
|
|
6844
|
+
const chainName = parent.opts().chain;
|
|
6845
|
+
if (!chainName) {
|
|
6846
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6847
|
+
return;
|
|
6848
|
+
}
|
|
6681
6849
|
const registry = Registry.loadEmbedded();
|
|
6682
6850
|
const chain = registry.getChain(chainName);
|
|
6683
6851
|
const protocol = registry.getProtocol(opts.protocol);
|
|
@@ -6696,7 +6864,11 @@ function registerLending(parent, getOpts, makeExecutor2) {
|
|
|
6696
6864
|
});
|
|
6697
6865
|
lending.command("repay").description("Repay a borrowed asset").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--asset <token>", "Token symbol or address").requiredOption("--amount <amount>", "Amount in wei").option("--rate-mode <mode>", "variable or stable", "variable").option("--on-behalf-of <address>", "On behalf of address").action(async (opts) => {
|
|
6698
6866
|
const executor = makeExecutor2();
|
|
6699
|
-
const chainName = parent.opts().chain
|
|
6867
|
+
const chainName = parent.opts().chain;
|
|
6868
|
+
if (!chainName) {
|
|
6869
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6870
|
+
return;
|
|
6871
|
+
}
|
|
6700
6872
|
const registry = Registry.loadEmbedded();
|
|
6701
6873
|
const chain = registry.getChain(chainName);
|
|
6702
6874
|
const protocol = registry.getProtocol(opts.protocol);
|
|
@@ -6715,7 +6887,11 @@ function registerLending(parent, getOpts, makeExecutor2) {
|
|
|
6715
6887
|
});
|
|
6716
6888
|
lending.command("withdraw").description("Withdraw a supplied asset").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--asset <token>", "Token symbol or address").requiredOption("--amount <amount>", "Amount in wei").option("--to <address>", "Recipient address").action(async (opts) => {
|
|
6717
6889
|
const executor = makeExecutor2();
|
|
6718
|
-
const chainName = parent.opts().chain
|
|
6890
|
+
const chainName = parent.opts().chain;
|
|
6891
|
+
if (!chainName) {
|
|
6892
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6893
|
+
return;
|
|
6894
|
+
}
|
|
6719
6895
|
const registry = Registry.loadEmbedded();
|
|
6720
6896
|
const chain = registry.getChain(chainName);
|
|
6721
6897
|
const protocol = registry.getProtocol(opts.protocol);
|
|
@@ -6943,8 +7119,10 @@ function registerYield(parent, getOpts, makeExecutor2) {
|
|
|
6943
7119
|
try {
|
|
6944
7120
|
const registry = Registry.loadEmbedded();
|
|
6945
7121
|
const asset = opts.asset;
|
|
7122
|
+
const specifiedChain = parent.opts().chain;
|
|
7123
|
+
const chainKeys = specifiedChain ? [specifiedChain.toLowerCase()] : Array.from(registry.chains.keys());
|
|
6946
7124
|
const allRates = [];
|
|
6947
|
-
for (const
|
|
7125
|
+
for (const chainKey of chainKeys) {
|
|
6948
7126
|
try {
|
|
6949
7127
|
const chain = registry.getChain(chainKey);
|
|
6950
7128
|
const rpc = chain.effectiveRpcUrl();
|
|
@@ -6973,7 +7151,12 @@ function registerYield(parent, getOpts, makeExecutor2) {
|
|
|
6973
7151
|
yieldCmd.command("compare").description("Compare lending rates across protocols for an asset").option("--asset <token>", "Token symbol or address", "USDC").action(async (opts) => {
|
|
6974
7152
|
try {
|
|
6975
7153
|
const registry = Registry.loadEmbedded();
|
|
6976
|
-
const
|
|
7154
|
+
const specChain = parent.opts().chain;
|
|
7155
|
+
if (!specChain) {
|
|
7156
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
7157
|
+
return;
|
|
7158
|
+
}
|
|
7159
|
+
const chainName = specChain.toLowerCase();
|
|
6977
7160
|
const chain = registry.getChain(chainName);
|
|
6978
7161
|
const rpc = chain.effectiveRpcUrl();
|
|
6979
7162
|
const assetAddr = resolveAsset(registry, chainName, opts.asset);
|
|
@@ -7209,7 +7392,12 @@ function registerYield(parent, getOpts, makeExecutor2) {
|
|
|
7209
7392
|
yieldCmd.command("optimize").description("Find the optimal yield strategy for an asset").requiredOption("--asset <token>", "Token symbol or address").option("--strategy <strategy>", "Strategy: best-supply, leverage-loop, auto", "auto").option("--amount <amount>", "Amount to deploy (for allocation breakdown)").action(async (opts) => {
|
|
7210
7393
|
try {
|
|
7211
7394
|
const registry = Registry.loadEmbedded();
|
|
7212
|
-
const
|
|
7395
|
+
const specChain = parent.opts().chain;
|
|
7396
|
+
if (!specChain) {
|
|
7397
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
7398
|
+
return;
|
|
7399
|
+
}
|
|
7400
|
+
const chainName = specChain.toLowerCase();
|
|
7213
7401
|
const chain = registry.getChain(chainName);
|
|
7214
7402
|
const rpc = chain.effectiveRpcUrl();
|
|
7215
7403
|
const asset = opts.asset;
|
|
@@ -7555,7 +7743,12 @@ function registerPortfolio(parent, getOpts) {
|
|
|
7555
7743
|
portfolio.command("show").description("Show current portfolio positions").requiredOption("--address <address>", "Wallet address to query").action(async (opts) => {
|
|
7556
7744
|
const mode = getOpts();
|
|
7557
7745
|
const registry = Registry.loadEmbedded();
|
|
7558
|
-
const
|
|
7746
|
+
const _chain = parent.opts().chain;
|
|
7747
|
+
if (!_chain) {
|
|
7748
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
7749
|
+
return;
|
|
7750
|
+
}
|
|
7751
|
+
const chainName = _chain.toLowerCase();
|
|
7559
7752
|
let chain;
|
|
7560
7753
|
try {
|
|
7561
7754
|
chain = registry.getChain(chainName);
|
|
@@ -7693,7 +7886,12 @@ function registerPortfolio(parent, getOpts) {
|
|
|
7693
7886
|
});
|
|
7694
7887
|
portfolio.command("snapshot").description("Take a new portfolio snapshot and save it locally").requiredOption("--address <address>", "Wallet address to snapshot").action(async (opts) => {
|
|
7695
7888
|
const mode = getOpts();
|
|
7696
|
-
const
|
|
7889
|
+
const _chain = parent.opts().chain;
|
|
7890
|
+
if (!_chain) {
|
|
7891
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
7892
|
+
return;
|
|
7893
|
+
}
|
|
7894
|
+
const chainName = _chain.toLowerCase();
|
|
7697
7895
|
const registry = Registry.loadEmbedded();
|
|
7698
7896
|
if (!/^0x[0-9a-fA-F]{40}$/.test(opts.address)) {
|
|
7699
7897
|
printOutput({ error: `Invalid address: ${opts.address}` }, mode);
|
|
@@ -7720,7 +7918,12 @@ function registerPortfolio(parent, getOpts) {
|
|
|
7720
7918
|
});
|
|
7721
7919
|
portfolio.command("pnl").description("Show PnL since the last snapshot").requiredOption("--address <address>", "Wallet address").option("--since <hours>", "Compare against snapshot from N hours ago (default: last snapshot)").action(async (opts) => {
|
|
7722
7920
|
const mode = getOpts();
|
|
7723
|
-
const
|
|
7921
|
+
const _chain = parent.opts().chain;
|
|
7922
|
+
if (!_chain) {
|
|
7923
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
7924
|
+
return;
|
|
7925
|
+
}
|
|
7926
|
+
const chainName = _chain.toLowerCase();
|
|
7724
7927
|
const registry = Registry.loadEmbedded();
|
|
7725
7928
|
if (!/^0x[0-9a-fA-F]{40}$/.test(opts.address)) {
|
|
7726
7929
|
printOutput({ error: `Invalid address: ${opts.address}` }, mode);
|
|
@@ -7765,7 +7968,12 @@ function registerPortfolio(parent, getOpts) {
|
|
|
7765
7968
|
});
|
|
7766
7969
|
portfolio.command("history").description("List saved portfolio snapshots with values").requiredOption("--address <address>", "Wallet address").option("--limit <n>", "Number of snapshots to show", "10").action(async (opts) => {
|
|
7767
7970
|
const mode = getOpts();
|
|
7768
|
-
const
|
|
7971
|
+
const _chain = parent.opts().chain;
|
|
7972
|
+
if (!_chain) {
|
|
7973
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
7974
|
+
return;
|
|
7975
|
+
}
|
|
7976
|
+
const chainName = _chain.toLowerCase();
|
|
7769
7977
|
if (!/^0x[0-9a-fA-F]{40}$/.test(opts.address)) {
|
|
7770
7978
|
printOutput({ error: `Invalid address: ${opts.address}` }, mode);
|
|
7771
7979
|
return;
|
|
@@ -7804,7 +8012,12 @@ function registerPrice(parent, getOpts) {
|
|
|
7804
8012
|
parent.command("price").description("Query asset prices from oracles and DEXes").requiredOption("--asset <token>", "Token symbol or address").option("--source <source>", "Price source: oracle, dex, or all", "all").action(async (opts) => {
|
|
7805
8013
|
const mode = getOpts();
|
|
7806
8014
|
const registry = Registry.loadEmbedded();
|
|
7807
|
-
const
|
|
8015
|
+
const _chain = parent.opts().chain;
|
|
8016
|
+
if (!_chain) {
|
|
8017
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
8018
|
+
return;
|
|
8019
|
+
}
|
|
8020
|
+
const chainName = _chain.toLowerCase();
|
|
7808
8021
|
let chain;
|
|
7809
8022
|
try {
|
|
7810
8023
|
chain = registry.getChain(chainName);
|
|
@@ -7931,7 +8144,11 @@ import { createPublicClient as createPublicClient23, http as http23, formatEther
|
|
|
7931
8144
|
function registerWallet(parent, getOpts) {
|
|
7932
8145
|
const wallet = parent.command("wallet").description("Wallet management");
|
|
7933
8146
|
wallet.command("balance").description("Show native token balance").requiredOption("--address <address>", "Wallet address to query").action(async (opts) => {
|
|
7934
|
-
const chainName = parent.opts().chain
|
|
8147
|
+
const chainName = parent.opts().chain;
|
|
8148
|
+
if (!chainName) {
|
|
8149
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
8150
|
+
return;
|
|
8151
|
+
}
|
|
7935
8152
|
const registry = Registry.loadEmbedded();
|
|
7936
8153
|
const chain = registry.getChain(chainName);
|
|
7937
8154
|
const client = createPublicClient23({ transport: http23(chain.effectiveRpcUrl()) });
|
|
@@ -7955,7 +8172,11 @@ import { createPublicClient as createPublicClient24, http as http24, maxUint256
|
|
|
7955
8172
|
function registerToken(parent, getOpts, makeExecutor2) {
|
|
7956
8173
|
const token = parent.command("token").description("Token operations: approve, allowance, transfer, balance");
|
|
7957
8174
|
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) => {
|
|
7958
|
-
const chainName = parent.opts().chain
|
|
8175
|
+
const chainName = parent.opts().chain;
|
|
8176
|
+
if (!chainName) {
|
|
8177
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
8178
|
+
return;
|
|
8179
|
+
}
|
|
7959
8180
|
const registry = Registry.loadEmbedded();
|
|
7960
8181
|
const chain = registry.getChain(chainName);
|
|
7961
8182
|
const client = createPublicClient24({ transport: http24(chain.effectiveRpcUrl()) });
|
|
@@ -7975,7 +8196,11 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
7975
8196
|
});
|
|
7976
8197
|
token.command("approve").description("Approve a spender for a token").requiredOption("--token <token>", "Token symbol or address").requiredOption("--spender <address>", "Spender address").option("--amount <amount>", "Amount to approve (use 'max' for unlimited)", "max").action(async (opts) => {
|
|
7977
8198
|
const executor = makeExecutor2();
|
|
7978
|
-
const chainName = parent.opts().chain
|
|
8199
|
+
const chainName = parent.opts().chain;
|
|
8200
|
+
if (!chainName) {
|
|
8201
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
8202
|
+
return;
|
|
8203
|
+
}
|
|
7979
8204
|
const registry = Registry.loadEmbedded();
|
|
7980
8205
|
const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
|
|
7981
8206
|
const amount = opts.amount === "max" ? maxUint256 : BigInt(opts.amount);
|
|
@@ -7984,7 +8209,11 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
7984
8209
|
printOutput(result, getOpts());
|
|
7985
8210
|
});
|
|
7986
8211
|
token.command("allowance").description("Check token allowance").requiredOption("--token <token>", "Token symbol or address").requiredOption("--owner <address>", "Owner address").requiredOption("--spender <address>", "Spender address").action(async (opts) => {
|
|
7987
|
-
const chainName = parent.opts().chain
|
|
8212
|
+
const chainName = parent.opts().chain;
|
|
8213
|
+
if (!chainName) {
|
|
8214
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
8215
|
+
return;
|
|
8216
|
+
}
|
|
7988
8217
|
const registry = Registry.loadEmbedded();
|
|
7989
8218
|
const chain = registry.getChain(chainName);
|
|
7990
8219
|
const client = createPublicClient24({ transport: http24(chain.effectiveRpcUrl()) });
|
|
@@ -7999,7 +8228,11 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
7999
8228
|
});
|
|
8000
8229
|
token.command("transfer").description("Transfer tokens to an address").requiredOption("--token <token>", "Token symbol or address").requiredOption("--to <address>", "Recipient address").requiredOption("--amount <amount>", "Amount to transfer (in wei)").action(async (opts) => {
|
|
8001
8230
|
const executor = makeExecutor2();
|
|
8002
|
-
const chainName = parent.opts().chain
|
|
8231
|
+
const chainName = parent.opts().chain;
|
|
8232
|
+
if (!chainName) {
|
|
8233
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
8234
|
+
return;
|
|
8235
|
+
}
|
|
8003
8236
|
const registry = Registry.loadEmbedded();
|
|
8004
8237
|
const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
|
|
8005
8238
|
const tx = buildTransfer(tokenAddr, opts.to, BigInt(opts.amount));
|
|
@@ -8106,7 +8339,11 @@ async function getCctpFeeEstimate(srcDomain, dstDomain, amountUsdc) {
|
|
|
8106
8339
|
}
|
|
8107
8340
|
function registerBridge(parent, getOpts) {
|
|
8108
8341
|
parent.command("bridge").description("Cross-chain bridge: move assets between chains").requiredOption("--token <token>", "Token symbol or address").requiredOption("--amount <amount>", "Amount in wei").requiredOption("--to-chain <chain>", "Destination chain name").option("--recipient <address>", "Recipient address on destination chain").option("--slippage <bps>", "Slippage in bps (LI.FI only)", "50").option("--provider <name>", "Bridge provider: lifi, debridge, cctp", "lifi").action(async (opts) => {
|
|
8109
|
-
const chainName = parent.opts().chain
|
|
8342
|
+
const chainName = parent.opts().chain;
|
|
8343
|
+
if (!chainName) {
|
|
8344
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
8345
|
+
return;
|
|
8346
|
+
}
|
|
8110
8347
|
const registry = Registry.loadEmbedded();
|
|
8111
8348
|
const fromChain = registry.getChain(chainName);
|
|
8112
8349
|
const toChain = registry.getChain(opts.toChain);
|
|
@@ -8310,7 +8547,11 @@ async function liquidSwapRoute(tokenIn, tokenOut, amountIn, slippagePct) {
|
|
|
8310
8547
|
function registerSwap(parent, getOpts, makeExecutor2) {
|
|
8311
8548
|
parent.command("swap").description("Swap tokens via DEX aggregator (KyberSwap, OpenOcean, LiquidSwap)").requiredOption("--from <token>", "Input token symbol or address").requiredOption("--to <token>", "Output token symbol or address").requiredOption("--amount <amount>", "Amount of input token in wei").option("--provider <name>", "Aggregator: kyber, openocean, liquid", "kyber").option("--slippage <bps>", "Slippage tolerance in bps", "50").action(async (opts) => {
|
|
8312
8549
|
const executor = makeExecutor2();
|
|
8313
|
-
const chainName = parent.opts().chain
|
|
8550
|
+
const chainName = parent.opts().chain;
|
|
8551
|
+
if (!chainName) {
|
|
8552
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
8553
|
+
return;
|
|
8554
|
+
}
|
|
8314
8555
|
const registry = Registry.loadEmbedded();
|
|
8315
8556
|
const provider = opts.provider.toLowerCase();
|
|
8316
8557
|
const slippageBps = parseInt(opts.slippage, 10);
|
|
@@ -8596,7 +8837,7 @@ var BANNER = `
|
|
|
8596
8837
|
Lending, LP farming, DEX swap, yield comparison
|
|
8597
8838
|
\u2014 all from your terminal.
|
|
8598
8839
|
`;
|
|
8599
|
-
var program = new Command().name("defi").description("DeFi CLI \u2014 Multi-chain DeFi toolkit").version(_pkg.version).addHelpText("before", BANNER).option("--json", "Output as JSON").option("--ndjson", "Output as newline-delimited JSON").option("--fields <fields>", "Select specific output fields (comma-separated)").option("--chain <chain>", "Target chain"
|
|
8840
|
+
var program = new Command().name("defi").description("DeFi CLI \u2014 Multi-chain DeFi toolkit").version(_pkg.version).addHelpText("before", BANNER).option("--json", "Output as JSON").option("--ndjson", "Output as newline-delimited JSON").option("--fields <fields>", "Select specific output fields (comma-separated)").option("--chain <chain>", "Target chain").option("--dry-run", "Dry-run mode (default, no broadcast)", true).option("--broadcast", "Actually broadcast the transaction");
|
|
8600
8841
|
function getOutputMode() {
|
|
8601
8842
|
const opts = program.opts();
|
|
8602
8843
|
return parseOutputMode(opts);
|
|
@@ -8604,7 +8845,11 @@ function getOutputMode() {
|
|
|
8604
8845
|
function makeExecutor() {
|
|
8605
8846
|
const opts = program.opts();
|
|
8606
8847
|
const registry = Registry.loadEmbedded();
|
|
8607
|
-
|
|
8848
|
+
if (!opts.chain) {
|
|
8849
|
+
process.stderr.write("Error: --chain is required for this command (e.g. --chain hyperevm)\n");
|
|
8850
|
+
process.exit(1);
|
|
8851
|
+
}
|
|
8852
|
+
const chain = registry.getChain(opts.chain);
|
|
8608
8853
|
return new Executor(!!opts.broadcast, chain.effectiveRpcUrl(), chain.explorer_url);
|
|
8609
8854
|
}
|
|
8610
8855
|
registerStatus(program, getOutputMode);
|