@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/index.js
CHANGED
|
@@ -1008,8 +1008,25 @@ function isPlaceholder(addr) {
|
|
|
1008
1008
|
function registerStatus(parent, getOpts) {
|
|
1009
1009
|
parent.command("status").description("Show chain and protocol status").option("--verify", "Verify contract addresses on-chain").action(async (opts) => {
|
|
1010
1010
|
const globalOpts = parent.opts();
|
|
1011
|
-
const chainName = globalOpts.chain ?? "hyperevm";
|
|
1012
1011
|
const registry = Registry.loadEmbedded();
|
|
1012
|
+
const chainKeys = globalOpts.chain ? [globalOpts.chain] : Array.from(registry.chains.keys());
|
|
1013
|
+
if (chainKeys.length > 1) {
|
|
1014
|
+
const summary = [];
|
|
1015
|
+
for (const ck of chainKeys) {
|
|
1016
|
+
const cc = registry.getChain(ck);
|
|
1017
|
+
const protos = registry.getProtocolsForChain(ck);
|
|
1018
|
+
summary.push({
|
|
1019
|
+
chain: cc.name,
|
|
1020
|
+
chain_id: cc.chain_id,
|
|
1021
|
+
rpc_url: cc.effectiveRpcUrl(),
|
|
1022
|
+
protocols: protos.map((p) => ({ slug: p.slug, name: p.name, category: p.category, interface: p.interface })),
|
|
1023
|
+
summary: { total_protocols: protos.length }
|
|
1024
|
+
});
|
|
1025
|
+
}
|
|
1026
|
+
printOutput(summary, getOpts());
|
|
1027
|
+
return;
|
|
1028
|
+
}
|
|
1029
|
+
const chainName = chainKeys[0];
|
|
1013
1030
|
const chainConfig = registry.getChain(chainName);
|
|
1014
1031
|
const chainProtocols = registry.getProtocolsForChain(chainName);
|
|
1015
1032
|
let blockNumber;
|
|
@@ -1113,27 +1130,34 @@ function registerStatus(parent, getOpts) {
|
|
|
1113
1130
|
function handleSchema(params) {
|
|
1114
1131
|
const action = typeof params["action"] === "string" ? params["action"] : "all";
|
|
1115
1132
|
switch (action) {
|
|
1116
|
-
case "
|
|
1133
|
+
case "status":
|
|
1134
|
+
return { action: "status", params: {}, cli: "defi status" };
|
|
1135
|
+
case "list_protocols":
|
|
1117
1136
|
return {
|
|
1118
|
-
action: "
|
|
1137
|
+
action: "list_protocols",
|
|
1119
1138
|
params: {
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
amount: { type: "string", required: true, description: "Amount (human-readable, e.g. '1.5')" },
|
|
1124
|
-
slippage_bps: { type: "number", required: false, default: 50, description: "Slippage in basis points" },
|
|
1125
|
-
recipient: { type: "string", required: false, description: "Recipient address" }
|
|
1126
|
-
}
|
|
1139
|
+
category: { type: "string", required: false, description: "Filter by category (e.g. dex, lending)" }
|
|
1140
|
+
},
|
|
1141
|
+
cli: "defi status"
|
|
1127
1142
|
};
|
|
1128
|
-
case "
|
|
1143
|
+
case "yield":
|
|
1129
1144
|
return {
|
|
1130
|
-
action: "
|
|
1145
|
+
action: "yield",
|
|
1131
1146
|
params: {
|
|
1147
|
+
chain: { type: "string", required: false, description: "Target chain (omit for all chains)" },
|
|
1148
|
+
asset: { type: "string", required: false, default: "USDC", description: "Token symbol" }
|
|
1149
|
+
},
|
|
1150
|
+
cli: "defi yield --asset USDC"
|
|
1151
|
+
};
|
|
1152
|
+
case "lending.rates":
|
|
1153
|
+
return {
|
|
1154
|
+
action: "lending.rates",
|
|
1155
|
+
params: {
|
|
1156
|
+
chain: { type: "string", required: true, description: "Target chain" },
|
|
1132
1157
|
protocol: { type: "string", required: true, description: "Protocol slug" },
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
}
|
|
1158
|
+
asset: { type: "string", required: true, description: "Token symbol or address" }
|
|
1159
|
+
},
|
|
1160
|
+
cli: "defi --chain hyperevm lending rates --protocol hypurrfi --asset USDC"
|
|
1137
1161
|
};
|
|
1138
1162
|
case "lending.supply":
|
|
1139
1163
|
case "lending.borrow":
|
|
@@ -1142,47 +1166,54 @@ function handleSchema(params) {
|
|
|
1142
1166
|
return {
|
|
1143
1167
|
action,
|
|
1144
1168
|
params: {
|
|
1169
|
+
chain: { type: "string", required: true, description: "Target chain" },
|
|
1145
1170
|
protocol: { type: "string", required: true, description: "Protocol slug" },
|
|
1146
1171
|
asset: { type: "string", required: true, description: "Token symbol or address" },
|
|
1147
|
-
amount: { type: "string", required: true, description: "Amount
|
|
1148
|
-
}
|
|
1172
|
+
amount: { type: "string", required: true, description: "Amount in wei" }
|
|
1173
|
+
},
|
|
1174
|
+
cli: `defi --chain hyperevm lending ${action.split(".")[1]} --protocol hypurrfi --asset USDC --amount 1000000`
|
|
1149
1175
|
};
|
|
1150
|
-
case "
|
|
1151
|
-
case "staking.unstake":
|
|
1176
|
+
case "lp.discover":
|
|
1152
1177
|
return {
|
|
1153
|
-
action,
|
|
1178
|
+
action: "lp.discover",
|
|
1154
1179
|
params: {
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
}
|
|
1180
|
+
chain: { type: "string", required: true, description: "Target chain" },
|
|
1181
|
+
protocol: { type: "string", required: false, description: "Filter by protocol slug" }
|
|
1182
|
+
},
|
|
1183
|
+
cli: "defi --chain hyperevm lp discover"
|
|
1158
1184
|
};
|
|
1159
|
-
case "
|
|
1160
|
-
case "vault.withdraw":
|
|
1185
|
+
case "swap":
|
|
1161
1186
|
return {
|
|
1162
|
-
action,
|
|
1187
|
+
action: "swap",
|
|
1163
1188
|
params: {
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1189
|
+
chain: { type: "string", required: true, description: "Target chain" },
|
|
1190
|
+
from: { type: "string", required: true, description: "Input token symbol or address" },
|
|
1191
|
+
to: { type: "string", required: true, description: "Output token symbol or address" },
|
|
1192
|
+
amount: { type: "string", required: true, description: "Amount in wei" },
|
|
1193
|
+
provider: { type: "string", required: false, default: "kyber", description: "Aggregator: kyber, openocean, liquid" },
|
|
1194
|
+
slippage: { type: "string", required: false, default: "50", description: "Slippage in bps" }
|
|
1195
|
+
},
|
|
1196
|
+
cli: "defi --chain hyperevm swap --from USDC --to WHYPE --amount 1000000"
|
|
1167
1197
|
};
|
|
1168
|
-
case "
|
|
1198
|
+
case "price":
|
|
1169
1199
|
return {
|
|
1170
|
-
action: "
|
|
1200
|
+
action: "price",
|
|
1171
1201
|
params: {
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
}
|
|
1202
|
+
chain: { type: "string", required: true, description: "Target chain" },
|
|
1203
|
+
asset: { type: "string", required: true, description: "Token symbol or address" }
|
|
1204
|
+
},
|
|
1205
|
+
cli: "defi --chain hyperevm price --asset WHYPE"
|
|
1177
1206
|
};
|
|
1178
|
-
case "
|
|
1179
|
-
return { action: "status", params: {} };
|
|
1180
|
-
case "list_protocols":
|
|
1207
|
+
case "bridge":
|
|
1181
1208
|
return {
|
|
1182
|
-
action: "
|
|
1209
|
+
action: "bridge",
|
|
1183
1210
|
params: {
|
|
1184
|
-
|
|
1185
|
-
|
|
1211
|
+
chain: { type: "string", required: true, description: "Source chain" },
|
|
1212
|
+
token: { type: "string", required: true, description: "Token symbol or address" },
|
|
1213
|
+
amount: { type: "string", required: true, description: "Amount in wei" },
|
|
1214
|
+
to_chain: { type: "string", required: true, description: "Destination chain" }
|
|
1215
|
+
},
|
|
1216
|
+
cli: "defi --chain hyperevm bridge --token USDC --amount 1000000 --to-chain mantle"
|
|
1186
1217
|
};
|
|
1187
1218
|
default:
|
|
1188
1219
|
return {
|
|
@@ -1190,17 +1221,25 @@ function handleSchema(params) {
|
|
|
1190
1221
|
"status",
|
|
1191
1222
|
"list_protocols",
|
|
1192
1223
|
"schema",
|
|
1193
|
-
"
|
|
1194
|
-
"
|
|
1224
|
+
"yield",
|
|
1225
|
+
"lending.rates",
|
|
1195
1226
|
"lending.supply",
|
|
1196
1227
|
"lending.borrow",
|
|
1197
1228
|
"lending.repay",
|
|
1198
1229
|
"lending.withdraw",
|
|
1199
|
-
"
|
|
1200
|
-
"
|
|
1201
|
-
"
|
|
1202
|
-
"
|
|
1203
|
-
"
|
|
1230
|
+
"lp.discover",
|
|
1231
|
+
"lp.add",
|
|
1232
|
+
"lp.farm",
|
|
1233
|
+
"lp.claim",
|
|
1234
|
+
"lp.remove",
|
|
1235
|
+
"swap",
|
|
1236
|
+
"price",
|
|
1237
|
+
"token.balance",
|
|
1238
|
+
"token.approve",
|
|
1239
|
+
"token.transfer",
|
|
1240
|
+
"wallet.balance",
|
|
1241
|
+
"portfolio.show",
|
|
1242
|
+
"bridge"
|
|
1204
1243
|
]
|
|
1205
1244
|
};
|
|
1206
1245
|
}
|
|
@@ -3455,7 +3494,8 @@ var lbQuoterAbi2 = parseAbi12([
|
|
|
3455
3494
|
"function findBestPathFromAmountIn(address[] calldata route, uint128 amountIn) external view returns ((address[] route, address[] pairs, uint256[] binSteps, uint256[] versions, uint128[] amounts, uint128[] virtualAmountsWithoutSlippage, uint128[] fees))"
|
|
3456
3495
|
]);
|
|
3457
3496
|
var erc20Abi2 = parseAbi12([
|
|
3458
|
-
"function symbol() external view returns (string)"
|
|
3497
|
+
"function symbol() external view returns (string)",
|
|
3498
|
+
"function balanceOf(address account) external view returns (uint256)"
|
|
3459
3499
|
]);
|
|
3460
3500
|
var _addressAbi = parseAbi12(["function f() external view returns (address)"]);
|
|
3461
3501
|
function decodeAddressResult(data) {
|
|
@@ -3963,6 +4003,74 @@ var MerchantMoeLBAdapter = class {
|
|
|
3963
4003
|
} catch {
|
|
3964
4004
|
}
|
|
3965
4005
|
}
|
|
4006
|
+
const stableSymbols = /* @__PURE__ */ new Set(["USDT", "USDC", "USDT0", "MUSD", "AUSD", "USDY", "FDUSD", "USDe", "sUSDe"]);
|
|
4007
|
+
const mntSymbols = /* @__PURE__ */ new Set(["WMNT", "MNT"]);
|
|
4008
|
+
const moeSymbols = /* @__PURE__ */ new Set(["MOE"]);
|
|
4009
|
+
const sixDecimalStables = /* @__PURE__ */ new Set(["USDT", "USDC", "USDT0", "FDUSD"]);
|
|
4010
|
+
const tokenPriceMap = /* @__PURE__ */ new Map();
|
|
4011
|
+
const tokenDecimalsMap = /* @__PURE__ */ new Map();
|
|
4012
|
+
for (const [addr, sym] of symbolMap) {
|
|
4013
|
+
const key = addr.toLowerCase();
|
|
4014
|
+
if (stableSymbols.has(sym)) {
|
|
4015
|
+
tokenPriceMap.set(key, 1);
|
|
4016
|
+
tokenDecimalsMap.set(key, sixDecimalStables.has(sym) ? 6 : 18);
|
|
4017
|
+
} else if (mntSymbols.has(sym)) {
|
|
4018
|
+
tokenPriceMap.set(key, wmntPriceUsd);
|
|
4019
|
+
tokenDecimalsMap.set(key, 18);
|
|
4020
|
+
} else if (moeSymbols.has(sym)) {
|
|
4021
|
+
tokenPriceMap.set(key, moePriceUsd);
|
|
4022
|
+
tokenDecimalsMap.set(key, 18);
|
|
4023
|
+
}
|
|
4024
|
+
}
|
|
4025
|
+
const unknownTokenAddrs = [];
|
|
4026
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
4027
|
+
for (const addr of [tokenXAddresses[i], tokenYAddresses[i]]) {
|
|
4028
|
+
if (addr && !tokenPriceMap.has(addr.toLowerCase())) {
|
|
4029
|
+
if (!unknownTokenAddrs.some((a) => a.toLowerCase() === addr.toLowerCase())) {
|
|
4030
|
+
unknownTokenAddrs.push(addr);
|
|
4031
|
+
}
|
|
4032
|
+
}
|
|
4033
|
+
}
|
|
4034
|
+
}
|
|
4035
|
+
if (unknownTokenAddrs.length > 0 && this.lbQuoter && this.wmnt && wmntPriceUsd > 0) {
|
|
4036
|
+
const erc20DecimalsAbi = parseAbi12(["function decimals() external view returns (uint8)"]);
|
|
4037
|
+
const decCalls = unknownTokenAddrs.map((addr) => [
|
|
4038
|
+
addr,
|
|
4039
|
+
encodeFunctionData12({ abi: erc20DecimalsAbi, functionName: "decimals" })
|
|
4040
|
+
]);
|
|
4041
|
+
const decResults = await multicallRead(rpcUrl, decCalls).catch(() => []);
|
|
4042
|
+
for (let i = 0; i < unknownTokenAddrs.length; i++) {
|
|
4043
|
+
const dec = decResults[i] ? Number(decodeUint256Result(decResults[i]) ?? 18n) : 18;
|
|
4044
|
+
tokenDecimalsMap.set(unknownTokenAddrs[i].toLowerCase(), dec);
|
|
4045
|
+
}
|
|
4046
|
+
const quotePromises = unknownTokenAddrs.map(async (tokenAddr) => {
|
|
4047
|
+
try {
|
|
4048
|
+
const dec = tokenDecimalsMap.get(tokenAddr.toLowerCase()) ?? 18;
|
|
4049
|
+
const quoteUnit = 10n ** BigInt(Math.max(dec - 2, 0));
|
|
4050
|
+
const quote = await client.readContract({
|
|
4051
|
+
address: this.lbQuoter,
|
|
4052
|
+
abi: lbQuoterAbi2,
|
|
4053
|
+
functionName: "findBestPathFromAmountIn",
|
|
4054
|
+
args: [[tokenAddr, this.wmnt], quoteUnit]
|
|
4055
|
+
});
|
|
4056
|
+
const amountOut = quote.amounts?.at(-1) ?? 0n;
|
|
4057
|
+
const priceInWmnt = Number(amountOut) / 1e18 * (10 ** dec / Number(quoteUnit));
|
|
4058
|
+
return { addr: tokenAddr, price: priceInWmnt * wmntPriceUsd };
|
|
4059
|
+
} catch {
|
|
4060
|
+
return { addr: tokenAddr, price: 0 };
|
|
4061
|
+
}
|
|
4062
|
+
});
|
|
4063
|
+
const priceResults = await Promise.all(quotePromises);
|
|
4064
|
+
for (const { addr, price } of priceResults) {
|
|
4065
|
+
if (price > 0) tokenPriceMap.set(addr.toLowerCase(), price);
|
|
4066
|
+
}
|
|
4067
|
+
}
|
|
4068
|
+
const getTokenPriceUsd = (_sym, addr) => {
|
|
4069
|
+
return tokenPriceMap.get(addr.toLowerCase()) ?? 0;
|
|
4070
|
+
};
|
|
4071
|
+
const getTokenDecimals = (_sym, addr) => {
|
|
4072
|
+
return tokenDecimalsMap.get(addr.toLowerCase()) ?? 18;
|
|
4073
|
+
};
|
|
3966
4074
|
const binRequests = [];
|
|
3967
4075
|
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
3968
4076
|
const range = poolData[i].range;
|
|
@@ -3993,19 +4101,23 @@ var MerchantMoeLBAdapter = class {
|
|
|
3993
4101
|
binReservesY.get(poolIdx).set(binId, decoded[1]);
|
|
3994
4102
|
}
|
|
3995
4103
|
}
|
|
3996
|
-
const
|
|
3997
|
-
const
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4104
|
+
const poolBalanceX = /* @__PURE__ */ new Map();
|
|
4105
|
+
const poolBalanceY = /* @__PURE__ */ new Map();
|
|
4106
|
+
{
|
|
4107
|
+
const balCalls = [];
|
|
4108
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
4109
|
+
const tx = tokenXAddresses[i];
|
|
4110
|
+
const ty = tokenYAddresses[i];
|
|
4111
|
+
const pool = rewardedPairs[i].pool;
|
|
4112
|
+
balCalls.push([tx ?? "0x0000000000000000000000000000000000000000", encodeFunctionData12({ abi: erc20Abi2, functionName: "balanceOf", args: [pool] })]);
|
|
4113
|
+
balCalls.push([ty ?? "0x0000000000000000000000000000000000000000", encodeFunctionData12({ abi: erc20Abi2, functionName: "balanceOf", args: [pool] })]);
|
|
4114
|
+
}
|
|
4115
|
+
const balResults = await multicallRead(rpcUrl, balCalls).catch(() => []);
|
|
4116
|
+
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
4117
|
+
poolBalanceX.set(i, decodeUint256Result(balResults[i * 2] ?? null) ?? 0n);
|
|
4118
|
+
poolBalanceY.set(i, decodeUint256Result(balResults[i * 2 + 1] ?? null) ?? 0n);
|
|
4119
|
+
}
|
|
4120
|
+
}
|
|
4009
4121
|
const results = [];
|
|
4010
4122
|
for (let i = 0; i < rewardedPairs.length; i++) {
|
|
4011
4123
|
const { pool, rewarder } = rewardedPairs[i];
|
|
@@ -4030,18 +4142,25 @@ var MerchantMoeLBAdapter = class {
|
|
|
4030
4142
|
const maxBin = Number(range[1]);
|
|
4031
4143
|
rewardedBins = maxBin - minBin + 1;
|
|
4032
4144
|
if (rxMap && ryMap) {
|
|
4033
|
-
const
|
|
4034
|
-
const
|
|
4035
|
-
const
|
|
4036
|
-
const
|
|
4145
|
+
const priceX2 = getTokenPriceUsd(symX, tokenX);
|
|
4146
|
+
const priceY2 = getTokenPriceUsd(symY, tokenY);
|
|
4147
|
+
const decX2 = getTokenDecimals(symX, tokenX);
|
|
4148
|
+
const decY2 = getTokenDecimals(symY, tokenY);
|
|
4037
4149
|
for (let b = minBin; b <= maxBin; b++) {
|
|
4038
4150
|
const rx = rxMap.get(b) ?? 0n;
|
|
4039
4151
|
const ry = ryMap.get(b) ?? 0n;
|
|
4040
|
-
rangeTvlUsd += Number(rx) / 10 **
|
|
4041
|
-
rangeTvlUsd += Number(ry) / 10 **
|
|
4152
|
+
rangeTvlUsd += Number(rx) / 10 ** decX2 * priceX2;
|
|
4153
|
+
rangeTvlUsd += Number(ry) / 10 ** decY2 * priceY2;
|
|
4042
4154
|
}
|
|
4043
4155
|
}
|
|
4044
4156
|
}
|
|
4157
|
+
const priceX = getTokenPriceUsd(symX, tokenX);
|
|
4158
|
+
const priceY = getTokenPriceUsd(symY, tokenY);
|
|
4159
|
+
const decX = getTokenDecimals(symX, tokenX);
|
|
4160
|
+
const decY = getTokenDecimals(symY, tokenY);
|
|
4161
|
+
const fullBalX = poolBalanceX.get(i) ?? 0n;
|
|
4162
|
+
const fullBalY = poolBalanceY.get(i) ?? 0n;
|
|
4163
|
+
const poolTvlUsd = Number(fullBalX) / 10 ** decX * priceX + Number(fullBalY) / 10 ** decY * priceY;
|
|
4045
4164
|
const aprPercent = rangeTvlUsd > 0 && moePriceUsd > 0 ? poolMoePerDay * moePriceUsd * 365 / rangeTvlUsd * 100 : 0;
|
|
4046
4165
|
results.push({
|
|
4047
4166
|
pool,
|
|
@@ -4058,8 +4177,11 @@ var MerchantMoeLBAdapter = class {
|
|
|
4058
4177
|
isTopPool,
|
|
4059
4178
|
moePerDay: poolMoePerDay,
|
|
4060
4179
|
rangeTvlUsd,
|
|
4180
|
+
poolTvlUsd,
|
|
4061
4181
|
aprPercent,
|
|
4062
|
-
rewardedBins
|
|
4182
|
+
rewardedBins,
|
|
4183
|
+
totalMoePerDay: moePerDay,
|
|
4184
|
+
moePriceUsd
|
|
4063
4185
|
});
|
|
4064
4186
|
}
|
|
4065
4187
|
return results;
|
|
@@ -6083,7 +6205,11 @@ function resolvePoolAddress(registry, protocolSlug, pool) {
|
|
|
6083
6205
|
function registerLP(parent, getOpts, makeExecutor2) {
|
|
6084
6206
|
const lp = parent.command("lp").description("Unified LP operations: discover, add, farm, claim, remove, positions");
|
|
6085
6207
|
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) => {
|
|
6086
|
-
const chainName = parent.opts().chain
|
|
6208
|
+
const chainName = parent.opts().chain;
|
|
6209
|
+
if (!chainName) {
|
|
6210
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6211
|
+
return;
|
|
6212
|
+
}
|
|
6087
6213
|
const registry = Registry.loadEmbedded();
|
|
6088
6214
|
const chain = registry.getChain(chainName);
|
|
6089
6215
|
const rpcUrl = chain.effectiveRpcUrl();
|
|
@@ -6138,7 +6264,13 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
6138
6264
|
moePerDay: p.moePerDay,
|
|
6139
6265
|
aprPercent: p.aprPercent,
|
|
6140
6266
|
rangeTvlUsd: p.rangeTvlUsd,
|
|
6141
|
-
|
|
6267
|
+
poolTvlUsd: p.poolTvlUsd,
|
|
6268
|
+
isTopPool: p.isTopPool,
|
|
6269
|
+
rewardedBins: p.rewardedBins,
|
|
6270
|
+
minBinId: p.minBinId,
|
|
6271
|
+
maxBinId: p.maxBinId,
|
|
6272
|
+
totalMoePerDay: p.totalMoePerDay,
|
|
6273
|
+
moePriceUsd: p.moePriceUsd
|
|
6142
6274
|
});
|
|
6143
6275
|
}
|
|
6144
6276
|
}
|
|
@@ -6155,7 +6287,11 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
6155
6287
|
});
|
|
6156
6288
|
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) => {
|
|
6157
6289
|
const executor = makeExecutor2();
|
|
6158
|
-
const chainName = parent.opts().chain
|
|
6290
|
+
const chainName = parent.opts().chain;
|
|
6291
|
+
if (!chainName) {
|
|
6292
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6293
|
+
return;
|
|
6294
|
+
}
|
|
6159
6295
|
const registry = Registry.loadEmbedded();
|
|
6160
6296
|
const chain = registry.getChain(chainName);
|
|
6161
6297
|
const protocol = registry.getProtocol(opts.protocol);
|
|
@@ -6181,7 +6317,11 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
6181
6317
|
});
|
|
6182
6318
|
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) => {
|
|
6183
6319
|
const executor = makeExecutor2();
|
|
6184
|
-
const chainName = parent.opts().chain
|
|
6320
|
+
const chainName = parent.opts().chain;
|
|
6321
|
+
if (!chainName) {
|
|
6322
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6323
|
+
return;
|
|
6324
|
+
}
|
|
6185
6325
|
const registry = Registry.loadEmbedded();
|
|
6186
6326
|
const chain = registry.getChain(chainName);
|
|
6187
6327
|
const protocol = registry.getProtocol(opts.protocol);
|
|
@@ -6259,7 +6399,11 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
6259
6399
|
});
|
|
6260
6400
|
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) => {
|
|
6261
6401
|
const executor = makeExecutor2();
|
|
6262
|
-
const chainName = parent.opts().chain
|
|
6402
|
+
const chainName = parent.opts().chain;
|
|
6403
|
+
if (!chainName) {
|
|
6404
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6405
|
+
return;
|
|
6406
|
+
}
|
|
6263
6407
|
const registry = Registry.loadEmbedded();
|
|
6264
6408
|
const chain = registry.getChain(chainName);
|
|
6265
6409
|
const rpcUrl = chain.effectiveRpcUrl();
|
|
@@ -6306,7 +6450,11 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
6306
6450
|
});
|
|
6307
6451
|
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) => {
|
|
6308
6452
|
const executor = makeExecutor2();
|
|
6309
|
-
const chainName = parent.opts().chain
|
|
6453
|
+
const chainName = parent.opts().chain;
|
|
6454
|
+
if (!chainName) {
|
|
6455
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6456
|
+
return;
|
|
6457
|
+
}
|
|
6310
6458
|
const registry = Registry.loadEmbedded();
|
|
6311
6459
|
const chain = registry.getChain(chainName);
|
|
6312
6460
|
const rpcUrl = chain.effectiveRpcUrl();
|
|
@@ -6369,7 +6517,11 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
6369
6517
|
printOutput({ step: "lp_remove", ...removeResult }, getOpts());
|
|
6370
6518
|
});
|
|
6371
6519
|
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) => {
|
|
6372
|
-
const chainName = parent.opts().chain
|
|
6520
|
+
const chainName = parent.opts().chain;
|
|
6521
|
+
if (!chainName) {
|
|
6522
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6523
|
+
return;
|
|
6524
|
+
}
|
|
6373
6525
|
const registry = Registry.loadEmbedded();
|
|
6374
6526
|
const chain = registry.getChain(chainName);
|
|
6375
6527
|
const rpcUrl = chain.effectiveRpcUrl();
|
|
@@ -6640,7 +6792,11 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
6640
6792
|
function registerLending(parent, getOpts, makeExecutor2) {
|
|
6641
6793
|
const lending = parent.command("lending").description("Lending operations: supply, borrow, repay, withdraw, rates, position");
|
|
6642
6794
|
lending.command("rates").description("Show current lending rates").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--asset <token>", "Token symbol or address").action(async (opts) => {
|
|
6643
|
-
const chainName = parent.opts().chain
|
|
6795
|
+
const chainName = parent.opts().chain;
|
|
6796
|
+
if (!chainName) {
|
|
6797
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6798
|
+
return;
|
|
6799
|
+
}
|
|
6644
6800
|
const registry = Registry.loadEmbedded();
|
|
6645
6801
|
const chain = registry.getChain(chainName);
|
|
6646
6802
|
const protocol = registry.getProtocol(opts.protocol);
|
|
@@ -6650,7 +6806,11 @@ function registerLending(parent, getOpts, makeExecutor2) {
|
|
|
6650
6806
|
printOutput(rates, getOpts());
|
|
6651
6807
|
});
|
|
6652
6808
|
lending.command("position").description("Show current lending position").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--address <address>", "Wallet address to query").action(async (opts) => {
|
|
6653
|
-
const chainName = parent.opts().chain
|
|
6809
|
+
const chainName = parent.opts().chain;
|
|
6810
|
+
if (!chainName) {
|
|
6811
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6812
|
+
return;
|
|
6813
|
+
}
|
|
6654
6814
|
const registry = Registry.loadEmbedded();
|
|
6655
6815
|
const chain = registry.getChain(chainName);
|
|
6656
6816
|
const protocol = registry.getProtocol(opts.protocol);
|
|
@@ -6660,7 +6820,11 @@ function registerLending(parent, getOpts, makeExecutor2) {
|
|
|
6660
6820
|
});
|
|
6661
6821
|
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) => {
|
|
6662
6822
|
const executor = makeExecutor2();
|
|
6663
|
-
const chainName = parent.opts().chain
|
|
6823
|
+
const chainName = parent.opts().chain;
|
|
6824
|
+
if (!chainName) {
|
|
6825
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6826
|
+
return;
|
|
6827
|
+
}
|
|
6664
6828
|
const registry = Registry.loadEmbedded();
|
|
6665
6829
|
const chain = registry.getChain(chainName);
|
|
6666
6830
|
const protocol = registry.getProtocol(opts.protocol);
|
|
@@ -6673,7 +6837,11 @@ function registerLending(parent, getOpts, makeExecutor2) {
|
|
|
6673
6837
|
});
|
|
6674
6838
|
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) => {
|
|
6675
6839
|
const executor = makeExecutor2();
|
|
6676
|
-
const chainName = parent.opts().chain
|
|
6840
|
+
const chainName = parent.opts().chain;
|
|
6841
|
+
if (!chainName) {
|
|
6842
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6843
|
+
return;
|
|
6844
|
+
}
|
|
6677
6845
|
const registry = Registry.loadEmbedded();
|
|
6678
6846
|
const chain = registry.getChain(chainName);
|
|
6679
6847
|
const protocol = registry.getProtocol(opts.protocol);
|
|
@@ -6692,7 +6860,11 @@ function registerLending(parent, getOpts, makeExecutor2) {
|
|
|
6692
6860
|
});
|
|
6693
6861
|
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) => {
|
|
6694
6862
|
const executor = makeExecutor2();
|
|
6695
|
-
const chainName = parent.opts().chain
|
|
6863
|
+
const chainName = parent.opts().chain;
|
|
6864
|
+
if (!chainName) {
|
|
6865
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6866
|
+
return;
|
|
6867
|
+
}
|
|
6696
6868
|
const registry = Registry.loadEmbedded();
|
|
6697
6869
|
const chain = registry.getChain(chainName);
|
|
6698
6870
|
const protocol = registry.getProtocol(opts.protocol);
|
|
@@ -6711,7 +6883,11 @@ function registerLending(parent, getOpts, makeExecutor2) {
|
|
|
6711
6883
|
});
|
|
6712
6884
|
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) => {
|
|
6713
6885
|
const executor = makeExecutor2();
|
|
6714
|
-
const chainName = parent.opts().chain
|
|
6886
|
+
const chainName = parent.opts().chain;
|
|
6887
|
+
if (!chainName) {
|
|
6888
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
6889
|
+
return;
|
|
6890
|
+
}
|
|
6715
6891
|
const registry = Registry.loadEmbedded();
|
|
6716
6892
|
const chain = registry.getChain(chainName);
|
|
6717
6893
|
const protocol = registry.getProtocol(opts.protocol);
|
|
@@ -6939,8 +7115,10 @@ function registerYield(parent, getOpts, makeExecutor2) {
|
|
|
6939
7115
|
try {
|
|
6940
7116
|
const registry = Registry.loadEmbedded();
|
|
6941
7117
|
const asset = opts.asset;
|
|
7118
|
+
const specifiedChain = parent.opts().chain;
|
|
7119
|
+
const chainKeys = specifiedChain ? [specifiedChain.toLowerCase()] : Array.from(registry.chains.keys());
|
|
6942
7120
|
const allRates = [];
|
|
6943
|
-
for (const
|
|
7121
|
+
for (const chainKey of chainKeys) {
|
|
6944
7122
|
try {
|
|
6945
7123
|
const chain = registry.getChain(chainKey);
|
|
6946
7124
|
const rpc = chain.effectiveRpcUrl();
|
|
@@ -6969,7 +7147,12 @@ function registerYield(parent, getOpts, makeExecutor2) {
|
|
|
6969
7147
|
yieldCmd.command("compare").description("Compare lending rates across protocols for an asset").option("--asset <token>", "Token symbol or address", "USDC").action(async (opts) => {
|
|
6970
7148
|
try {
|
|
6971
7149
|
const registry = Registry.loadEmbedded();
|
|
6972
|
-
const
|
|
7150
|
+
const specChain = parent.opts().chain;
|
|
7151
|
+
if (!specChain) {
|
|
7152
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
7153
|
+
return;
|
|
7154
|
+
}
|
|
7155
|
+
const chainName = specChain.toLowerCase();
|
|
6973
7156
|
const chain = registry.getChain(chainName);
|
|
6974
7157
|
const rpc = chain.effectiveRpcUrl();
|
|
6975
7158
|
const assetAddr = resolveAsset(registry, chainName, opts.asset);
|
|
@@ -7205,7 +7388,12 @@ function registerYield(parent, getOpts, makeExecutor2) {
|
|
|
7205
7388
|
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) => {
|
|
7206
7389
|
try {
|
|
7207
7390
|
const registry = Registry.loadEmbedded();
|
|
7208
|
-
const
|
|
7391
|
+
const specChain = parent.opts().chain;
|
|
7392
|
+
if (!specChain) {
|
|
7393
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
7394
|
+
return;
|
|
7395
|
+
}
|
|
7396
|
+
const chainName = specChain.toLowerCase();
|
|
7209
7397
|
const chain = registry.getChain(chainName);
|
|
7210
7398
|
const rpc = chain.effectiveRpcUrl();
|
|
7211
7399
|
const asset = opts.asset;
|
|
@@ -7551,7 +7739,12 @@ function registerPortfolio(parent, getOpts) {
|
|
|
7551
7739
|
portfolio.command("show").description("Show current portfolio positions").requiredOption("--address <address>", "Wallet address to query").action(async (opts) => {
|
|
7552
7740
|
const mode = getOpts();
|
|
7553
7741
|
const registry = Registry.loadEmbedded();
|
|
7554
|
-
const
|
|
7742
|
+
const _chain = parent.opts().chain;
|
|
7743
|
+
if (!_chain) {
|
|
7744
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
7745
|
+
return;
|
|
7746
|
+
}
|
|
7747
|
+
const chainName = _chain.toLowerCase();
|
|
7555
7748
|
let chain;
|
|
7556
7749
|
try {
|
|
7557
7750
|
chain = registry.getChain(chainName);
|
|
@@ -7689,7 +7882,12 @@ function registerPortfolio(parent, getOpts) {
|
|
|
7689
7882
|
});
|
|
7690
7883
|
portfolio.command("snapshot").description("Take a new portfolio snapshot and save it locally").requiredOption("--address <address>", "Wallet address to snapshot").action(async (opts) => {
|
|
7691
7884
|
const mode = getOpts();
|
|
7692
|
-
const
|
|
7885
|
+
const _chain = parent.opts().chain;
|
|
7886
|
+
if (!_chain) {
|
|
7887
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
7888
|
+
return;
|
|
7889
|
+
}
|
|
7890
|
+
const chainName = _chain.toLowerCase();
|
|
7693
7891
|
const registry = Registry.loadEmbedded();
|
|
7694
7892
|
if (!/^0x[0-9a-fA-F]{40}$/.test(opts.address)) {
|
|
7695
7893
|
printOutput({ error: `Invalid address: ${opts.address}` }, mode);
|
|
@@ -7716,7 +7914,12 @@ function registerPortfolio(parent, getOpts) {
|
|
|
7716
7914
|
});
|
|
7717
7915
|
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) => {
|
|
7718
7916
|
const mode = getOpts();
|
|
7719
|
-
const
|
|
7917
|
+
const _chain = parent.opts().chain;
|
|
7918
|
+
if (!_chain) {
|
|
7919
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
7920
|
+
return;
|
|
7921
|
+
}
|
|
7922
|
+
const chainName = _chain.toLowerCase();
|
|
7720
7923
|
const registry = Registry.loadEmbedded();
|
|
7721
7924
|
if (!/^0x[0-9a-fA-F]{40}$/.test(opts.address)) {
|
|
7722
7925
|
printOutput({ error: `Invalid address: ${opts.address}` }, mode);
|
|
@@ -7761,7 +7964,12 @@ function registerPortfolio(parent, getOpts) {
|
|
|
7761
7964
|
});
|
|
7762
7965
|
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) => {
|
|
7763
7966
|
const mode = getOpts();
|
|
7764
|
-
const
|
|
7967
|
+
const _chain = parent.opts().chain;
|
|
7968
|
+
if (!_chain) {
|
|
7969
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
7970
|
+
return;
|
|
7971
|
+
}
|
|
7972
|
+
const chainName = _chain.toLowerCase();
|
|
7765
7973
|
if (!/^0x[0-9a-fA-F]{40}$/.test(opts.address)) {
|
|
7766
7974
|
printOutput({ error: `Invalid address: ${opts.address}` }, mode);
|
|
7767
7975
|
return;
|
|
@@ -7800,7 +8008,12 @@ function registerPrice(parent, getOpts) {
|
|
|
7800
8008
|
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) => {
|
|
7801
8009
|
const mode = getOpts();
|
|
7802
8010
|
const registry = Registry.loadEmbedded();
|
|
7803
|
-
const
|
|
8011
|
+
const _chain = parent.opts().chain;
|
|
8012
|
+
if (!_chain) {
|
|
8013
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
8014
|
+
return;
|
|
8015
|
+
}
|
|
8016
|
+
const chainName = _chain.toLowerCase();
|
|
7804
8017
|
let chain;
|
|
7805
8018
|
try {
|
|
7806
8019
|
chain = registry.getChain(chainName);
|
|
@@ -7927,7 +8140,11 @@ import { createPublicClient as createPublicClient23, http as http23, formatEther
|
|
|
7927
8140
|
function registerWallet(parent, getOpts) {
|
|
7928
8141
|
const wallet = parent.command("wallet").description("Wallet management");
|
|
7929
8142
|
wallet.command("balance").description("Show native token balance").requiredOption("--address <address>", "Wallet address to query").action(async (opts) => {
|
|
7930
|
-
const chainName = parent.opts().chain
|
|
8143
|
+
const chainName = parent.opts().chain;
|
|
8144
|
+
if (!chainName) {
|
|
8145
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
8146
|
+
return;
|
|
8147
|
+
}
|
|
7931
8148
|
const registry = Registry.loadEmbedded();
|
|
7932
8149
|
const chain = registry.getChain(chainName);
|
|
7933
8150
|
const client = createPublicClient23({ transport: http23(chain.effectiveRpcUrl()) });
|
|
@@ -7951,7 +8168,11 @@ import { createPublicClient as createPublicClient24, http as http24, maxUint256
|
|
|
7951
8168
|
function registerToken(parent, getOpts, makeExecutor2) {
|
|
7952
8169
|
const token = parent.command("token").description("Token operations: approve, allowance, transfer, balance");
|
|
7953
8170
|
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) => {
|
|
7954
|
-
const chainName = parent.opts().chain
|
|
8171
|
+
const chainName = parent.opts().chain;
|
|
8172
|
+
if (!chainName) {
|
|
8173
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
8174
|
+
return;
|
|
8175
|
+
}
|
|
7955
8176
|
const registry = Registry.loadEmbedded();
|
|
7956
8177
|
const chain = registry.getChain(chainName);
|
|
7957
8178
|
const client = createPublicClient24({ transport: http24(chain.effectiveRpcUrl()) });
|
|
@@ -7971,7 +8192,11 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
7971
8192
|
});
|
|
7972
8193
|
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) => {
|
|
7973
8194
|
const executor = makeExecutor2();
|
|
7974
|
-
const chainName = parent.opts().chain
|
|
8195
|
+
const chainName = parent.opts().chain;
|
|
8196
|
+
if (!chainName) {
|
|
8197
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
8198
|
+
return;
|
|
8199
|
+
}
|
|
7975
8200
|
const registry = Registry.loadEmbedded();
|
|
7976
8201
|
const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
|
|
7977
8202
|
const amount = opts.amount === "max" ? maxUint256 : BigInt(opts.amount);
|
|
@@ -7980,7 +8205,11 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
7980
8205
|
printOutput(result, getOpts());
|
|
7981
8206
|
});
|
|
7982
8207
|
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) => {
|
|
7983
|
-
const chainName = parent.opts().chain
|
|
8208
|
+
const chainName = parent.opts().chain;
|
|
8209
|
+
if (!chainName) {
|
|
8210
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
8211
|
+
return;
|
|
8212
|
+
}
|
|
7984
8213
|
const registry = Registry.loadEmbedded();
|
|
7985
8214
|
const chain = registry.getChain(chainName);
|
|
7986
8215
|
const client = createPublicClient24({ transport: http24(chain.effectiveRpcUrl()) });
|
|
@@ -7995,7 +8224,11 @@ function registerToken(parent, getOpts, makeExecutor2) {
|
|
|
7995
8224
|
});
|
|
7996
8225
|
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) => {
|
|
7997
8226
|
const executor = makeExecutor2();
|
|
7998
|
-
const chainName = parent.opts().chain
|
|
8227
|
+
const chainName = parent.opts().chain;
|
|
8228
|
+
if (!chainName) {
|
|
8229
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
8230
|
+
return;
|
|
8231
|
+
}
|
|
7999
8232
|
const registry = Registry.loadEmbedded();
|
|
8000
8233
|
const tokenAddr = opts.token.startsWith("0x") ? opts.token : registry.resolveToken(chainName, opts.token).address;
|
|
8001
8234
|
const tx = buildTransfer(tokenAddr, opts.to, BigInt(opts.amount));
|
|
@@ -8102,7 +8335,11 @@ async function getCctpFeeEstimate(srcDomain, dstDomain, amountUsdc) {
|
|
|
8102
8335
|
}
|
|
8103
8336
|
function registerBridge(parent, getOpts) {
|
|
8104
8337
|
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) => {
|
|
8105
|
-
const chainName = parent.opts().chain
|
|
8338
|
+
const chainName = parent.opts().chain;
|
|
8339
|
+
if (!chainName) {
|
|
8340
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
8341
|
+
return;
|
|
8342
|
+
}
|
|
8106
8343
|
const registry = Registry.loadEmbedded();
|
|
8107
8344
|
const fromChain = registry.getChain(chainName);
|
|
8108
8345
|
const toChain = registry.getChain(opts.toChain);
|
|
@@ -8306,7 +8543,11 @@ async function liquidSwapRoute(tokenIn, tokenOut, amountIn, slippagePct) {
|
|
|
8306
8543
|
function registerSwap(parent, getOpts, makeExecutor2) {
|
|
8307
8544
|
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) => {
|
|
8308
8545
|
const executor = makeExecutor2();
|
|
8309
|
-
const chainName = parent.opts().chain
|
|
8546
|
+
const chainName = parent.opts().chain;
|
|
8547
|
+
if (!chainName) {
|
|
8548
|
+
printOutput({ error: "--chain is required (e.g. --chain hyperevm)" }, getOpts());
|
|
8549
|
+
return;
|
|
8550
|
+
}
|
|
8310
8551
|
const registry = Registry.loadEmbedded();
|
|
8311
8552
|
const provider = opts.provider.toLowerCase();
|
|
8312
8553
|
const slippageBps = parseInt(opts.slippage, 10);
|
|
@@ -8592,7 +8833,7 @@ var BANNER = `
|
|
|
8592
8833
|
Lending, LP farming, DEX swap, yield comparison
|
|
8593
8834
|
\u2014 all from your terminal.
|
|
8594
8835
|
`;
|
|
8595
|
-
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"
|
|
8836
|
+
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");
|
|
8596
8837
|
function getOutputMode() {
|
|
8597
8838
|
const opts = program.opts();
|
|
8598
8839
|
return parseOutputMode(opts);
|
|
@@ -8600,7 +8841,11 @@ function getOutputMode() {
|
|
|
8600
8841
|
function makeExecutor() {
|
|
8601
8842
|
const opts = program.opts();
|
|
8602
8843
|
const registry = Registry.loadEmbedded();
|
|
8603
|
-
|
|
8844
|
+
if (!opts.chain) {
|
|
8845
|
+
process.stderr.write("Error: --chain is required for this command (e.g. --chain hyperevm)\n");
|
|
8846
|
+
process.exit(1);
|
|
8847
|
+
}
|
|
8848
|
+
const chain = registry.getChain(opts.chain);
|
|
8604
8849
|
return new Executor(!!opts.broadcast, chain.effectiveRpcUrl(), chain.explorer_url);
|
|
8605
8850
|
}
|
|
8606
8851
|
registerStatus(program, getOutputMode);
|