@hypurrquant/defi-cli 0.3.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +313 -1190
- package/dist/index.js.map +1 -1
- package/dist/main.js +314 -1200
- package/dist/main.js.map +1 -1
- package/dist/mcp-server.js +4 -4
- package/dist/mcp-server.js.map +1 -1
- package/package.json +1 -1
- package/config/protocols/lending/euler.toml +0 -20
- package/config/protocols/lending/hyperyield_hyperevm.toml +0 -14
- package/config/protocols/lending/primefi_hyperevm.toml +0 -13
- package/config/protocols/lending/purrlend_hyperevm.toml +0 -14
package/dist/main.js
CHANGED
|
@@ -1212,7 +1212,7 @@ var Executor = class _Executor {
|
|
|
1212
1212
|
const [maxFee, priorityFee] = await this.fetchEip1559Fees(rpcUrl);
|
|
1213
1213
|
return {
|
|
1214
1214
|
tx_hash: void 0,
|
|
1215
|
-
status:
|
|
1215
|
+
status: TxStatus.Simulated,
|
|
1216
1216
|
gas_used: gasEstimate > 0n ? Number(gasEstimate) : void 0,
|
|
1217
1217
|
description: tx.description,
|
|
1218
1218
|
details: {
|
|
@@ -1232,7 +1232,7 @@ var Executor = class _Executor {
|
|
|
1232
1232
|
const revertReason = extractRevertReason(errMsg);
|
|
1233
1233
|
return {
|
|
1234
1234
|
tx_hash: void 0,
|
|
1235
|
-
status:
|
|
1235
|
+
status: TxStatus.SimulationFailed,
|
|
1236
1236
|
gas_used: tx.gas_estimate,
|
|
1237
1237
|
description: tx.description,
|
|
1238
1238
|
details: {
|
|
@@ -1254,7 +1254,7 @@ var Executor = class _Executor {
|
|
|
1254
1254
|
}
|
|
1255
1255
|
return {
|
|
1256
1256
|
tx_hash: void 0,
|
|
1257
|
-
status:
|
|
1257
|
+
status: TxStatus.DryRun,
|
|
1258
1258
|
gas_used: tx.gas_estimate,
|
|
1259
1259
|
description: tx.description,
|
|
1260
1260
|
details: {
|
|
@@ -1339,7 +1339,7 @@ var Executor = class _Executor {
|
|
|
1339
1339
|
`);
|
|
1340
1340
|
process.stderr.write("Waiting for confirmation...\n");
|
|
1341
1341
|
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
1342
|
-
const status = receipt.status === "success" ?
|
|
1342
|
+
const status = receipt.status === "success" ? TxStatus.Confirmed : TxStatus.Failed;
|
|
1343
1343
|
let mintedTokenId;
|
|
1344
1344
|
if (receipt.status === "success" && receipt.logs) {
|
|
1345
1345
|
const TRANSFER_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
|
|
@@ -1907,6 +1907,9 @@ function registerSchema(parent, getOpts) {
|
|
|
1907
1907
|
});
|
|
1908
1908
|
}
|
|
1909
1909
|
|
|
1910
|
+
// src/commands/lp.ts
|
|
1911
|
+
import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
1912
|
+
|
|
1910
1913
|
// ../defi-protocols/dist/index.js
|
|
1911
1914
|
import { encodeFunctionData as encodeFunctionData4, parseAbi as parseAbi4, createPublicClient as createPublicClient4, http as http4, decodeAbiParameters } from "viem";
|
|
1912
1915
|
import { encodeFunctionData as encodeFunctionData22, parseAbi as parseAbi22, createPublicClient as createPublicClient22, http as http22, decodeFunctionResult as decodeFunctionResult2, decodeAbiParameters as decodeAbiParameters2 } from "viem";
|
|
@@ -4095,128 +4098,6 @@ var masterchefAbi = parseAbi11([
|
|
|
4095
4098
|
"function getNumberOfFarms() view returns (uint256)",
|
|
4096
4099
|
"function getPidByPool(address pool) view returns (uint256)"
|
|
4097
4100
|
]);
|
|
4098
|
-
var MasterChefAdapter = class {
|
|
4099
|
-
protocolName;
|
|
4100
|
-
masterchef;
|
|
4101
|
-
rpcUrl;
|
|
4102
|
-
constructor(entry, rpcUrl) {
|
|
4103
|
-
this.protocolName = entry.name;
|
|
4104
|
-
const masterchef = entry.contracts?.["masterchef"];
|
|
4105
|
-
if (!masterchef) {
|
|
4106
|
-
throw new DefiError("CONTRACT_ERROR", "Missing 'masterchef' contract");
|
|
4107
|
-
}
|
|
4108
|
-
this.masterchef = masterchef;
|
|
4109
|
-
this.rpcUrl = rpcUrl;
|
|
4110
|
-
}
|
|
4111
|
-
name() {
|
|
4112
|
-
return this.protocolName;
|
|
4113
|
-
}
|
|
4114
|
-
/**
|
|
4115
|
-
* Deposit LP tokens into a MasterChef farm.
|
|
4116
|
-
* `gauge` is the pool address (unused for calldata — MasterChef is the target).
|
|
4117
|
-
* `tokenId` carries the farm pid.
|
|
4118
|
-
*/
|
|
4119
|
-
async buildDeposit(gauge, amount, tokenId) {
|
|
4120
|
-
const pid = tokenId ?? 0n;
|
|
4121
|
-
const data = encodeFunctionData11({
|
|
4122
|
-
abi: masterchefAbi,
|
|
4123
|
-
functionName: "deposit",
|
|
4124
|
-
args: [pid, amount]
|
|
4125
|
-
});
|
|
4126
|
-
return {
|
|
4127
|
-
description: `[${this.protocolName}] Deposit ${amount} LP to farm pid=${pid} (pool ${gauge})`,
|
|
4128
|
-
to: this.masterchef,
|
|
4129
|
-
data,
|
|
4130
|
-
value: 0n,
|
|
4131
|
-
gas_estimate: 2e5
|
|
4132
|
-
};
|
|
4133
|
-
}
|
|
4134
|
-
/**
|
|
4135
|
-
* Withdraw LP tokens from a MasterChef farm.
|
|
4136
|
-
* `gauge` is used to look up the pid description only; call site should pass pid via tokenId
|
|
4137
|
-
* on the deposit flow. Here pid defaults to 0 — callers should encode the pid in the gauge
|
|
4138
|
-
* address slot or wrap this adapter with a pid-aware helper.
|
|
4139
|
-
*/
|
|
4140
|
-
async buildWithdraw(gauge, amount) {
|
|
4141
|
-
const pid = 0n;
|
|
4142
|
-
const data = encodeFunctionData11({
|
|
4143
|
-
abi: masterchefAbi,
|
|
4144
|
-
functionName: "withdraw",
|
|
4145
|
-
args: [pid, amount]
|
|
4146
|
-
});
|
|
4147
|
-
return {
|
|
4148
|
-
description: `[${this.protocolName}] Withdraw ${amount} LP from farm pid=${pid} (pool ${gauge})`,
|
|
4149
|
-
to: this.masterchef,
|
|
4150
|
-
data,
|
|
4151
|
-
value: 0n,
|
|
4152
|
-
gas_estimate: 2e5
|
|
4153
|
-
};
|
|
4154
|
-
}
|
|
4155
|
-
/** Withdraw LP tokens specifying a pid explicitly (MasterChef extension beyond IGauge). */
|
|
4156
|
-
async buildWithdrawPid(pid, amount) {
|
|
4157
|
-
const data = encodeFunctionData11({
|
|
4158
|
-
abi: masterchefAbi,
|
|
4159
|
-
functionName: "withdraw",
|
|
4160
|
-
args: [pid, amount]
|
|
4161
|
-
});
|
|
4162
|
-
return {
|
|
4163
|
-
description: `[${this.protocolName}] Withdraw ${amount} LP from farm pid=${pid}`,
|
|
4164
|
-
to: this.masterchef,
|
|
4165
|
-
data,
|
|
4166
|
-
value: 0n,
|
|
4167
|
-
gas_estimate: 2e5
|
|
4168
|
-
};
|
|
4169
|
-
}
|
|
4170
|
-
/** Claim pending MOE rewards. IGauge interface provides no pid — defaults to pid=0. */
|
|
4171
|
-
async buildClaimRewards(gauge) {
|
|
4172
|
-
const pid = 0n;
|
|
4173
|
-
const data = encodeFunctionData11({
|
|
4174
|
-
abi: masterchefAbi,
|
|
4175
|
-
functionName: "claim",
|
|
4176
|
-
args: [[pid]]
|
|
4177
|
-
});
|
|
4178
|
-
return {
|
|
4179
|
-
description: `[${this.protocolName}] Claim MOE rewards for farm pid=${pid} (pool ${gauge})`,
|
|
4180
|
-
to: this.masterchef,
|
|
4181
|
-
data,
|
|
4182
|
-
value: 0n,
|
|
4183
|
-
gas_estimate: 2e5
|
|
4184
|
-
};
|
|
4185
|
-
}
|
|
4186
|
-
/** Claim pending MOE rewards for a specific pid (MasterChef extension beyond IGauge). */
|
|
4187
|
-
async buildClaimRewardsPid(pid) {
|
|
4188
|
-
const data = encodeFunctionData11({
|
|
4189
|
-
abi: masterchefAbi,
|
|
4190
|
-
functionName: "claim",
|
|
4191
|
-
args: [[pid]]
|
|
4192
|
-
});
|
|
4193
|
-
return {
|
|
4194
|
-
description: `[${this.protocolName}] Claim MOE rewards for farm pid=${pid}`,
|
|
4195
|
-
to: this.masterchef,
|
|
4196
|
-
data,
|
|
4197
|
-
value: 0n,
|
|
4198
|
-
gas_estimate: 2e5
|
|
4199
|
-
};
|
|
4200
|
-
}
|
|
4201
|
-
/** Get pending MOE rewards for a user. Requires rpcUrl. */
|
|
4202
|
-
async getPendingRewards(_gauge, user) {
|
|
4203
|
-
if (!this.rpcUrl) {
|
|
4204
|
-
throw DefiError.unsupported(`[${this.protocolName}] getPendingRewards requires RPC`);
|
|
4205
|
-
}
|
|
4206
|
-
const client = createPublicClient7({ transport: http7(this.rpcUrl) });
|
|
4207
|
-
const rewards = await client.readContract({
|
|
4208
|
-
address: this.masterchef,
|
|
4209
|
-
abi: masterchefAbi,
|
|
4210
|
-
functionName: "pendingRewards",
|
|
4211
|
-
args: [user, [0n]]
|
|
4212
|
-
});
|
|
4213
|
-
return rewards.map((amount) => ({
|
|
4214
|
-
token: this.masterchef,
|
|
4215
|
-
symbol: "MOE",
|
|
4216
|
-
amount
|
|
4217
|
-
}));
|
|
4218
|
-
}
|
|
4219
|
-
};
|
|
4220
4101
|
var lbRouterAbi = parseAbi12([
|
|
4221
4102
|
"struct LiquidityParameters { address tokenX; address tokenY; uint256 binStep; uint256 amountX; uint256 amountY; uint256 amountXMin; uint256 amountYMin; uint256 activeIdDesired; uint256 idSlippage; int256[] deltaIds; uint256[] distributionX; uint256[] distributionY; address to; address refundTo; uint256 deadline; }",
|
|
4222
4103
|
"function addLiquidity(LiquidityParameters calldata liquidityParameters) external returns (uint256 amountXAdded, uint256 amountYAdded, uint256 amountXLeft, uint256 amountYLeft, uint256[] memory depositIds, uint256[] memory liquidityMinted)",
|
|
@@ -6838,46 +6719,6 @@ var GENERIC_LST_ABI = parseAbi24([
|
|
|
6838
6719
|
"function stake() external payable returns (uint256)",
|
|
6839
6720
|
"function unstake(uint256 amount) external returns (uint256)"
|
|
6840
6721
|
]);
|
|
6841
|
-
var GenericLstAdapter = class {
|
|
6842
|
-
protocolName;
|
|
6843
|
-
staking;
|
|
6844
|
-
constructor(entry, _rpcUrl) {
|
|
6845
|
-
this.protocolName = entry.name;
|
|
6846
|
-
const staking = entry.contracts?.["staking"];
|
|
6847
|
-
if (!staking) throw DefiError.contractError("Missing 'staking' contract");
|
|
6848
|
-
this.staking = staking;
|
|
6849
|
-
}
|
|
6850
|
-
name() {
|
|
6851
|
-
return this.protocolName;
|
|
6852
|
-
}
|
|
6853
|
-
async buildStake(params) {
|
|
6854
|
-
const data = encodeFunctionData222({ abi: GENERIC_LST_ABI, functionName: "stake" });
|
|
6855
|
-
return {
|
|
6856
|
-
description: `[${this.protocolName}] Stake ${params.amount} HYPE`,
|
|
6857
|
-
to: this.staking,
|
|
6858
|
-
data,
|
|
6859
|
-
value: params.amount,
|
|
6860
|
-
gas_estimate: 2e5
|
|
6861
|
-
};
|
|
6862
|
-
}
|
|
6863
|
-
async buildUnstake(params) {
|
|
6864
|
-
const data = encodeFunctionData222({
|
|
6865
|
-
abi: GENERIC_LST_ABI,
|
|
6866
|
-
functionName: "unstake",
|
|
6867
|
-
args: [params.amount]
|
|
6868
|
-
});
|
|
6869
|
-
return {
|
|
6870
|
-
description: `[${this.protocolName}] Unstake ${params.amount}`,
|
|
6871
|
-
to: this.staking,
|
|
6872
|
-
data,
|
|
6873
|
-
value: 0n,
|
|
6874
|
-
gas_estimate: 2e5
|
|
6875
|
-
};
|
|
6876
|
-
}
|
|
6877
|
-
async getInfo() {
|
|
6878
|
-
throw DefiError.unsupported(`[${this.protocolName}] getInfo requires RPC`);
|
|
6879
|
-
}
|
|
6880
|
-
};
|
|
6881
6722
|
var STHYPE_ABI = parseAbi25([
|
|
6882
6723
|
"function submit(address referral) external payable returns (uint256)",
|
|
6883
6724
|
"function requestWithdrawals(uint256[] amounts, address owner) external returns (uint256[] requestIds)"
|
|
@@ -6885,70 +6726,6 @@ var STHYPE_ABI = parseAbi25([
|
|
|
6885
6726
|
var ERC20_ABI3 = parseAbi25([
|
|
6886
6727
|
"function totalSupply() external view returns (uint256)"
|
|
6887
6728
|
]);
|
|
6888
|
-
var StHypeAdapter = class {
|
|
6889
|
-
protocolName;
|
|
6890
|
-
staking;
|
|
6891
|
-
sthypeToken;
|
|
6892
|
-
rpcUrl;
|
|
6893
|
-
constructor(entry, rpcUrl) {
|
|
6894
|
-
this.protocolName = entry.name;
|
|
6895
|
-
this.rpcUrl = rpcUrl;
|
|
6896
|
-
const staking = entry.contracts?.["staking"];
|
|
6897
|
-
if (!staking) throw DefiError.contractError("Missing 'staking' contract");
|
|
6898
|
-
this.staking = staking;
|
|
6899
|
-
this.sthypeToken = entry.contracts?.["sthype_token"];
|
|
6900
|
-
}
|
|
6901
|
-
name() {
|
|
6902
|
-
return this.protocolName;
|
|
6903
|
-
}
|
|
6904
|
-
async buildStake(params) {
|
|
6905
|
-
const data = encodeFunctionData23({
|
|
6906
|
-
abi: STHYPE_ABI,
|
|
6907
|
-
functionName: "submit",
|
|
6908
|
-
args: [zeroAddress12]
|
|
6909
|
-
});
|
|
6910
|
-
return {
|
|
6911
|
-
description: `[${this.protocolName}] Stake ${params.amount} HYPE for stHYPE`,
|
|
6912
|
-
to: this.staking,
|
|
6913
|
-
data,
|
|
6914
|
-
value: params.amount,
|
|
6915
|
-
gas_estimate: 2e5
|
|
6916
|
-
};
|
|
6917
|
-
}
|
|
6918
|
-
async buildUnstake(params) {
|
|
6919
|
-
const data = encodeFunctionData23({
|
|
6920
|
-
abi: STHYPE_ABI,
|
|
6921
|
-
functionName: "requestWithdrawals",
|
|
6922
|
-
args: [[params.amount], params.recipient]
|
|
6923
|
-
});
|
|
6924
|
-
return {
|
|
6925
|
-
description: `[${this.protocolName}] Request unstake ${params.amount} stHYPE`,
|
|
6926
|
-
to: this.staking,
|
|
6927
|
-
data,
|
|
6928
|
-
value: 0n,
|
|
6929
|
-
gas_estimate: 2e5
|
|
6930
|
-
};
|
|
6931
|
-
}
|
|
6932
|
-
async getInfo() {
|
|
6933
|
-
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
6934
|
-
const client = createPublicClient19({ transport: http19(this.rpcUrl) });
|
|
6935
|
-
const tokenAddr = this.sthypeToken ?? this.staking;
|
|
6936
|
-
const totalSupply = await client.readContract({
|
|
6937
|
-
address: tokenAddr,
|
|
6938
|
-
abi: ERC20_ABI3,
|
|
6939
|
-
functionName: "totalSupply"
|
|
6940
|
-
}).catch((e) => {
|
|
6941
|
-
throw DefiError.rpcError(`[${this.protocolName}] totalSupply failed: ${e}`);
|
|
6942
|
-
});
|
|
6943
|
-
return {
|
|
6944
|
-
protocol: this.protocolName,
|
|
6945
|
-
staked_token: zeroAddress12,
|
|
6946
|
-
liquid_token: tokenAddr,
|
|
6947
|
-
exchange_rate: 1,
|
|
6948
|
-
total_staked: totalSupply
|
|
6949
|
-
};
|
|
6950
|
-
}
|
|
6951
|
-
};
|
|
6952
6729
|
var KINETIQ_ABI = parseAbi26([
|
|
6953
6730
|
"function stake() external payable returns (uint256)",
|
|
6954
6731
|
"function requestUnstake(uint256 amount) external returns (uint256)",
|
|
@@ -6957,72 +6734,6 @@ var KINETIQ_ABI = parseAbi26([
|
|
|
6957
6734
|
var ORACLE_ABI3 = parseAbi26([
|
|
6958
6735
|
"function getAssetPrice(address asset) external view returns (uint256)"
|
|
6959
6736
|
]);
|
|
6960
|
-
var WHYPE = "0x5555555555555555555555555555555555555555";
|
|
6961
|
-
var HYPERLEND_ORACLE = "0xc9fb4fbe842d57ea1df3e641a281827493a63030";
|
|
6962
|
-
var KinetiqAdapter = class {
|
|
6963
|
-
protocolName;
|
|
6964
|
-
staking;
|
|
6965
|
-
liquidToken;
|
|
6966
|
-
rpcUrl;
|
|
6967
|
-
constructor(entry, rpcUrl) {
|
|
6968
|
-
this.protocolName = entry.name;
|
|
6969
|
-
this.rpcUrl = rpcUrl;
|
|
6970
|
-
const staking = entry.contracts?.["staking"];
|
|
6971
|
-
if (!staking) throw DefiError.contractError("Missing 'staking' contract address");
|
|
6972
|
-
this.staking = staking;
|
|
6973
|
-
this.liquidToken = entry.contracts?.["khype_token"] ?? staking;
|
|
6974
|
-
}
|
|
6975
|
-
name() {
|
|
6976
|
-
return this.protocolName;
|
|
6977
|
-
}
|
|
6978
|
-
async buildStake(params) {
|
|
6979
|
-
const data = encodeFunctionData24({ abi: KINETIQ_ABI, functionName: "stake" });
|
|
6980
|
-
return {
|
|
6981
|
-
description: `[${this.protocolName}] Stake ${params.amount} HYPE for kHYPE`,
|
|
6982
|
-
to: this.staking,
|
|
6983
|
-
data,
|
|
6984
|
-
value: params.amount,
|
|
6985
|
-
gas_estimate: 3e5
|
|
6986
|
-
};
|
|
6987
|
-
}
|
|
6988
|
-
async buildUnstake(params) {
|
|
6989
|
-
const data = encodeFunctionData24({
|
|
6990
|
-
abi: KINETIQ_ABI,
|
|
6991
|
-
functionName: "requestUnstake",
|
|
6992
|
-
args: [params.amount]
|
|
6993
|
-
});
|
|
6994
|
-
return {
|
|
6995
|
-
description: `[${this.protocolName}] Request unstake ${params.amount} kHYPE`,
|
|
6996
|
-
to: this.staking,
|
|
6997
|
-
data,
|
|
6998
|
-
value: 0n,
|
|
6999
|
-
gas_estimate: 3e5
|
|
7000
|
-
};
|
|
7001
|
-
}
|
|
7002
|
-
async getInfo() {
|
|
7003
|
-
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
7004
|
-
const client = createPublicClient20({ transport: http20(this.rpcUrl) });
|
|
7005
|
-
const totalStaked = await client.readContract({
|
|
7006
|
-
address: this.staking,
|
|
7007
|
-
abi: KINETIQ_ABI,
|
|
7008
|
-
functionName: "totalStaked"
|
|
7009
|
-
}).catch((e) => {
|
|
7010
|
-
throw DefiError.rpcError(`[${this.protocolName}] totalStaked failed: ${e}`);
|
|
7011
|
-
});
|
|
7012
|
-
const [khypePrice, hypePrice] = await Promise.all([
|
|
7013
|
-
client.readContract({ address: HYPERLEND_ORACLE, abi: ORACLE_ABI3, functionName: "getAssetPrice", args: [this.liquidToken] }).catch(() => 0n),
|
|
7014
|
-
client.readContract({ address: HYPERLEND_ORACLE, abi: ORACLE_ABI3, functionName: "getAssetPrice", args: [WHYPE] }).catch(() => 0n)
|
|
7015
|
-
]);
|
|
7016
|
-
const rateF64 = hypePrice > 0n && khypePrice > 0n ? Number(khypePrice * 10n ** 18n / hypePrice) / 1e18 : 1;
|
|
7017
|
-
return {
|
|
7018
|
-
protocol: this.protocolName,
|
|
7019
|
-
staked_token: zeroAddress13,
|
|
7020
|
-
liquid_token: this.liquidToken,
|
|
7021
|
-
exchange_rate: rateF64,
|
|
7022
|
-
total_staked: totalStaked
|
|
7023
|
-
};
|
|
7024
|
-
}
|
|
7025
|
-
};
|
|
7026
6737
|
var HLP_ABI = parseAbi27([
|
|
7027
6738
|
"function deposit(uint256 amount) external returns (uint256)",
|
|
7028
6739
|
"function withdraw(uint256 shares) external returns (uint256)"
|
|
@@ -7039,59 +6750,6 @@ var ERC721_ABI = parseAbi29([
|
|
|
7039
6750
|
"function balanceOf(address owner) returns (uint256)",
|
|
7040
6751
|
"function tokenURI(uint256 tokenId) returns (string)"
|
|
7041
6752
|
]);
|
|
7042
|
-
var ERC721Adapter = class {
|
|
7043
|
-
protocolName;
|
|
7044
|
-
rpcUrl;
|
|
7045
|
-
constructor(entry, rpcUrl) {
|
|
7046
|
-
this.protocolName = entry.name;
|
|
7047
|
-
this.rpcUrl = rpcUrl;
|
|
7048
|
-
}
|
|
7049
|
-
name() {
|
|
7050
|
-
return this.protocolName;
|
|
7051
|
-
}
|
|
7052
|
-
async getCollectionInfo(collection) {
|
|
7053
|
-
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
7054
|
-
const client = createPublicClient21({ transport: http21(this.rpcUrl) });
|
|
7055
|
-
const [collectionName, symbol, totalSupply] = await Promise.all([
|
|
7056
|
-
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "name" }).catch((e) => {
|
|
7057
|
-
throw DefiError.rpcError(`[${this.protocolName}] name failed: ${e}`);
|
|
7058
|
-
}),
|
|
7059
|
-
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "symbol" }).catch((e) => {
|
|
7060
|
-
throw DefiError.rpcError(`[${this.protocolName}] symbol failed: ${e}`);
|
|
7061
|
-
}),
|
|
7062
|
-
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "totalSupply" }).catch(() => void 0)
|
|
7063
|
-
]);
|
|
7064
|
-
return {
|
|
7065
|
-
address: collection,
|
|
7066
|
-
name: collectionName,
|
|
7067
|
-
symbol,
|
|
7068
|
-
total_supply: totalSupply
|
|
7069
|
-
};
|
|
7070
|
-
}
|
|
7071
|
-
async getTokenInfo(collection, tokenId) {
|
|
7072
|
-
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
7073
|
-
const client = createPublicClient21({ transport: http21(this.rpcUrl) });
|
|
7074
|
-
const [owner, tokenUri] = await Promise.all([
|
|
7075
|
-
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "ownerOf", args: [tokenId] }).catch((e) => {
|
|
7076
|
-
throw DefiError.rpcError(`[${this.protocolName}] ownerOf failed: ${e}`);
|
|
7077
|
-
}),
|
|
7078
|
-
client.readContract({ address: collection, abi: ERC721_ABI, functionName: "tokenURI", args: [tokenId] }).catch(() => void 0)
|
|
7079
|
-
]);
|
|
7080
|
-
return {
|
|
7081
|
-
collection,
|
|
7082
|
-
token_id: tokenId,
|
|
7083
|
-
owner,
|
|
7084
|
-
token_uri: tokenUri
|
|
7085
|
-
};
|
|
7086
|
-
}
|
|
7087
|
-
async getBalance(owner, collection) {
|
|
7088
|
-
if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
|
|
7089
|
-
const client = createPublicClient21({ transport: http21(this.rpcUrl) });
|
|
7090
|
-
return client.readContract({ address: collection, abi: ERC721_ABI, functionName: "balanceOf", args: [owner] }).catch((e) => {
|
|
7091
|
-
throw DefiError.rpcError(`[${this.protocolName}] balanceOf failed: ${e}`);
|
|
7092
|
-
});
|
|
7093
|
-
}
|
|
7094
|
-
};
|
|
7095
6753
|
function createDex(entry, rpcUrl) {
|
|
7096
6754
|
switch (entry.interface) {
|
|
7097
6755
|
case "uniswap_v3":
|
|
@@ -7155,19 +6813,6 @@ function createVault(entry, rpcUrl) {
|
|
|
7155
6813
|
throw DefiError.unsupported(`Vault interface '${entry.interface}' not yet implemented`);
|
|
7156
6814
|
}
|
|
7157
6815
|
}
|
|
7158
|
-
function createLiquidStaking(entry, rpcUrl) {
|
|
7159
|
-
switch (entry.interface) {
|
|
7160
|
-
case "kinetiq_staking":
|
|
7161
|
-
return new KinetiqAdapter(entry, rpcUrl);
|
|
7162
|
-
case "sthype_staking":
|
|
7163
|
-
return new StHypeAdapter(entry, rpcUrl);
|
|
7164
|
-
case "hyperbeat_lst":
|
|
7165
|
-
case "kintsu":
|
|
7166
|
-
return new GenericLstAdapter(entry, rpcUrl);
|
|
7167
|
-
default:
|
|
7168
|
-
return new GenericLstAdapter(entry, rpcUrl);
|
|
7169
|
-
}
|
|
7170
|
-
}
|
|
7171
6816
|
function createGauge(entry, rpcUrl) {
|
|
7172
6817
|
if (entry.interface === "hybra" || entry.contracts?.["gauge_manager"]) {
|
|
7173
6818
|
return new HybraGaugeAdapter(entry, rpcUrl);
|
|
@@ -7181,19 +6826,6 @@ function createGauge(entry, rpcUrl) {
|
|
|
7181
6826
|
throw DefiError.unsupported(`Gauge interface '${entry.interface}' not supported`);
|
|
7182
6827
|
}
|
|
7183
6828
|
}
|
|
7184
|
-
function createMasterChef(entry, rpcUrl) {
|
|
7185
|
-
return new MasterChefAdapter(entry, rpcUrl);
|
|
7186
|
-
}
|
|
7187
|
-
function createNft(entry, rpcUrl) {
|
|
7188
|
-
switch (entry.interface) {
|
|
7189
|
-
case "erc721":
|
|
7190
|
-
return new ERC721Adapter(entry, rpcUrl);
|
|
7191
|
-
case "marketplace":
|
|
7192
|
-
throw DefiError.unsupported(`NFT marketplace '${entry.name}' is not queryable as ERC-721. Use a specific collection address.`);
|
|
7193
|
-
default:
|
|
7194
|
-
throw DefiError.unsupported(`NFT interface '${entry.interface}' not supported`);
|
|
7195
|
-
}
|
|
7196
|
-
}
|
|
7197
6829
|
function createOracleFromLending(entry, rpcUrl) {
|
|
7198
6830
|
switch (entry.interface) {
|
|
7199
6831
|
case "aave_v3":
|
|
@@ -7267,61 +6899,127 @@ var DexSpotPrice = class {
|
|
|
7267
6899
|
}
|
|
7268
6900
|
};
|
|
7269
6901
|
|
|
7270
|
-
// src/commands/
|
|
7271
|
-
function
|
|
7272
|
-
|
|
7273
|
-
|
|
6902
|
+
// src/commands/lp.ts
|
|
6903
|
+
function resolveAccount(optOwner) {
|
|
6904
|
+
if (optOwner) return optOwner;
|
|
6905
|
+
const walletAddr = process.env["DEFI_WALLET_ADDRESS"];
|
|
6906
|
+
if (walletAddr) return walletAddr;
|
|
6907
|
+
const privateKey = process.env["DEFI_PRIVATE_KEY"];
|
|
6908
|
+
if (privateKey) return privateKeyToAccount2(privateKey).address;
|
|
6909
|
+
throw new Error("--address, DEFI_WALLET_ADDRESS, or DEFI_PRIVATE_KEY is required");
|
|
6910
|
+
}
|
|
6911
|
+
function resolvePoolAddress(registry, protocolSlug, pool) {
|
|
6912
|
+
if (pool.startsWith("0x")) return pool;
|
|
6913
|
+
return registry.resolvePool(protocolSlug, pool).address;
|
|
6914
|
+
}
|
|
6915
|
+
function registerLP(parent, getOpts, makeExecutor2) {
|
|
6916
|
+
const lp = parent.command("lp").description("Unified LP operations: discover, add, farm, claim, remove, positions");
|
|
6917
|
+
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) => {
|
|
7274
6918
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7275
6919
|
const registry = Registry.loadEmbedded();
|
|
7276
6920
|
const chain = registry.getChain(chainName);
|
|
7277
|
-
const
|
|
7278
|
-
const
|
|
7279
|
-
const
|
|
7280
|
-
const
|
|
7281
|
-
|
|
7282
|
-
|
|
6921
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
6922
|
+
const allProtocols = registry.getProtocolsForChain(chainName);
|
|
6923
|
+
const protocols = opts.protocol ? [registry.getProtocol(opts.protocol)] : allProtocols;
|
|
6924
|
+
const results = [];
|
|
6925
|
+
await Promise.allSettled(
|
|
6926
|
+
protocols.map(async (protocol) => {
|
|
6927
|
+
try {
|
|
6928
|
+
if (["solidly_v2", "solidly_cl", "algebra_v3", "hybra"].includes(protocol.interface)) {
|
|
6929
|
+
const adapter = createGauge(protocol, rpcUrl);
|
|
6930
|
+
if (adapter.discoverGaugedPools) {
|
|
6931
|
+
const pools = await adapter.discoverGaugedPools();
|
|
6932
|
+
for (const p of pools) {
|
|
6933
|
+
results.push({
|
|
6934
|
+
protocol: protocol.slug,
|
|
6935
|
+
pool: p.pool,
|
|
6936
|
+
pair: `${p.token0}/${p.token1}`,
|
|
6937
|
+
type: "EMISSION",
|
|
6938
|
+
source: "gauge"
|
|
6939
|
+
});
|
|
6940
|
+
}
|
|
6941
|
+
}
|
|
6942
|
+
}
|
|
6943
|
+
if (protocol.interface === "algebra_v3" && protocol.contracts?.["farming_center"]) {
|
|
6944
|
+
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
6945
|
+
const pools = await adapter.discoverFarmingPools();
|
|
6946
|
+
for (const p of pools) {
|
|
6947
|
+
results.push({
|
|
6948
|
+
protocol: protocol.slug,
|
|
6949
|
+
pool: p.pool,
|
|
6950
|
+
type: "EMISSION",
|
|
6951
|
+
source: "farming",
|
|
6952
|
+
total_reward: p.totalReward.toString(),
|
|
6953
|
+
bonus_reward: p.bonusReward.toString(),
|
|
6954
|
+
active: p.active
|
|
6955
|
+
});
|
|
6956
|
+
}
|
|
6957
|
+
}
|
|
6958
|
+
if (protocol.interface === "uniswap_v2" && protocol.contracts?.["lb_factory"]) {
|
|
6959
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
6960
|
+
const pools = await adapter.discoverRewardedPools();
|
|
6961
|
+
for (const p of pools) {
|
|
6962
|
+
if (!opts.emissionOnly || !p.stopped) {
|
|
6963
|
+
results.push({
|
|
6964
|
+
protocol: protocol.slug,
|
|
6965
|
+
pool: p.pool,
|
|
6966
|
+
pair: `${p.symbolX}/${p.symbolY}`,
|
|
6967
|
+
type: "EMISSION",
|
|
6968
|
+
source: "lb_hooks",
|
|
6969
|
+
stopped: p.stopped
|
|
6970
|
+
});
|
|
6971
|
+
}
|
|
6972
|
+
}
|
|
6973
|
+
}
|
|
6974
|
+
} catch {
|
|
6975
|
+
}
|
|
6976
|
+
})
|
|
6977
|
+
);
|
|
6978
|
+
if (opts.emissionOnly) {
|
|
6979
|
+
printOutput(results.filter((r) => r.type === "EMISSION"), getOpts());
|
|
6980
|
+
} else {
|
|
6981
|
+
printOutput(results, getOpts());
|
|
6982
|
+
}
|
|
7283
6983
|
});
|
|
7284
|
-
|
|
6984
|
+
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) => {
|
|
7285
6985
|
const executor = makeExecutor2();
|
|
7286
6986
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7287
6987
|
const registry = Registry.loadEmbedded();
|
|
7288
6988
|
const chain = registry.getChain(chainName);
|
|
7289
6989
|
const protocol = registry.getProtocol(opts.protocol);
|
|
7290
6990
|
const adapter = createDex(protocol, chain.effectiveRpcUrl());
|
|
7291
|
-
const
|
|
7292
|
-
const
|
|
7293
|
-
const recipient = opts.recipient ?? process.env
|
|
7294
|
-
const
|
|
6991
|
+
const tokenA = opts.tokenA.startsWith("0x") ? opts.tokenA : registry.resolveToken(chainName, opts.tokenA).address;
|
|
6992
|
+
const tokenB = opts.tokenB.startsWith("0x") ? opts.tokenB : registry.resolveToken(chainName, opts.tokenB).address;
|
|
6993
|
+
const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
|
|
6994
|
+
const poolAddr = opts.pool ? resolvePoolAddress(registry, opts.protocol, opts.pool) : void 0;
|
|
6995
|
+
const tx = await adapter.buildAddLiquidity({
|
|
7295
6996
|
protocol: protocol.name,
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
recipient
|
|
6997
|
+
token_a: tokenA,
|
|
6998
|
+
token_b: tokenB,
|
|
6999
|
+
amount_a: BigInt(opts.amountA),
|
|
7000
|
+
amount_b: BigInt(opts.amountB),
|
|
7001
|
+
recipient,
|
|
7002
|
+
tick_lower: opts.tickLower !== void 0 ? parseInt(opts.tickLower) : void 0,
|
|
7003
|
+
tick_upper: opts.tickUpper !== void 0 ? parseInt(opts.tickUpper) : void 0,
|
|
7004
|
+
range_pct: opts.range !== void 0 ? parseFloat(opts.range) : void 0,
|
|
7005
|
+
pool: poolAddr
|
|
7301
7006
|
});
|
|
7302
7007
|
const result = await executor.execute(tx);
|
|
7303
7008
|
printOutput(result, getOpts());
|
|
7304
7009
|
});
|
|
7305
|
-
|
|
7010
|
+
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) => {
|
|
7306
7011
|
const executor = makeExecutor2();
|
|
7307
7012
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7308
7013
|
const registry = Registry.loadEmbedded();
|
|
7309
7014
|
const chain = registry.getChain(chainName);
|
|
7310
7015
|
const protocol = registry.getProtocol(opts.protocol);
|
|
7311
|
-
const
|
|
7016
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
7017
|
+
const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
|
|
7018
|
+
const poolAddr = opts.pool ? resolvePoolAddress(registry, opts.protocol, opts.pool) : void 0;
|
|
7312
7019
|
const tokenA = opts.tokenA.startsWith("0x") ? opts.tokenA : registry.resolveToken(chainName, opts.tokenA).address;
|
|
7313
7020
|
const tokenB = opts.tokenB.startsWith("0x") ? opts.tokenB : registry.resolveToken(chainName, opts.tokenB).address;
|
|
7314
|
-
const
|
|
7315
|
-
|
|
7316
|
-
if (opts.pool) {
|
|
7317
|
-
if (opts.pool.startsWith("0x")) {
|
|
7318
|
-
poolAddr = opts.pool;
|
|
7319
|
-
} else {
|
|
7320
|
-
const poolInfo = registry.resolvePool(opts.protocol, opts.pool);
|
|
7321
|
-
poolAddr = poolInfo.address;
|
|
7322
|
-
}
|
|
7323
|
-
}
|
|
7324
|
-
const tx = await adapter.buildAddLiquidity({
|
|
7021
|
+
const dexAdapter = createDex(protocol, rpcUrl);
|
|
7022
|
+
const addTx = await dexAdapter.buildAddLiquidity({
|
|
7325
7023
|
protocol: protocol.name,
|
|
7326
7024
|
token_a: tokenA,
|
|
7327
7025
|
token_b: tokenB,
|
|
@@ -7333,143 +7031,202 @@ function registerDex(parent, getOpts, makeExecutor2) {
|
|
|
7333
7031
|
range_pct: opts.range !== void 0 ? parseFloat(opts.range) : void 0,
|
|
7334
7032
|
pool: poolAddr
|
|
7335
7033
|
});
|
|
7336
|
-
|
|
7337
|
-
|
|
7034
|
+
process.stderr.write("Step 1/2: Adding liquidity...\n");
|
|
7035
|
+
const addResult = await executor.execute(addTx);
|
|
7036
|
+
printOutput({ step: "lp_add", ...addResult }, getOpts());
|
|
7037
|
+
if (addResult.status !== "confirmed" && addResult.status !== "simulated") {
|
|
7038
|
+
process.stderr.write("Step 2/2: Skipped \u2014 LP add did not succeed.\n");
|
|
7039
|
+
return;
|
|
7040
|
+
}
|
|
7041
|
+
const mintedTokenId = addResult.details?.minted_token_id ? BigInt(addResult.details.minted_token_id) : void 0;
|
|
7042
|
+
const iface = protocol.interface;
|
|
7043
|
+
if (iface === "algebra_v3" && protocol.contracts?.["farming_center"]) {
|
|
7044
|
+
if (!mintedTokenId) {
|
|
7045
|
+
process.stderr.write("Step 2/2: Skipped staking (no tokenId \u2014 run in --broadcast mode to get minted NFT)\n");
|
|
7046
|
+
return;
|
|
7047
|
+
}
|
|
7048
|
+
if (!poolAddr) throw new Error("--pool is required for lp farm with KittenSwap (needed for farming center)");
|
|
7049
|
+
process.stderr.write("Step 2/2: Staking into KittenSwap eternal farming...\n");
|
|
7050
|
+
const farmAdapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
7051
|
+
const stakeTx = await farmAdapter.buildEnterFarming(mintedTokenId, poolAddr, recipient);
|
|
7052
|
+
const stakeResult = await executor.execute(stakeTx);
|
|
7053
|
+
printOutput({ step: "stake_farming", ...stakeResult }, getOpts());
|
|
7054
|
+
return;
|
|
7055
|
+
}
|
|
7056
|
+
if (["solidly_v2", "solidly_cl", "hybra"].includes(iface)) {
|
|
7057
|
+
if (!mintedTokenId && iface !== "solidly_v2") {
|
|
7058
|
+
process.stderr.write("Step 2/2: Skipped staking (no tokenId \u2014 run in --broadcast mode to get minted NFT)\n");
|
|
7059
|
+
return;
|
|
7060
|
+
}
|
|
7061
|
+
let gaugeAddr = opts.gauge;
|
|
7062
|
+
if (!gaugeAddr && poolAddr) {
|
|
7063
|
+
try {
|
|
7064
|
+
const gaugeAdapter2 = createGauge(protocol, rpcUrl);
|
|
7065
|
+
if (gaugeAdapter2.resolveGauge) {
|
|
7066
|
+
gaugeAddr = await gaugeAdapter2.resolveGauge(poolAddr);
|
|
7067
|
+
}
|
|
7068
|
+
} catch {
|
|
7069
|
+
}
|
|
7070
|
+
}
|
|
7071
|
+
if (!gaugeAddr) throw new Error("--gauge <address> is required for staking (could not auto-resolve gauge)");
|
|
7072
|
+
process.stderr.write("Step 2/2: Staking into gauge...\n");
|
|
7073
|
+
const gaugeAdapter = createGauge(protocol, rpcUrl);
|
|
7074
|
+
const tokenIdArg = mintedTokenId;
|
|
7075
|
+
const amountArg = iface === "solidly_v2" ? BigInt("115792089237316195423570985008687907853269984665640564039457584007913129639935") : 0n;
|
|
7076
|
+
const lpTokenArg = iface === "solidly_v2" ? poolAddr : void 0;
|
|
7077
|
+
const stakeTx = await gaugeAdapter.buildDeposit(gaugeAddr, amountArg, tokenIdArg, lpTokenArg);
|
|
7078
|
+
const stakeResult = await executor.execute(stakeTx);
|
|
7079
|
+
printOutput({ step: "stake_gauge", ...stakeResult }, getOpts());
|
|
7080
|
+
return;
|
|
7081
|
+
}
|
|
7082
|
+
if (iface === "uniswap_v2" && protocol.contracts?.["lb_factory"]) {
|
|
7083
|
+
process.stderr.write("Step 2/2: Merchant Moe LB hooks handle rewards automatically \u2014 no staking needed.\n");
|
|
7084
|
+
return;
|
|
7085
|
+
}
|
|
7086
|
+
process.stderr.write("Step 2/2: No staking adapter found for this protocol interface \u2014 liquidity added only.\n");
|
|
7338
7087
|
});
|
|
7339
|
-
|
|
7088
|
+
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) => {
|
|
7340
7089
|
const executor = makeExecutor2();
|
|
7341
7090
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7342
7091
|
const registry = Registry.loadEmbedded();
|
|
7343
7092
|
const chain = registry.getChain(chainName);
|
|
7093
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
7344
7094
|
const protocol = registry.getProtocol(opts.protocol);
|
|
7345
|
-
const
|
|
7095
|
+
const account = resolveAccount(opts.address);
|
|
7096
|
+
const iface = protocol.interface;
|
|
7097
|
+
if (iface === "algebra_v3" && protocol.contracts?.["farming_center"]) {
|
|
7098
|
+
if (!opts.pool) throw new Error("--pool is required for KittenSwap farming claim");
|
|
7099
|
+
if (!opts.tokenId) throw new Error("--token-id is required for KittenSwap farming claim");
|
|
7100
|
+
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
7101
|
+
const tx = await adapter.buildCollectRewards(
|
|
7102
|
+
BigInt(opts.tokenId),
|
|
7103
|
+
opts.pool,
|
|
7104
|
+
account
|
|
7105
|
+
);
|
|
7106
|
+
const result = await executor.execute(tx);
|
|
7107
|
+
printOutput(result, getOpts());
|
|
7108
|
+
return;
|
|
7109
|
+
}
|
|
7110
|
+
if (iface === "uniswap_v2" && protocol.contracts?.["lb_factory"]) {
|
|
7111
|
+
if (!opts.pool) throw new Error("--pool is required for Merchant Moe LB claim");
|
|
7112
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
7113
|
+
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
7114
|
+
const tx = await adapter.buildClaimRewards(account, opts.pool, binIds);
|
|
7115
|
+
const result = await executor.execute(tx);
|
|
7116
|
+
printOutput(result, getOpts());
|
|
7117
|
+
return;
|
|
7118
|
+
}
|
|
7119
|
+
if (["solidly_v2", "solidly_cl", "algebra_v3", "hybra"].includes(iface)) {
|
|
7120
|
+
if (!opts.gauge) throw new Error("--gauge is required for gauge claim");
|
|
7121
|
+
const adapter = createGauge(protocol, rpcUrl);
|
|
7122
|
+
let tx;
|
|
7123
|
+
if (opts.tokenId) {
|
|
7124
|
+
if (!adapter.buildClaimRewardsByTokenId) throw new Error(`${protocol.name} does not support NFT-based claim`);
|
|
7125
|
+
tx = await adapter.buildClaimRewardsByTokenId(opts.gauge, BigInt(opts.tokenId));
|
|
7126
|
+
} else {
|
|
7127
|
+
tx = await adapter.buildClaimRewards(opts.gauge, account);
|
|
7128
|
+
}
|
|
7129
|
+
const result = await executor.execute(tx);
|
|
7130
|
+
printOutput(result, getOpts());
|
|
7131
|
+
return;
|
|
7132
|
+
}
|
|
7133
|
+
throw new Error(`No claim method found for protocol interface '${iface}'`);
|
|
7134
|
+
});
|
|
7135
|
+
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) => {
|
|
7136
|
+
const executor = makeExecutor2();
|
|
7137
|
+
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7138
|
+
const registry = Registry.loadEmbedded();
|
|
7139
|
+
const chain = registry.getChain(chainName);
|
|
7140
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
7141
|
+
const protocol = registry.getProtocol(opts.protocol);
|
|
7142
|
+
const iface = protocol.interface;
|
|
7143
|
+
const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
|
|
7346
7144
|
const tokenA = opts.tokenA.startsWith("0x") ? opts.tokenA : registry.resolveToken(chainName, opts.tokenA).address;
|
|
7347
7145
|
const tokenB = opts.tokenB.startsWith("0x") ? opts.tokenB : registry.resolveToken(chainName, opts.tokenB).address;
|
|
7348
|
-
const
|
|
7349
|
-
|
|
7146
|
+
const poolAddr = opts.pool ? opts.pool : void 0;
|
|
7147
|
+
let didUnstake = false;
|
|
7148
|
+
if (iface === "algebra_v3" && protocol.contracts?.["farming_center"] && opts.tokenId && poolAddr) {
|
|
7149
|
+
process.stderr.write("Step 1/2: Exiting KittenSwap farming...\n");
|
|
7150
|
+
const farmAdapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
7151
|
+
const exitTx = await farmAdapter.buildExitFarming(BigInt(opts.tokenId), poolAddr);
|
|
7152
|
+
const exitResult = await executor.execute(exitTx);
|
|
7153
|
+
printOutput({ step: "unstake_farming", ...exitResult }, getOpts());
|
|
7154
|
+
if (exitResult.status !== "confirmed" && exitResult.status !== "simulated") {
|
|
7155
|
+
process.stderr.write("Step 2/2: Skipped \u2014 unstake did not succeed.\n");
|
|
7156
|
+
return;
|
|
7157
|
+
}
|
|
7158
|
+
didUnstake = true;
|
|
7159
|
+
} else if (["solidly_v2", "solidly_cl", "hybra"].includes(iface)) {
|
|
7160
|
+
let gaugeAddr = opts.gauge;
|
|
7161
|
+
if (!gaugeAddr && poolAddr) {
|
|
7162
|
+
try {
|
|
7163
|
+
const gaugeAdapter = createGauge(protocol, rpcUrl);
|
|
7164
|
+
if (gaugeAdapter.resolveGauge) {
|
|
7165
|
+
gaugeAddr = await gaugeAdapter.resolveGauge(poolAddr);
|
|
7166
|
+
}
|
|
7167
|
+
} catch {
|
|
7168
|
+
}
|
|
7169
|
+
}
|
|
7170
|
+
if (gaugeAddr) {
|
|
7171
|
+
process.stderr.write("Step 1/2: Withdrawing from gauge...\n");
|
|
7172
|
+
const gaugeAdapter = createGauge(protocol, rpcUrl);
|
|
7173
|
+
const tokenId = opts.tokenId ? BigInt(opts.tokenId) : void 0;
|
|
7174
|
+
const withdrawTx = await gaugeAdapter.buildWithdraw(gaugeAddr, BigInt(opts.liquidity), tokenId);
|
|
7175
|
+
const withdrawResult = await executor.execute(withdrawTx);
|
|
7176
|
+
printOutput({ step: "unstake_gauge", ...withdrawResult }, getOpts());
|
|
7177
|
+
if (withdrawResult.status !== "confirmed" && withdrawResult.status !== "simulated") {
|
|
7178
|
+
process.stderr.write("Step 2/2: Skipped \u2014 unstake did not succeed.\n");
|
|
7179
|
+
return;
|
|
7180
|
+
}
|
|
7181
|
+
didUnstake = true;
|
|
7182
|
+
}
|
|
7183
|
+
}
|
|
7184
|
+
if (!didUnstake) {
|
|
7185
|
+
process.stderr.write("Step 1/2: No staking detected \u2014 skipping unstake.\n");
|
|
7186
|
+
}
|
|
7187
|
+
process.stderr.write("Step 2/2: Removing liquidity...\n");
|
|
7188
|
+
const dexAdapter = createDex(protocol, rpcUrl);
|
|
7189
|
+
const removeTx = await dexAdapter.buildRemoveLiquidity({
|
|
7350
7190
|
protocol: protocol.name,
|
|
7351
7191
|
token_a: tokenA,
|
|
7352
7192
|
token_b: tokenB,
|
|
7353
7193
|
liquidity: BigInt(opts.liquidity),
|
|
7354
7194
|
recipient
|
|
7355
7195
|
});
|
|
7356
|
-
const
|
|
7357
|
-
printOutput(
|
|
7196
|
+
const removeResult = await executor.execute(removeTx);
|
|
7197
|
+
printOutput({ step: "lp_remove", ...removeResult }, getOpts());
|
|
7358
7198
|
});
|
|
7359
|
-
|
|
7199
|
+
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) => {
|
|
7360
7200
|
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7361
7201
|
const registry = Registry.loadEmbedded();
|
|
7362
7202
|
const chain = registry.getChain(chainName);
|
|
7363
|
-
const
|
|
7364
|
-
const
|
|
7365
|
-
const
|
|
7203
|
+
const rpcUrl = chain.effectiveRpcUrl();
|
|
7204
|
+
const user = resolveAccount(opts.address);
|
|
7205
|
+
const allProtocols = registry.getProtocolsForChain(chainName);
|
|
7206
|
+
const protocols = opts.protocol ? [registry.getProtocol(opts.protocol)] : allProtocols;
|
|
7366
7207
|
const results = [];
|
|
7367
|
-
await Promise.
|
|
7368
|
-
|
|
7369
|
-
|
|
7370
|
-
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
|
|
7377
|
-
|
|
7378
|
-
|
|
7379
|
-
|
|
7380
|
-
|
|
7381
|
-
|
|
7382
|
-
|
|
7383
|
-
|
|
7384
|
-
|
|
7385
|
-
|
|
7386
|
-
|
|
7387
|
-
|
|
7388
|
-
|
|
7389
|
-
}
|
|
7390
|
-
function registerGauge(parent, getOpts, makeExecutor2) {
|
|
7391
|
-
const gauge = parent.command("gauge").description("Gauge operations: find, deposit, withdraw, claim, earned");
|
|
7392
|
-
gauge.command("discover").description("Find all pools with emission gauges (scans V2 + CL factories)").requiredOption("--protocol <protocol>", "Protocol slug").action(async (opts) => {
|
|
7393
|
-
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7394
|
-
const registry = Registry.loadEmbedded();
|
|
7395
|
-
const chain = registry.getChain(chainName);
|
|
7396
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
7397
|
-
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7398
|
-
if (!adapter.discoverGaugedPools) throw new Error(`${protocol.name} does not support gauge discovery`);
|
|
7399
|
-
const pools = await adapter.discoverGaugedPools();
|
|
7400
|
-
printOutput(pools, getOpts());
|
|
7401
|
-
});
|
|
7402
|
-
gauge.command("find").description("Find gauge address for a pool via voter contract").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "Pool address").action(async (opts) => {
|
|
7403
|
-
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7404
|
-
const registry = Registry.loadEmbedded();
|
|
7405
|
-
const chain = registry.getChain(chainName);
|
|
7406
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
7407
|
-
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7408
|
-
if (!adapter.resolveGauge) throw new Error(`${protocol.name} does not support gauge lookup`);
|
|
7409
|
-
const gaugeAddr = await adapter.resolveGauge(opts.pool);
|
|
7410
|
-
printOutput({ pool: opts.pool, gauge: gaugeAddr, protocol: protocol.name }, getOpts());
|
|
7411
|
-
});
|
|
7412
|
-
gauge.command("earned").description("Check pending rewards for a gauge").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--gauge <address>", "Gauge contract address").option("--token-id <id>", "NFT tokenId (for CL gauges like Hybra)").action(async (opts) => {
|
|
7413
|
-
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7414
|
-
const registry = Registry.loadEmbedded();
|
|
7415
|
-
const chain = registry.getChain(chainName);
|
|
7416
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
7417
|
-
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7418
|
-
if (opts.tokenId) {
|
|
7419
|
-
if (!adapter.getPendingRewardsByTokenId) throw new Error(`${protocol.name} does not support NFT rewards`);
|
|
7420
|
-
const earned = await adapter.getPendingRewardsByTokenId(opts.gauge, BigInt(opts.tokenId));
|
|
7421
|
-
printOutput({ gauge: opts.gauge, token_id: opts.tokenId, earned: earned.toString() }, getOpts());
|
|
7422
|
-
} else {
|
|
7423
|
-
const account = resolveAccount();
|
|
7424
|
-
if (!account) throw new Error("DEFI_WALLET_ADDRESS or DEFI_PRIVATE_KEY required");
|
|
7425
|
-
const rewards = await adapter.getPendingRewards(opts.gauge, account);
|
|
7426
|
-
printOutput(rewards.map((r) => ({ token: r.token, amount: r.amount.toString() })), getOpts());
|
|
7427
|
-
}
|
|
7428
|
-
});
|
|
7429
|
-
gauge.command("deposit").description("Deposit LP tokens or NFT into a gauge").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--gauge <address>", "Gauge contract address").option("--amount <amount>", "LP token amount in wei (for V2 gauges)").option("--token-id <id>", "NFT tokenId (for CL gauges like Hybra)").action(async (opts) => {
|
|
7430
|
-
const executor = makeExecutor2();
|
|
7431
|
-
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7432
|
-
const registry = Registry.loadEmbedded();
|
|
7433
|
-
const chain = registry.getChain(chainName);
|
|
7434
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
7435
|
-
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7436
|
-
const amount = opts.amount ? BigInt(opts.amount) : 0n;
|
|
7437
|
-
const tokenId = opts.tokenId ? BigInt(opts.tokenId) : void 0;
|
|
7438
|
-
const tx = await adapter.buildDeposit(opts.gauge, amount, tokenId);
|
|
7439
|
-
const result = await executor.execute(tx);
|
|
7440
|
-
printOutput(result, getOpts());
|
|
7441
|
-
});
|
|
7442
|
-
gauge.command("withdraw").description("Withdraw LP tokens or NFT from a gauge").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--gauge <address>", "Gauge contract address").option("--amount <amount>", "LP token amount in wei (for V2 gauges)").option("--token-id <id>", "NFT tokenId (for CL gauges like Hybra)").action(async (opts) => {
|
|
7443
|
-
const executor = makeExecutor2();
|
|
7444
|
-
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7445
|
-
const registry = Registry.loadEmbedded();
|
|
7446
|
-
const chain = registry.getChain(chainName);
|
|
7447
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
7448
|
-
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7449
|
-
const amount = opts.amount ? BigInt(opts.amount) : 0n;
|
|
7450
|
-
const tokenId = opts.tokenId ? BigInt(opts.tokenId) : void 0;
|
|
7451
|
-
const tx = await adapter.buildWithdraw(opts.gauge, amount, tokenId);
|
|
7452
|
-
const result = await executor.execute(tx);
|
|
7453
|
-
printOutput(result, getOpts());
|
|
7454
|
-
});
|
|
7455
|
-
gauge.command("claim").description("Claim earned rewards from a gauge").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--gauge <address>", "Gauge contract address").option("--token-id <id>", "NFT tokenId (for CL gauges like Hybra)").action(async (opts) => {
|
|
7456
|
-
const executor = makeExecutor2();
|
|
7457
|
-
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7458
|
-
const registry = Registry.loadEmbedded();
|
|
7459
|
-
const chain = registry.getChain(chainName);
|
|
7460
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
7461
|
-
const adapter = createGauge(protocol, chain.effectiveRpcUrl());
|
|
7462
|
-
if (opts.tokenId) {
|
|
7463
|
-
if (!adapter.buildClaimRewardsByTokenId) throw new Error(`${protocol.name} does not support NFT claim`);
|
|
7464
|
-
const tx = await adapter.buildClaimRewardsByTokenId(opts.gauge, BigInt(opts.tokenId));
|
|
7465
|
-
const result = await executor.execute(tx);
|
|
7466
|
-
printOutput(result, getOpts());
|
|
7467
|
-
} else {
|
|
7468
|
-
const account = resolveAccount();
|
|
7469
|
-
const tx = await adapter.buildClaimRewards(opts.gauge, account);
|
|
7470
|
-
const result = await executor.execute(tx);
|
|
7471
|
-
printOutput(result, getOpts());
|
|
7472
|
-
}
|
|
7208
|
+
await Promise.allSettled(
|
|
7209
|
+
protocols.map(async (protocol) => {
|
|
7210
|
+
try {
|
|
7211
|
+
if (protocol.interface === "uniswap_v2" && protocol.contracts?.["lb_factory"]) {
|
|
7212
|
+
if (!opts.pool) return;
|
|
7213
|
+
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
7214
|
+
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
7215
|
+
const positions = await adapter.getUserPositions(user, opts.pool, binIds);
|
|
7216
|
+
for (const pos of positions) {
|
|
7217
|
+
results.push({
|
|
7218
|
+
protocol: protocol.slug,
|
|
7219
|
+
type: "lb",
|
|
7220
|
+
pool: opts.pool,
|
|
7221
|
+
...pos
|
|
7222
|
+
});
|
|
7223
|
+
}
|
|
7224
|
+
}
|
|
7225
|
+
} catch {
|
|
7226
|
+
}
|
|
7227
|
+
})
|
|
7228
|
+
);
|
|
7229
|
+
printOutput(results, getOpts());
|
|
7473
7230
|
});
|
|
7474
7231
|
}
|
|
7475
7232
|
|
|
@@ -7631,44 +7388,6 @@ function registerCdp(parent, getOpts, makeExecutor2) {
|
|
|
7631
7388
|
});
|
|
7632
7389
|
}
|
|
7633
7390
|
|
|
7634
|
-
// src/commands/staking.ts
|
|
7635
|
-
function registerStaking(parent, getOpts, makeExecutor2) {
|
|
7636
|
-
const staking = parent.command("staking").description("Liquid staking: stake, unstake, info");
|
|
7637
|
-
staking.command("stake").description("Stake tokens via liquid staking").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--amount <amount>", "Amount in wei").option("--recipient <address>", "Recipient address").action(async (opts) => {
|
|
7638
|
-
const executor = makeExecutor2();
|
|
7639
|
-
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7640
|
-
const registry = Registry.loadEmbedded();
|
|
7641
|
-
const chain = registry.getChain(chainName);
|
|
7642
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
7643
|
-
const adapter = createLiquidStaking(protocol, chain.effectiveRpcUrl());
|
|
7644
|
-
const recipient = opts.recipient ?? process.env.DEFI_WALLET_ADDRESS ?? "0x0000000000000000000000000000000000000001";
|
|
7645
|
-
const tx = await adapter.buildStake({ protocol: protocol.name, amount: BigInt(opts.amount), recipient });
|
|
7646
|
-
const result = await executor.execute(tx);
|
|
7647
|
-
printOutput(result, getOpts());
|
|
7648
|
-
});
|
|
7649
|
-
staking.command("unstake").description("Unstake tokens").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--amount <amount>", "Amount in wei").option("--recipient <address>", "Recipient address").action(async (opts) => {
|
|
7650
|
-
const executor = makeExecutor2();
|
|
7651
|
-
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7652
|
-
const registry = Registry.loadEmbedded();
|
|
7653
|
-
const chain = registry.getChain(chainName);
|
|
7654
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
7655
|
-
const adapter = createLiquidStaking(protocol, chain.effectiveRpcUrl());
|
|
7656
|
-
const recipient = opts.recipient ?? process.env.DEFI_WALLET_ADDRESS ?? "0x0000000000000000000000000000000000000001";
|
|
7657
|
-
const tx = await adapter.buildUnstake({ protocol: protocol.name, amount: BigInt(opts.amount), recipient });
|
|
7658
|
-
const result = await executor.execute(tx);
|
|
7659
|
-
printOutput(result, getOpts());
|
|
7660
|
-
});
|
|
7661
|
-
staking.command("info").description("Show staking info and rates").requiredOption("--protocol <protocol>", "Protocol slug").action(async (opts) => {
|
|
7662
|
-
const chainName = parent.opts().chain ?? "hyperevm";
|
|
7663
|
-
const registry = Registry.loadEmbedded();
|
|
7664
|
-
const chain = registry.getChain(chainName);
|
|
7665
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
7666
|
-
const adapter = createLiquidStaking(protocol, chain.effectiveRpcUrl());
|
|
7667
|
-
const info = await adapter.getInfo();
|
|
7668
|
-
printOutput(info, getOpts());
|
|
7669
|
-
});
|
|
7670
|
-
}
|
|
7671
|
-
|
|
7672
7391
|
// src/commands/vault.ts
|
|
7673
7392
|
function registerVault(parent, getOpts, makeExecutor2) {
|
|
7674
7393
|
const vault = parent.command("vault").description("Vault operations: deposit, withdraw, info");
|
|
@@ -7922,18 +7641,30 @@ function registerYield(parent, getOpts, makeExecutor2) {
|
|
|
7922
7641
|
yieldCmd.option("--asset <token>", "Token symbol or address", "USDC").action(async (opts) => {
|
|
7923
7642
|
try {
|
|
7924
7643
|
const registry = Registry.loadEmbedded();
|
|
7925
|
-
const
|
|
7926
|
-
const
|
|
7927
|
-
const
|
|
7928
|
-
|
|
7929
|
-
|
|
7930
|
-
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
|
|
7936
|
-
|
|
7644
|
+
const asset = opts.asset;
|
|
7645
|
+
const allRates = [];
|
|
7646
|
+
for (const [chainKey] of registry.chains) {
|
|
7647
|
+
try {
|
|
7648
|
+
const chain = registry.getChain(chainKey);
|
|
7649
|
+
const rpc = chain.effectiveRpcUrl();
|
|
7650
|
+
let assetAddr;
|
|
7651
|
+
try {
|
|
7652
|
+
assetAddr = resolveAsset(registry, chainKey, asset);
|
|
7653
|
+
} catch {
|
|
7654
|
+
continue;
|
|
7655
|
+
}
|
|
7656
|
+
const rates = await collectLendingRates(registry, chainKey, rpc, assetAddr);
|
|
7657
|
+
for (const r of rates) {
|
|
7658
|
+
if (r.supply_apy > 0) {
|
|
7659
|
+
allRates.push({ chain: chain.name, protocol: r.protocol, supply_apy: r.supply_apy, borrow_variable_apy: r.borrow_variable_apy });
|
|
7660
|
+
}
|
|
7661
|
+
}
|
|
7662
|
+
} catch {
|
|
7663
|
+
}
|
|
7664
|
+
}
|
|
7665
|
+
allRates.sort((a, b) => b.supply_apy - a.supply_apy);
|
|
7666
|
+
const best = allRates[0] ? `${allRates[0].protocol} on ${allRates[0].chain}` : null;
|
|
7667
|
+
printOutput({ asset, chains_scanned: registry.chains.size, rates: allRates, best_supply: best }, getOpts());
|
|
7937
7668
|
} catch (err) {
|
|
7938
7669
|
printOutput({ error: String(err) }, getOpts());
|
|
7939
7670
|
}
|
|
@@ -9400,53 +9131,6 @@ async function runAllChains(registry, patterns, oracleThreshold, stableThreshold
|
|
|
9400
9131
|
};
|
|
9401
9132
|
}
|
|
9402
9133
|
|
|
9403
|
-
// src/commands/arb.ts
|
|
9404
|
-
function registerArb(parent, getOpts, makeExecutor2) {
|
|
9405
|
-
parent.command("arb").description("Detect arbitrage opportunities across DEXes").option("--token-in <token>", "Base token (default: WHYPE)", "WHYPE").option("--token-out <token>", "Quote token (default: USDC)", "USDC").option("--amount <amount>", "Test amount in wei", "1000000000000000000").option("--execute", "Execute best arb (default: analysis only)").option("--min-profit <bps>", "Min profit in bps to execute", "10").action(async (opts) => {
|
|
9406
|
-
const chainName = parent.opts().chain ?? "hyperevm";
|
|
9407
|
-
const registry = Registry.loadEmbedded();
|
|
9408
|
-
const chain = registry.getChain(chainName);
|
|
9409
|
-
const rpcUrl = chain.effectiveRpcUrl();
|
|
9410
|
-
const tokenIn = opts.tokenIn.startsWith("0x") ? opts.tokenIn : registry.resolveToken(chainName, opts.tokenIn).address;
|
|
9411
|
-
const tokenOut = opts.tokenOut.startsWith("0x") ? opts.tokenOut : registry.resolveToken(chainName, opts.tokenOut).address;
|
|
9412
|
-
const amountIn = BigInt(opts.amount);
|
|
9413
|
-
const dexProtocols = registry.getProtocolsByCategory("dex").filter((p) => p.chain === chainName);
|
|
9414
|
-
const quotes = [];
|
|
9415
|
-
for (const p of dexProtocols) {
|
|
9416
|
-
try {
|
|
9417
|
-
const adapter = createDex(p, rpcUrl);
|
|
9418
|
-
const buyQuote = await adapter.quote({ protocol: p.name, token_in: tokenIn, token_out: tokenOut, amount_in: amountIn });
|
|
9419
|
-
if (buyQuote.amount_out === 0n) continue;
|
|
9420
|
-
const sellQuote = await adapter.quote({ protocol: p.name, token_in: tokenOut, token_out: tokenIn, amount_in: buyQuote.amount_out });
|
|
9421
|
-
const profitBps = Number((sellQuote.amount_out - amountIn) * 10000n / amountIn);
|
|
9422
|
-
quotes.push({ protocol: p.name, buy: buyQuote.amount_out, sell: sellQuote.amount_out, profit_bps: profitBps });
|
|
9423
|
-
} catch {
|
|
9424
|
-
}
|
|
9425
|
-
}
|
|
9426
|
-
const opportunities = [];
|
|
9427
|
-
for (let i = 0; i < quotes.length; i++) {
|
|
9428
|
-
for (let j = 0; j < quotes.length; j++) {
|
|
9429
|
-
if (i === j) continue;
|
|
9430
|
-
const buyAmount = quotes[i].buy;
|
|
9431
|
-
const sellAmount = quotes[j].sell;
|
|
9432
|
-
if (sellAmount > amountIn) {
|
|
9433
|
-
const profitBps = Number((sellAmount - amountIn) * 10000n / amountIn);
|
|
9434
|
-
opportunities.push({ buy_on: quotes[i].protocol, sell_on: quotes[j].protocol, profit_bps: profitBps });
|
|
9435
|
-
}
|
|
9436
|
-
}
|
|
9437
|
-
}
|
|
9438
|
-
opportunities.sort((a, b) => b.profit_bps - a.profit_bps);
|
|
9439
|
-
printOutput({
|
|
9440
|
-
chain: chainName,
|
|
9441
|
-
token_in: tokenIn,
|
|
9442
|
-
token_out: tokenOut,
|
|
9443
|
-
amount_in: amountIn,
|
|
9444
|
-
single_dex: quotes,
|
|
9445
|
-
cross_dex_opportunities: opportunities.slice(0, 5)
|
|
9446
|
-
}, getOpts());
|
|
9447
|
-
});
|
|
9448
|
-
}
|
|
9449
|
-
|
|
9450
9134
|
// src/commands/positions.ts
|
|
9451
9135
|
import { encodeFunctionData as encodeFunctionData30, parseAbi as parseAbi34 } from "viem";
|
|
9452
9136
|
var ERC20_ABI6 = parseAbi34([
|
|
@@ -10059,207 +9743,6 @@ function registerWhales(parent, getOpts) {
|
|
|
10059
9743
|
});
|
|
10060
9744
|
}
|
|
10061
9745
|
|
|
10062
|
-
// src/commands/compare.ts
|
|
10063
|
-
import { spawnSync } from "child_process";
|
|
10064
|
-
function round25(x) {
|
|
10065
|
-
return Math.round(x * 100) / 100;
|
|
10066
|
-
}
|
|
10067
|
-
async function fetchPerpRates() {
|
|
10068
|
-
let result = spawnSync("perp", ["--json", "arb", "scan", "--rates"], { encoding: "utf8", timeout: 3e4 });
|
|
10069
|
-
if (result.error || result.status !== 0) {
|
|
10070
|
-
result = spawnSync("npx", ["-y", "perp-cli@latest", "--json", "arb", "scan", "--rates"], {
|
|
10071
|
-
encoding: "utf8",
|
|
10072
|
-
timeout: 6e4
|
|
10073
|
-
});
|
|
10074
|
-
}
|
|
10075
|
-
if (result.error || result.status !== 0) {
|
|
10076
|
-
throw new Error("perp-cli not found or failed");
|
|
10077
|
-
}
|
|
10078
|
-
let data;
|
|
10079
|
-
try {
|
|
10080
|
-
data = JSON.parse(result.stdout);
|
|
10081
|
-
} catch {
|
|
10082
|
-
throw new Error("perp JSON parse error");
|
|
10083
|
-
}
|
|
10084
|
-
const d = data;
|
|
10085
|
-
const symbolsRaw = d["data"]?.["symbols"] ?? d["symbols"];
|
|
10086
|
-
const symbols = Array.isArray(symbolsRaw) ? symbolsRaw : [];
|
|
10087
|
-
const results = [];
|
|
10088
|
-
for (const sym of symbols) {
|
|
10089
|
-
const symbol = sym["symbol"] ?? "?";
|
|
10090
|
-
const maxSpread = sym["maxSpreadAnnual"] ?? 0;
|
|
10091
|
-
const longEx = sym["longExchange"] ?? "?";
|
|
10092
|
-
const shortEx = sym["shortExchange"] ?? "?";
|
|
10093
|
-
if (Math.abs(maxSpread) > 0) {
|
|
10094
|
-
results.push({
|
|
10095
|
-
type: "perp_funding",
|
|
10096
|
-
asset: symbol,
|
|
10097
|
-
apy: round25(maxSpread),
|
|
10098
|
-
detail: `long ${longEx} / short ${shortEx}`,
|
|
10099
|
-
risk: Math.abs(maxSpread) > 50 ? "high" : Math.abs(maxSpread) > 20 ? "medium" : "low",
|
|
10100
|
-
source: "perp-cli"
|
|
10101
|
-
});
|
|
10102
|
-
}
|
|
10103
|
-
const rates = Array.isArray(sym["rates"]) ? sym["rates"] : [];
|
|
10104
|
-
for (const rate of rates) {
|
|
10105
|
-
const exchange = rate["exchange"] ?? "?";
|
|
10106
|
-
const annual = rate["annualizedPct"] ?? 0;
|
|
10107
|
-
if (Math.abs(annual) > 1) {
|
|
10108
|
-
results.push({
|
|
10109
|
-
type: "perp_rate",
|
|
10110
|
-
asset: symbol,
|
|
10111
|
-
apy: round25(annual),
|
|
10112
|
-
detail: exchange,
|
|
10113
|
-
risk: Math.abs(annual) > 50 ? "high" : Math.abs(annual) > 20 ? "medium" : "low",
|
|
10114
|
-
source: "perp-cli"
|
|
10115
|
-
});
|
|
10116
|
-
}
|
|
10117
|
-
}
|
|
10118
|
-
}
|
|
10119
|
-
return results;
|
|
10120
|
-
}
|
|
10121
|
-
async function fetchLendingRates(registry, asset) {
|
|
10122
|
-
const chainKeys = Array.from(registry.chains.keys());
|
|
10123
|
-
const tasks = chainKeys.map(async (ck) => {
|
|
10124
|
-
try {
|
|
10125
|
-
const chain = registry.getChain(ck);
|
|
10126
|
-
const chainName = chain.name.toLowerCase();
|
|
10127
|
-
let assetAddr;
|
|
10128
|
-
try {
|
|
10129
|
-
assetAddr = registry.resolveToken(chainName, asset).address;
|
|
10130
|
-
} catch {
|
|
10131
|
-
return [];
|
|
10132
|
-
}
|
|
10133
|
-
const protos = registry.getProtocolsForChain(chainName).filter((p) => p.category === ProtocolCategory.Lending && p.interface === "aave_v3");
|
|
10134
|
-
if (protos.length === 0) return [];
|
|
10135
|
-
const rpc = chain.effectiveRpcUrl();
|
|
10136
|
-
const rates = [];
|
|
10137
|
-
for (const proto of protos) {
|
|
10138
|
-
try {
|
|
10139
|
-
const lending = createLending(proto, rpc);
|
|
10140
|
-
const r = await lending.getRates(assetAddr);
|
|
10141
|
-
if (r.supply_apy > 0) {
|
|
10142
|
-
rates.push({
|
|
10143
|
-
type: "lending_supply",
|
|
10144
|
-
asset,
|
|
10145
|
-
apy: round25(r.supply_apy * 100),
|
|
10146
|
-
detail: `${r.protocol} (${chain.name})`,
|
|
10147
|
-
risk: "low",
|
|
10148
|
-
source: "defi-cli"
|
|
10149
|
-
});
|
|
10150
|
-
}
|
|
10151
|
-
} catch {
|
|
10152
|
-
}
|
|
10153
|
-
}
|
|
10154
|
-
return rates;
|
|
10155
|
-
} catch {
|
|
10156
|
-
return [];
|
|
10157
|
-
}
|
|
10158
|
-
});
|
|
10159
|
-
const nested = await Promise.all(tasks);
|
|
10160
|
-
return nested.flat();
|
|
10161
|
-
}
|
|
10162
|
-
function registerCompare(parent, getOpts) {
|
|
10163
|
-
parent.command("compare").description("Compare all yield sources: perp funding vs lending APY vs staking").option("--asset <token>", "Token symbol to compare (e.g. USDC, ETH)", "USDC").option("--no-perps", "Exclude perp funding rates").option("--no-lending", "Exclude lending rates").option("--min-apy <pct>", "Minimum absolute APY to show", "1.0").action(async (opts) => {
|
|
10164
|
-
try {
|
|
10165
|
-
const registry = Registry.loadEmbedded();
|
|
10166
|
-
const asset = opts.asset ?? "USDC";
|
|
10167
|
-
const includePerps = opts.perps !== false;
|
|
10168
|
-
const includeLending = opts.lending !== false;
|
|
10169
|
-
const minApy = parseFloat(opts.minApy ?? "1.0");
|
|
10170
|
-
const t0 = Date.now();
|
|
10171
|
-
const opportunities = [];
|
|
10172
|
-
if (includePerps) {
|
|
10173
|
-
try {
|
|
10174
|
-
const perpData = await fetchPerpRates();
|
|
10175
|
-
for (const opp of perpData) {
|
|
10176
|
-
const apy = Math.abs(opp["apy"] ?? 0);
|
|
10177
|
-
if (apy >= minApy) opportunities.push(opp);
|
|
10178
|
-
}
|
|
10179
|
-
} catch {
|
|
10180
|
-
}
|
|
10181
|
-
}
|
|
10182
|
-
if (includeLending) {
|
|
10183
|
-
const lendingData = await fetchLendingRates(registry, asset);
|
|
10184
|
-
for (const opp of lendingData) {
|
|
10185
|
-
const apy = Math.abs(opp["apy"] ?? 0);
|
|
10186
|
-
if (apy >= minApy) opportunities.push(opp);
|
|
10187
|
-
}
|
|
10188
|
-
}
|
|
10189
|
-
opportunities.sort((a, b) => {
|
|
10190
|
-
const aApy = Math.abs(a["apy"] ?? 0);
|
|
10191
|
-
const bApy = Math.abs(b["apy"] ?? 0);
|
|
10192
|
-
return bApy - aApy;
|
|
10193
|
-
});
|
|
10194
|
-
const scanMs = Date.now() - t0;
|
|
10195
|
-
printOutput(
|
|
10196
|
-
{
|
|
10197
|
-
asset,
|
|
10198
|
-
scan_duration_ms: scanMs,
|
|
10199
|
-
total_opportunities: opportunities.length,
|
|
10200
|
-
opportunities
|
|
10201
|
-
},
|
|
10202
|
-
getOpts()
|
|
10203
|
-
);
|
|
10204
|
-
} catch (err) {
|
|
10205
|
-
printOutput({ error: String(err) }, getOpts());
|
|
10206
|
-
process.exit(1);
|
|
10207
|
-
}
|
|
10208
|
-
});
|
|
10209
|
-
}
|
|
10210
|
-
|
|
10211
|
-
// src/commands/swap.ts
|
|
10212
|
-
var ODOS_API = "https://api.odos.xyz";
|
|
10213
|
-
function registerSwap(parent, getOpts, makeExecutor2) {
|
|
10214
|
-
parent.command("swap").description("Aggregator swap: best price across all DEXes (ODOS)").requiredOption("--token-in <token>", "Input token symbol or address").requiredOption("--token-out <token>", "Output token symbol or address").requiredOption("--amount <amount>", "Amount of input token in wei").option("--slippage <bps>", "Slippage tolerance in basis points", "50").option("--recipient <address>", "Recipient address").action(async (opts) => {
|
|
10215
|
-
const executor = makeExecutor2();
|
|
10216
|
-
const chainName = parent.opts().chain ?? "hyperevm";
|
|
10217
|
-
const registry = Registry.loadEmbedded();
|
|
10218
|
-
const chain = registry.getChain(chainName);
|
|
10219
|
-
const tokenIn = opts.tokenIn.startsWith("0x") ? opts.tokenIn : registry.resolveToken(chainName, opts.tokenIn).address;
|
|
10220
|
-
const tokenOut = opts.tokenOut.startsWith("0x") ? opts.tokenOut : registry.resolveToken(chainName, opts.tokenOut).address;
|
|
10221
|
-
const sender = opts.recipient ?? process.env.DEFI_WALLET_ADDRESS ?? "0x0000000000000000000000000000000000000001";
|
|
10222
|
-
try {
|
|
10223
|
-
const quoteRes = await fetch(`${ODOS_API}/sor/quote/v2`, {
|
|
10224
|
-
method: "POST",
|
|
10225
|
-
headers: { "Content-Type": "application/json" },
|
|
10226
|
-
body: JSON.stringify({
|
|
10227
|
-
chainId: chain.chain_id,
|
|
10228
|
-
inputTokens: [{ tokenAddress: tokenIn, amount: opts.amount }],
|
|
10229
|
-
outputTokens: [{ tokenAddress: tokenOut, proportion: 1 }],
|
|
10230
|
-
slippageLimitPercent: parseInt(opts.slippage) / 100,
|
|
10231
|
-
userAddr: sender
|
|
10232
|
-
})
|
|
10233
|
-
});
|
|
10234
|
-
const quote = await quoteRes.json();
|
|
10235
|
-
if (!quote.pathId) {
|
|
10236
|
-
printOutput({ error: "No ODOS route found", quote }, getOpts());
|
|
10237
|
-
return;
|
|
10238
|
-
}
|
|
10239
|
-
const assembleRes = await fetch(`${ODOS_API}/sor/assemble`, {
|
|
10240
|
-
method: "POST",
|
|
10241
|
-
headers: { "Content-Type": "application/json" },
|
|
10242
|
-
body: JSON.stringify({ pathId: quote.pathId, userAddr: sender })
|
|
10243
|
-
});
|
|
10244
|
-
const assembled = await assembleRes.json();
|
|
10245
|
-
if (assembled.transaction) {
|
|
10246
|
-
const tx = {
|
|
10247
|
-
description: `ODOS swap ${tokenIn} \u2192 ${tokenOut}`,
|
|
10248
|
-
to: assembled.transaction.to,
|
|
10249
|
-
data: assembled.transaction.data,
|
|
10250
|
-
value: BigInt(assembled.transaction.value ?? 0)
|
|
10251
|
-
};
|
|
10252
|
-
const result = await executor.execute(tx);
|
|
10253
|
-
printOutput({ ...result, odos_quote: quote }, getOpts());
|
|
10254
|
-
} else {
|
|
10255
|
-
printOutput({ error: "ODOS assembly failed", assembled }, getOpts());
|
|
10256
|
-
}
|
|
10257
|
-
} catch (e) {
|
|
10258
|
-
printOutput({ error: `ODOS API error: ${e instanceof Error ? e.message : String(e)}` }, getOpts());
|
|
10259
|
-
}
|
|
10260
|
-
});
|
|
10261
|
-
}
|
|
10262
|
-
|
|
10263
9746
|
// src/commands/bridge.ts
|
|
10264
9747
|
var LIFI_API = "https://li.quest/v1";
|
|
10265
9748
|
var DLN_API = "https://dln.debridge.finance/v1.0/dln/order";
|
|
@@ -10485,250 +9968,6 @@ function registerBridge(parent, getOpts) {
|
|
|
10485
9968
|
});
|
|
10486
9969
|
}
|
|
10487
9970
|
|
|
10488
|
-
// src/commands/nft.ts
|
|
10489
|
-
function registerNft(parent, getOpts) {
|
|
10490
|
-
const nft = parent.command("nft").description("NFT operations: collection info, ownership, balance");
|
|
10491
|
-
nft.command("info").description("Get NFT collection info (name, symbol, total supply)").requiredOption("--collection <address>", "NFT collection contract address").action(async (opts) => {
|
|
10492
|
-
const chainName = parent.opts().chain ?? "hyperevm";
|
|
10493
|
-
const registry = Registry.loadEmbedded();
|
|
10494
|
-
const chain = registry.getChain(chainName);
|
|
10495
|
-
const nftProtocols = registry.getProtocolsByCategory("nft").filter((p) => p.chain === chainName);
|
|
10496
|
-
const entry = nftProtocols[0] ?? { name: "ERC721", slug: "erc721", category: "nft", interface: "erc721", chain: chainName, contracts: { collection: opts.collection } };
|
|
10497
|
-
try {
|
|
10498
|
-
const adapter = createNft(entry, chain.effectiveRpcUrl());
|
|
10499
|
-
const info = await adapter.getCollectionInfo(opts.collection);
|
|
10500
|
-
printOutput(info, getOpts());
|
|
10501
|
-
} catch (e) {
|
|
10502
|
-
printOutput({ error: e instanceof Error ? e.message : String(e) }, getOpts());
|
|
10503
|
-
}
|
|
10504
|
-
});
|
|
10505
|
-
nft.command("owner").description("Check who owns a specific NFT token ID").requiredOption("--collection <address>", "NFT collection contract address").requiredOption("--token-id <id>", "Token ID").action(async (opts) => {
|
|
10506
|
-
const chainName = parent.opts().chain ?? "hyperevm";
|
|
10507
|
-
const registry = Registry.loadEmbedded();
|
|
10508
|
-
const chain = registry.getChain(chainName);
|
|
10509
|
-
const nftProtocols = registry.getProtocolsByCategory("nft").filter((p) => p.chain === chainName);
|
|
10510
|
-
const entry = nftProtocols[0] ?? { name: "ERC721", slug: "erc721", category: "nft", interface: "erc721", chain: chainName, contracts: { collection: opts.collection } };
|
|
10511
|
-
try {
|
|
10512
|
-
const adapter = createNft(entry, chain.effectiveRpcUrl());
|
|
10513
|
-
const info = await adapter.getTokenInfo(opts.collection, BigInt(opts.tokenId));
|
|
10514
|
-
printOutput(info, getOpts());
|
|
10515
|
-
} catch (e) {
|
|
10516
|
-
printOutput({ error: e instanceof Error ? e.message : String(e) }, getOpts());
|
|
10517
|
-
}
|
|
10518
|
-
});
|
|
10519
|
-
nft.command("balance").description("Check how many NFTs an address holds in a collection").requiredOption("--collection <address>", "NFT collection contract address").requiredOption("--owner <address>", "Owner address to query").action(async (opts) => {
|
|
10520
|
-
const chainName = parent.opts().chain ?? "hyperevm";
|
|
10521
|
-
const registry = Registry.loadEmbedded();
|
|
10522
|
-
const chain = registry.getChain(chainName);
|
|
10523
|
-
const nftProtocols = registry.getProtocolsByCategory("nft").filter((p) => p.chain === chainName);
|
|
10524
|
-
const entry = nftProtocols[0] ?? { name: "ERC721", slug: "erc721", category: "nft", interface: "erc721", chain: chainName, contracts: { collection: opts.collection } };
|
|
10525
|
-
try {
|
|
10526
|
-
const adapter = createNft(entry, chain.effectiveRpcUrl());
|
|
10527
|
-
const balance = await adapter.getBalance(opts.owner, opts.collection);
|
|
10528
|
-
printOutput({ collection: opts.collection, owner: opts.owner, balance }, getOpts());
|
|
10529
|
-
} catch (e) {
|
|
10530
|
-
printOutput({ error: e instanceof Error ? e.message : String(e) }, getOpts());
|
|
10531
|
-
}
|
|
10532
|
-
});
|
|
10533
|
-
nft.command("uri").description("Get token URI for a specific NFT").requiredOption("--collection <address>", "NFT collection contract address").requiredOption("--token-id <id>", "Token ID").action(async (opts) => {
|
|
10534
|
-
const chainName = parent.opts().chain ?? "hyperevm";
|
|
10535
|
-
const registry = Registry.loadEmbedded();
|
|
10536
|
-
const chain = registry.getChain(chainName);
|
|
10537
|
-
const nftProtocols = registry.getProtocolsByCategory("nft").filter((p) => p.chain === chainName);
|
|
10538
|
-
const entry = nftProtocols[0] ?? { name: "ERC721", slug: "erc721", category: "nft", interface: "erc721", chain: chainName, contracts: { collection: opts.collection } };
|
|
10539
|
-
try {
|
|
10540
|
-
const adapter = createNft(entry, chain.effectiveRpcUrl());
|
|
10541
|
-
const info = await adapter.getTokenInfo(opts.collection, BigInt(opts.tokenId));
|
|
10542
|
-
printOutput({ collection: opts.collection, token_id: opts.tokenId, token_uri: info.token_uri }, getOpts());
|
|
10543
|
-
} catch (e) {
|
|
10544
|
-
printOutput({ error: e instanceof Error ? e.message : String(e) }, getOpts());
|
|
10545
|
-
}
|
|
10546
|
-
});
|
|
10547
|
-
}
|
|
10548
|
-
|
|
10549
|
-
// src/commands/farm.ts
|
|
10550
|
-
function registerFarm(parent, getOpts, makeExecutor2) {
|
|
10551
|
-
const farm = parent.command("farm").description("LP farm operations: deposit, withdraw, claim rewards (MasterChef)");
|
|
10552
|
-
farm.command("deposit").description("Deposit LP tokens into a MasterChef farm").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pid <pid>", "Farm pool ID").requiredOption("--amount <amount>", "LP token amount in wei").action(async (opts) => {
|
|
10553
|
-
const executor = makeExecutor2();
|
|
10554
|
-
const registry = Registry.loadEmbedded();
|
|
10555
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
10556
|
-
const chainName = parent.opts().chain;
|
|
10557
|
-
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10558
|
-
const rpcUrl = chain.effectiveRpcUrl();
|
|
10559
|
-
const adapter = createMasterChef(protocol, rpcUrl);
|
|
10560
|
-
const tx = await adapter.buildDeposit(
|
|
10561
|
-
protocol.contracts?.["masterchef"],
|
|
10562
|
-
BigInt(opts.amount),
|
|
10563
|
-
BigInt(opts.pid)
|
|
10564
|
-
);
|
|
10565
|
-
const result = await executor.execute(tx);
|
|
10566
|
-
printOutput(result, getOpts());
|
|
10567
|
-
});
|
|
10568
|
-
farm.command("withdraw").description("Withdraw LP tokens from a MasterChef farm").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pid <pid>", "Farm pool ID").requiredOption("--amount <amount>", "LP token amount in wei").action(async (opts) => {
|
|
10569
|
-
const executor = makeExecutor2();
|
|
10570
|
-
const registry = Registry.loadEmbedded();
|
|
10571
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
10572
|
-
const chainName = parent.opts().chain;
|
|
10573
|
-
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10574
|
-
const rpcUrl = chain.effectiveRpcUrl();
|
|
10575
|
-
const adapter = createMasterChef(protocol, rpcUrl);
|
|
10576
|
-
const tx = await adapter.buildWithdrawPid(
|
|
10577
|
-
BigInt(opts.pid),
|
|
10578
|
-
BigInt(opts.amount)
|
|
10579
|
-
);
|
|
10580
|
-
const result = await executor.execute(tx);
|
|
10581
|
-
printOutput(result, getOpts());
|
|
10582
|
-
});
|
|
10583
|
-
farm.command("claim").description("Claim pending rewards from a MasterChef farm").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pid <pid>", "Farm pool ID").action(async (opts) => {
|
|
10584
|
-
const executor = makeExecutor2();
|
|
10585
|
-
const registry = Registry.loadEmbedded();
|
|
10586
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
10587
|
-
const chainName = parent.opts().chain;
|
|
10588
|
-
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10589
|
-
const rpcUrl = chain.effectiveRpcUrl();
|
|
10590
|
-
const adapter = createMasterChef(protocol, rpcUrl);
|
|
10591
|
-
const tx = await adapter.buildClaimRewardsPid(
|
|
10592
|
-
BigInt(opts.pid)
|
|
10593
|
-
);
|
|
10594
|
-
const result = await executor.execute(tx);
|
|
10595
|
-
printOutput(result, getOpts());
|
|
10596
|
-
});
|
|
10597
|
-
farm.command("info").description("Show pending rewards and farm info").requiredOption("--protocol <protocol>", "Protocol slug").option("--pid <pid>", "Farm pool ID (optional)").option("--address <address>", "Wallet address to query (defaults to DEFI_WALLET_ADDRESS env)").action(async (opts) => {
|
|
10598
|
-
const registry = Registry.loadEmbedded();
|
|
10599
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
10600
|
-
const chainName = parent.opts().chain;
|
|
10601
|
-
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10602
|
-
const rpcUrl = chain.effectiveRpcUrl();
|
|
10603
|
-
const adapter = createMasterChef(protocol, rpcUrl);
|
|
10604
|
-
const walletAddress = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
|
|
10605
|
-
if (!walletAddress) {
|
|
10606
|
-
throw new Error("--address or DEFI_WALLET_ADDRESS required");
|
|
10607
|
-
}
|
|
10608
|
-
const masterchef = protocol.contracts?.["masterchef"];
|
|
10609
|
-
const rewards = await adapter.getPendingRewards(masterchef, walletAddress);
|
|
10610
|
-
printOutput(rewards, getOpts());
|
|
10611
|
-
});
|
|
10612
|
-
}
|
|
10613
|
-
|
|
10614
|
-
// src/commands/farming.ts
|
|
10615
|
-
import { privateKeyToAccount as privateKeyToAccount3 } from "viem/accounts";
|
|
10616
|
-
function registerFarming(parent, getOpts, makeExecutor2) {
|
|
10617
|
-
const farming = parent.command("farming").description("Algebra eternal farming operations (KittenSwap): enter, exit, collect rewards, claim, discover");
|
|
10618
|
-
farming.command("enter").description("Enter farming: stake an NFT position to start earning rewards").requiredOption("--protocol <protocol>", "Protocol slug (e.g. kittenswap)").requiredOption("--pool <address>", "Pool address").requiredOption("--token-id <id>", "NFT position token ID").option("--owner <address>", "Owner address to receive claimed rewards (defaults to DEFI_WALLET_ADDRESS or private key address)").action(async (opts) => {
|
|
10619
|
-
const executor = makeExecutor2();
|
|
10620
|
-
const registry = Registry.loadEmbedded();
|
|
10621
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
10622
|
-
const chainName = parent.opts().chain;
|
|
10623
|
-
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10624
|
-
const rpcUrl = chain.effectiveRpcUrl();
|
|
10625
|
-
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10626
|
-
const owner = resolveOwner(opts.owner);
|
|
10627
|
-
const tx = await adapter.buildEnterFarming(
|
|
10628
|
-
BigInt(opts.tokenId),
|
|
10629
|
-
opts.pool,
|
|
10630
|
-
owner
|
|
10631
|
-
);
|
|
10632
|
-
const result = await executor.execute(tx);
|
|
10633
|
-
printOutput(result, getOpts());
|
|
10634
|
-
});
|
|
10635
|
-
farming.command("exit").description("Exit farming: unstake an NFT position").requiredOption("--protocol <protocol>", "Protocol slug (e.g. kittenswap)").requiredOption("--pool <address>", "Pool address").requiredOption("--token-id <id>", "NFT position token ID").action(async (opts) => {
|
|
10636
|
-
const executor = makeExecutor2();
|
|
10637
|
-
const registry = Registry.loadEmbedded();
|
|
10638
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
10639
|
-
const chainName = parent.opts().chain;
|
|
10640
|
-
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10641
|
-
const rpcUrl = chain.effectiveRpcUrl();
|
|
10642
|
-
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10643
|
-
const tx = await adapter.buildExitFarming(
|
|
10644
|
-
BigInt(opts.tokenId),
|
|
10645
|
-
opts.pool
|
|
10646
|
-
);
|
|
10647
|
-
const result = await executor.execute(tx);
|
|
10648
|
-
printOutput(result, getOpts());
|
|
10649
|
-
});
|
|
10650
|
-
farming.command("rewards").description("Collect + claim farming rewards for a staked position (collectRewards + claimReward multicall)").requiredOption("--protocol <protocol>", "Protocol slug (e.g. kittenswap)").requiredOption("--pool <address>", "Pool address").requiredOption("--token-id <id>", "NFT position token ID").option("--owner <address>", "Owner address to receive claimed rewards (defaults to DEFI_WALLET_ADDRESS or private key address)").action(async (opts) => {
|
|
10651
|
-
const executor = makeExecutor2();
|
|
10652
|
-
const registry = Registry.loadEmbedded();
|
|
10653
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
10654
|
-
const chainName = parent.opts().chain;
|
|
10655
|
-
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10656
|
-
const rpcUrl = chain.effectiveRpcUrl();
|
|
10657
|
-
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10658
|
-
const owner = resolveOwner(opts.owner);
|
|
10659
|
-
const tx = await adapter.buildCollectRewards(
|
|
10660
|
-
BigInt(opts.tokenId),
|
|
10661
|
-
opts.pool,
|
|
10662
|
-
owner
|
|
10663
|
-
);
|
|
10664
|
-
const result = await executor.execute(tx);
|
|
10665
|
-
printOutput(result, getOpts());
|
|
10666
|
-
});
|
|
10667
|
-
farming.command("claim").description("Claim accumulated farming rewards (KITTEN + WHYPE) without changing position").requiredOption("--protocol <protocol>", "Protocol slug (e.g. kittenswap)").option("--owner <address>", "Owner address to receive rewards (defaults to DEFI_WALLET_ADDRESS or private key address)").action(async (opts) => {
|
|
10668
|
-
const executor = makeExecutor2();
|
|
10669
|
-
const registry = Registry.loadEmbedded();
|
|
10670
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
10671
|
-
const chainName = parent.opts().chain;
|
|
10672
|
-
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10673
|
-
const rpcUrl = chain.effectiveRpcUrl();
|
|
10674
|
-
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10675
|
-
const owner = resolveOwner(opts.owner);
|
|
10676
|
-
const tx = await adapter.buildClaimReward(owner);
|
|
10677
|
-
const result = await executor.execute(tx);
|
|
10678
|
-
printOutput(result, getOpts());
|
|
10679
|
-
});
|
|
10680
|
-
farming.command("pending").description("Query pending farming rewards for a position (read-only)").requiredOption("--protocol <protocol>", "Protocol slug (e.g. kittenswap)").requiredOption("--pool <address>", "Pool address").requiredOption("--token-id <id>", "NFT position token ID").action(async (opts) => {
|
|
10681
|
-
const registry = Registry.loadEmbedded();
|
|
10682
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
10683
|
-
const chainName = parent.opts().chain;
|
|
10684
|
-
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10685
|
-
const rpcUrl = chain.effectiveRpcUrl();
|
|
10686
|
-
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10687
|
-
const rewards = await adapter.getPendingRewards(
|
|
10688
|
-
BigInt(opts.tokenId),
|
|
10689
|
-
opts.pool
|
|
10690
|
-
);
|
|
10691
|
-
printOutput(
|
|
10692
|
-
{
|
|
10693
|
-
tokenId: opts.tokenId,
|
|
10694
|
-
pool: opts.pool,
|
|
10695
|
-
reward_kitten: rewards.reward.toString(),
|
|
10696
|
-
bonus_reward_whype: rewards.bonusReward.toString()
|
|
10697
|
-
},
|
|
10698
|
-
getOpts()
|
|
10699
|
-
);
|
|
10700
|
-
});
|
|
10701
|
-
farming.command("discover").description("Discover all pools with active KittenSwap farming incentives").requiredOption("--protocol <protocol>", "Protocol slug (e.g. kittenswap)").action(async (opts) => {
|
|
10702
|
-
const registry = Registry.loadEmbedded();
|
|
10703
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
10704
|
-
const chainName = parent.opts().chain;
|
|
10705
|
-
const chain = registry.getChain(chainName ?? "hyperevm");
|
|
10706
|
-
const rpcUrl = chain.effectiveRpcUrl();
|
|
10707
|
-
const adapter = createKittenSwapFarming(protocol, rpcUrl);
|
|
10708
|
-
const pools = await adapter.discoverFarmingPools();
|
|
10709
|
-
const output = pools.map((p) => ({
|
|
10710
|
-
pool: p.pool,
|
|
10711
|
-
nonce: p.key.nonce.toString(),
|
|
10712
|
-
total_reward: p.totalReward.toString(),
|
|
10713
|
-
bonus_reward: p.bonusReward.toString(),
|
|
10714
|
-
active: p.active
|
|
10715
|
-
}));
|
|
10716
|
-
printOutput(output, getOpts());
|
|
10717
|
-
});
|
|
10718
|
-
}
|
|
10719
|
-
function resolveOwner(optOwner) {
|
|
10720
|
-
if (optOwner) return optOwner;
|
|
10721
|
-
const walletAddr = process.env["DEFI_WALLET_ADDRESS"];
|
|
10722
|
-
if (walletAddr) return walletAddr;
|
|
10723
|
-
const privateKey = process.env["DEFI_PRIVATE_KEY"];
|
|
10724
|
-
if (privateKey) {
|
|
10725
|
-
return privateKeyToAccount3(privateKey).address;
|
|
10726
|
-
}
|
|
10727
|
-
throw new Error(
|
|
10728
|
-
"--owner, DEFI_WALLET_ADDRESS, or DEFI_PRIVATE_KEY is required to resolve reward recipient"
|
|
10729
|
-
);
|
|
10730
|
-
}
|
|
10731
|
-
|
|
10732
9971
|
// src/commands/setup.ts
|
|
10733
9972
|
import pc2 from "picocolors";
|
|
10734
9973
|
import { createInterface } from "readline";
|
|
@@ -10777,8 +10016,8 @@ function isValidPrivateKey(s) {
|
|
|
10777
10016
|
}
|
|
10778
10017
|
async function deriveAddress(privateKey) {
|
|
10779
10018
|
try {
|
|
10780
|
-
const { privateKeyToAccount:
|
|
10781
|
-
const account =
|
|
10019
|
+
const { privateKeyToAccount: privateKeyToAccount3 } = await import("viem/accounts");
|
|
10020
|
+
const account = privateKeyToAccount3(privateKey);
|
|
10782
10021
|
return account.address;
|
|
10783
10022
|
} catch {
|
|
10784
10023
|
return null;
|
|
@@ -10873,107 +10112,6 @@ function registerSetup(program2) {
|
|
|
10873
10112
|
});
|
|
10874
10113
|
}
|
|
10875
10114
|
|
|
10876
|
-
// src/commands/lb.ts
|
|
10877
|
-
function registerLB(parent, getOpts, makeExecutor2) {
|
|
10878
|
-
const lb = parent.command("lb").description("Merchant Moe Liquidity Book: add/remove liquidity, rewards, positions");
|
|
10879
|
-
lb.command("add").description("Add liquidity to a Liquidity Book pair").requiredOption("--protocol <protocol>", "Protocol slug (e.g. merchantmoe-mantle)").requiredOption("--pool <address>", "LB pair address").requiredOption("--token-x <address>", "Token X address").requiredOption("--token-y <address>", "Token Y address").requiredOption("--bin-step <step>", "Bin step of the pair").option("--amount-x <wei>", "Amount of token X in wei", "0").option("--amount-y <wei>", "Amount of token Y in wei", "0").option("--bins <N>", "Number of bins on each side of active bin", "5").option("--active-id <id>", "Active bin id (defaults to on-chain query)").option("--recipient <address>", "Recipient address").action(async (opts) => {
|
|
10880
|
-
const executor = makeExecutor2();
|
|
10881
|
-
const registry = Registry.loadEmbedded();
|
|
10882
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
10883
|
-
const chainName = parent.opts().chain;
|
|
10884
|
-
const chain = registry.getChain(chainName ?? "mantle");
|
|
10885
|
-
const rpcUrl = chain.effectiveRpcUrl();
|
|
10886
|
-
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
10887
|
-
const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
|
|
10888
|
-
const tx = await adapter.buildAddLiquidity({
|
|
10889
|
-
pool: opts.pool,
|
|
10890
|
-
tokenX: opts.tokenX,
|
|
10891
|
-
tokenY: opts.tokenY,
|
|
10892
|
-
binStep: parseInt(opts.binStep),
|
|
10893
|
-
amountX: BigInt(opts.amountX),
|
|
10894
|
-
amountY: BigInt(opts.amountY),
|
|
10895
|
-
numBins: parseInt(opts.bins),
|
|
10896
|
-
activeIdDesired: opts.activeId ? parseInt(opts.activeId) : void 0,
|
|
10897
|
-
recipient
|
|
10898
|
-
});
|
|
10899
|
-
const result = await executor.execute(tx);
|
|
10900
|
-
printOutput(result, getOpts());
|
|
10901
|
-
});
|
|
10902
|
-
lb.command("remove").description("Remove liquidity from Liquidity Book bins").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--token-x <address>", "Token X address").requiredOption("--token-y <address>", "Token Y address").requiredOption("--bin-step <step>", "Bin step of the pair").requiredOption("--bins <binIds>", "Comma-separated bin IDs to remove from").requiredOption("--amounts <amounts>", "Comma-separated LB token amounts to remove per bin (wei)").option("--recipient <address>", "Recipient address").action(async (opts) => {
|
|
10903
|
-
const executor = makeExecutor2();
|
|
10904
|
-
const registry = Registry.loadEmbedded();
|
|
10905
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
10906
|
-
const adapter = createMerchantMoeLB(protocol);
|
|
10907
|
-
const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
|
|
10908
|
-
const binIds = opts.bins.split(",").map((s) => parseInt(s.trim()));
|
|
10909
|
-
const amounts = opts.amounts.split(",").map((s) => BigInt(s.trim()));
|
|
10910
|
-
const tx = await adapter.buildRemoveLiquidity({
|
|
10911
|
-
tokenX: opts.tokenX,
|
|
10912
|
-
tokenY: opts.tokenY,
|
|
10913
|
-
binStep: parseInt(opts.binStep),
|
|
10914
|
-
binIds,
|
|
10915
|
-
amounts,
|
|
10916
|
-
recipient
|
|
10917
|
-
});
|
|
10918
|
-
const result = await executor.execute(tx);
|
|
10919
|
-
printOutput(result, getOpts());
|
|
10920
|
-
});
|
|
10921
|
-
lb.command("rewards").description("Show pending MOE rewards for a pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "LB pair address").option("--bins <binIds>", "Comma-separated bin IDs to check (auto-detected from rewarder range if omitted)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
|
|
10922
|
-
const registry = Registry.loadEmbedded();
|
|
10923
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
10924
|
-
const chainName = parent.opts().chain;
|
|
10925
|
-
const chain = registry.getChain(chainName ?? "mantle");
|
|
10926
|
-
const rpcUrl = chain.effectiveRpcUrl();
|
|
10927
|
-
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
10928
|
-
const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
|
|
10929
|
-
if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
|
|
10930
|
-
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
10931
|
-
const rewards = await adapter.getPendingRewards(user, opts.pool, binIds);
|
|
10932
|
-
printOutput(rewards, getOpts());
|
|
10933
|
-
});
|
|
10934
|
-
lb.command("claim").description("Claim pending MOE rewards from a pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "LB pair address").option("--bins <binIds>", "Comma-separated bin IDs to claim from (auto-detected from rewarder range if omitted)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
|
|
10935
|
-
const executor = makeExecutor2();
|
|
10936
|
-
const registry = Registry.loadEmbedded();
|
|
10937
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
10938
|
-
const chainName = parent.opts().chain;
|
|
10939
|
-
const chain = registry.getChain(chainName ?? "mantle");
|
|
10940
|
-
const rpcUrl = chain.effectiveRpcUrl();
|
|
10941
|
-
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
10942
|
-
const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
|
|
10943
|
-
if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
|
|
10944
|
-
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
10945
|
-
const tx = await adapter.buildClaimRewards(user, opts.pool, binIds);
|
|
10946
|
-
const result = await executor.execute(tx);
|
|
10947
|
-
printOutput(result, getOpts());
|
|
10948
|
-
});
|
|
10949
|
-
lb.command("discover").description("Find all rewarded LB pools on chain").requiredOption("--protocol <protocol>", "Protocol slug").option("--active-only", "Only show non-stopped pools").action(async (opts) => {
|
|
10950
|
-
const registry = Registry.loadEmbedded();
|
|
10951
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
10952
|
-
const chainName = parent.opts().chain;
|
|
10953
|
-
const chain = registry.getChain(chainName ?? "mantle");
|
|
10954
|
-
const rpcUrl = chain.effectiveRpcUrl();
|
|
10955
|
-
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
10956
|
-
let pools = await adapter.discoverRewardedPools();
|
|
10957
|
-
if (opts.activeOnly) {
|
|
10958
|
-
pools = pools.filter((p) => !p.stopped);
|
|
10959
|
-
}
|
|
10960
|
-
printOutput(pools, getOpts());
|
|
10961
|
-
});
|
|
10962
|
-
lb.command("positions").description("Show user positions per bin in a LB pool").requiredOption("--protocol <protocol>", "Protocol slug").requiredOption("--pool <address>", "LB pair address").option("--bins <binIds>", "Comma-separated bin IDs to query (auto-detected from rewarder range or active \xB1 50 if omitted)").option("--address <address>", "Wallet address (defaults to DEFI_WALLET_ADDRESS)").action(async (opts) => {
|
|
10963
|
-
const registry = Registry.loadEmbedded();
|
|
10964
|
-
const protocol = registry.getProtocol(opts.protocol);
|
|
10965
|
-
const chainName = parent.opts().chain;
|
|
10966
|
-
const chain = registry.getChain(chainName ?? "mantle");
|
|
10967
|
-
const rpcUrl = chain.effectiveRpcUrl();
|
|
10968
|
-
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
10969
|
-
const user = opts.address ?? process.env["DEFI_WALLET_ADDRESS"];
|
|
10970
|
-
if (!user) throw new Error("--address or DEFI_WALLET_ADDRESS required");
|
|
10971
|
-
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
10972
|
-
const positions = await adapter.getUserPositions(user, opts.pool, binIds);
|
|
10973
|
-
printOutput(positions, getOpts());
|
|
10974
|
-
});
|
|
10975
|
-
}
|
|
10976
|
-
|
|
10977
10115
|
// src/cli.ts
|
|
10978
10116
|
var _require = createRequire(import.meta.url);
|
|
10979
10117
|
var _pkg = _require("../package.json");
|
|
@@ -10985,10 +10123,10 @@ var BANNER = `
|
|
|
10985
10123
|
\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551
|
|
10986
10124
|
\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D
|
|
10987
10125
|
|
|
10988
|
-
2 chains \xB7
|
|
10126
|
+
2 chains \xB7 21 protocols \xB7 by HypurrQuant
|
|
10989
10127
|
|
|
10990
|
-
|
|
10991
|
-
|
|
10128
|
+
Lending, LP provision, farming, gauges, vaults,
|
|
10129
|
+
yield comparison \u2014 all from your terminal.
|
|
10992
10130
|
`;
|
|
10993
10131
|
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", "hyperevm").option("--dry-run", "Dry-run mode (default, no broadcast)", true).option("--broadcast", "Actually broadcast the transaction");
|
|
10994
10132
|
function getOutputMode() {
|
|
@@ -11003,37 +10141,22 @@ function makeExecutor() {
|
|
|
11003
10141
|
}
|
|
11004
10142
|
registerStatus(program, getOutputMode);
|
|
11005
10143
|
registerSchema(program, getOutputMode);
|
|
11006
|
-
|
|
11007
|
-
registerGauge(program, getOutputMode, makeExecutor);
|
|
10144
|
+
registerLP(program, getOutputMode, makeExecutor);
|
|
11008
10145
|
registerLending(program, getOutputMode, makeExecutor);
|
|
11009
10146
|
registerCdp(program, getOutputMode, makeExecutor);
|
|
11010
|
-
registerStaking(program, getOutputMode, makeExecutor);
|
|
11011
10147
|
registerVault(program, getOutputMode, makeExecutor);
|
|
11012
10148
|
registerYield(program, getOutputMode, makeExecutor);
|
|
11013
10149
|
registerPortfolio(program, getOutputMode);
|
|
11014
10150
|
registerMonitor(program, getOutputMode);
|
|
11015
10151
|
registerAlert(program, getOutputMode);
|
|
11016
10152
|
registerScan(program, getOutputMode);
|
|
11017
|
-
registerArb(program, getOutputMode, makeExecutor);
|
|
11018
10153
|
registerPositions(program, getOutputMode);
|
|
11019
10154
|
registerPrice(program, getOutputMode);
|
|
11020
10155
|
registerWallet(program, getOutputMode);
|
|
11021
10156
|
registerToken(program, getOutputMode, makeExecutor);
|
|
11022
10157
|
registerWhales(program, getOutputMode);
|
|
11023
|
-
registerCompare(program, getOutputMode);
|
|
11024
|
-
registerSwap(program, getOutputMode, makeExecutor);
|
|
11025
10158
|
registerBridge(program, getOutputMode);
|
|
11026
|
-
registerNft(program, getOutputMode);
|
|
11027
|
-
registerFarm(program, getOutputMode, makeExecutor);
|
|
11028
|
-
registerFarming(program, getOutputMode, makeExecutor);
|
|
11029
|
-
registerLB(program, getOutputMode, makeExecutor);
|
|
11030
10159
|
registerSetup(program);
|
|
11031
|
-
program.command("agent").description("Agent mode: read JSON commands from stdin (for AI agents)").action(async () => {
|
|
11032
|
-
const executor = makeExecutor();
|
|
11033
|
-
process.stderr.write("Agent mode: reading JSON commands from stdin...\n");
|
|
11034
|
-
process.stderr.write("Agent mode not yet fully implemented in TS port.\n");
|
|
11035
|
-
process.exit(1);
|
|
11036
|
-
});
|
|
11037
10160
|
|
|
11038
10161
|
// src/landing.ts
|
|
11039
10162
|
import pc3 from "picocolors";
|
|
@@ -11213,30 +10336,21 @@ async function main() {
|
|
|
11213
10336
|
const knownSubcommands = /* @__PURE__ */ new Set([
|
|
11214
10337
|
"status",
|
|
11215
10338
|
"schema",
|
|
11216
|
-
"
|
|
11217
|
-
"gauge",
|
|
10339
|
+
"lp",
|
|
11218
10340
|
"lending",
|
|
11219
10341
|
"cdp",
|
|
11220
|
-
"staking",
|
|
11221
10342
|
"vault",
|
|
11222
10343
|
"yield",
|
|
11223
10344
|
"portfolio",
|
|
11224
10345
|
"monitor",
|
|
11225
10346
|
"alert",
|
|
11226
10347
|
"scan",
|
|
11227
|
-
"arb",
|
|
11228
10348
|
"positions",
|
|
11229
10349
|
"price",
|
|
11230
10350
|
"wallet",
|
|
11231
10351
|
"token",
|
|
11232
10352
|
"whales",
|
|
11233
|
-
"compare",
|
|
11234
|
-
"swap",
|
|
11235
10353
|
"bridge",
|
|
11236
|
-
"nft",
|
|
11237
|
-
"farm",
|
|
11238
|
-
"farming",
|
|
11239
|
-
"lb",
|
|
11240
10354
|
"agent",
|
|
11241
10355
|
"setup",
|
|
11242
10356
|
"init"
|