@hypurrquant/defi-cli 1.0.7 → 1.0.8
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 +121 -35
- package/dist/index.js.map +1 -1
- package/dist/main.js +121 -35
- package/dist/main.js.map +1 -1
- package/dist/mcp-server.js +102 -30
- package/dist/mcp-server.js.map +1 -1
- package/package.json +1 -1
- package/skills/defi-cli/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4077,6 +4077,79 @@ var init_dist2 = __esm({
|
|
|
4077
4077
|
gas_estimate: 3e5
|
|
4078
4078
|
};
|
|
4079
4079
|
}
|
|
4080
|
+
/**
|
|
4081
|
+
* List every LB pair from the factory with basic pair info (no rewarder /
|
|
4082
|
+
* APR enrichment). Useful when the factory has pools but none have hooks
|
|
4083
|
+
* deployed yet (e.g. early-stage Monad TraderJoe).
|
|
4084
|
+
*
|
|
4085
|
+
* Three multicall batches: pair addresses, token addresses, token symbols.
|
|
4086
|
+
*/
|
|
4087
|
+
async discoverAllPools() {
|
|
4088
|
+
const rpcUrl = this.requireRpc();
|
|
4089
|
+
const client = createPublicClient8({ transport: http8(rpcUrl) });
|
|
4090
|
+
const pairCount = await client.readContract({
|
|
4091
|
+
address: this.lbFactory,
|
|
4092
|
+
abi: lbFactoryAbi,
|
|
4093
|
+
functionName: "getNumberOfLBPairs"
|
|
4094
|
+
});
|
|
4095
|
+
const count = Number(pairCount);
|
|
4096
|
+
if (count === 0) return [];
|
|
4097
|
+
const indexCalls = Array.from({ length: count }, (_, i) => [
|
|
4098
|
+
this.lbFactory,
|
|
4099
|
+
encodeFunctionData12({ abi: lbFactoryAbi, functionName: "getLBPairAtIndex", args: [BigInt(i)] })
|
|
4100
|
+
]);
|
|
4101
|
+
const indexResults = await multicallRead(rpcUrl, indexCalls);
|
|
4102
|
+
const pairs = indexResults.map((r) => decodeAddressResult(r)).filter((a) => a !== null);
|
|
4103
|
+
if (pairs.length === 0) return [];
|
|
4104
|
+
const tokenCalls = [];
|
|
4105
|
+
for (const pool of pairs) {
|
|
4106
|
+
tokenCalls.push([pool, encodeFunctionData12({ abi: lbPairAbi, functionName: "getTokenX" })]);
|
|
4107
|
+
tokenCalls.push([pool, encodeFunctionData12({ abi: lbPairAbi, functionName: "getTokenY" })]);
|
|
4108
|
+
}
|
|
4109
|
+
const tokenResults = await multicallRead(rpcUrl, tokenCalls);
|
|
4110
|
+
const tokensX = [];
|
|
4111
|
+
const tokensY = [];
|
|
4112
|
+
for (let i = 0; i < pairs.length; i++) {
|
|
4113
|
+
tokensX.push(decodeAddressResult(tokenResults[i * 2] ?? null));
|
|
4114
|
+
tokensY.push(decodeAddressResult(tokenResults[i * 2 + 1] ?? null));
|
|
4115
|
+
}
|
|
4116
|
+
const uniqueTokens = Array.from(
|
|
4117
|
+
new Set([...tokensX, ...tokensY].filter((a) => a !== null))
|
|
4118
|
+
);
|
|
4119
|
+
const symbolCalls = uniqueTokens.map((t) => [
|
|
4120
|
+
t,
|
|
4121
|
+
encodeFunctionData12({ abi: erc20Abi2, functionName: "symbol" })
|
|
4122
|
+
]);
|
|
4123
|
+
const symbolResults = await multicallRead(rpcUrl, symbolCalls);
|
|
4124
|
+
const symbolMap = /* @__PURE__ */ new Map();
|
|
4125
|
+
for (let i = 0; i < uniqueTokens.length; i++) {
|
|
4126
|
+
const raw = symbolResults[i];
|
|
4127
|
+
if (!raw) continue;
|
|
4128
|
+
try {
|
|
4129
|
+
const sym = decodeFunctionResult4({
|
|
4130
|
+
abi: parseAbi12(["function f() external view returns (string)"]),
|
|
4131
|
+
functionName: "f",
|
|
4132
|
+
data: raw
|
|
4133
|
+
});
|
|
4134
|
+
symbolMap.set(uniqueTokens[i].toLowerCase(), sym);
|
|
4135
|
+
} catch {
|
|
4136
|
+
}
|
|
4137
|
+
}
|
|
4138
|
+
const out = [];
|
|
4139
|
+
for (let i = 0; i < pairs.length; i++) {
|
|
4140
|
+
const tx = tokensX[i];
|
|
4141
|
+
const ty = tokensY[i];
|
|
4142
|
+
if (!tx || !ty) continue;
|
|
4143
|
+
out.push({
|
|
4144
|
+
pool: pairs[i],
|
|
4145
|
+
tokenX: tx,
|
|
4146
|
+
tokenY: ty,
|
|
4147
|
+
symbolX: symbolMap.get(tx.toLowerCase()) ?? "?",
|
|
4148
|
+
symbolY: symbolMap.get(ty.toLowerCase()) ?? "?"
|
|
4149
|
+
});
|
|
4150
|
+
}
|
|
4151
|
+
return out;
|
|
4152
|
+
}
|
|
4080
4153
|
/**
|
|
4081
4154
|
* Discover all active rewarded LB pools by iterating the factory.
|
|
4082
4155
|
* Uses 7 multicall batches to minimise RPC round-trips and avoid 429s.
|
|
@@ -5622,6 +5695,7 @@ var init_dist2 = __esm({
|
|
|
5622
5695
|
"function borrowBalanceStored(address account) external view returns (uint256)",
|
|
5623
5696
|
"function mint(uint256 mintAmount) external returns (uint256)",
|
|
5624
5697
|
"function redeem(uint256 redeemTokens) external returns (uint256)",
|
|
5698
|
+
"function redeemUnderlying(uint256 redeemAmount) external returns (uint256)",
|
|
5625
5699
|
"function borrow(uint256 borrowAmount) external returns (uint256)",
|
|
5626
5700
|
"function repayBorrow(uint256 repayAmount) external returns (uint256)"
|
|
5627
5701
|
]);
|
|
@@ -5664,57 +5738,55 @@ var init_dist2 = __esm({
|
|
|
5664
5738
|
name() {
|
|
5665
5739
|
return this.protocolName;
|
|
5666
5740
|
}
|
|
5741
|
+
// Resolve the vToken whose underlying() matches params.asset. Compound V2 has
|
|
5742
|
+
// a separate vToken per asset, so all builders must dispatch on the request
|
|
5743
|
+
// asset. Returns the resolved vToken or throws if no candidate matches.
|
|
5744
|
+
async vtokenFor(asset) {
|
|
5745
|
+
const v = await this.resolveVtoken(asset);
|
|
5746
|
+
if (!v) throw DefiError.contractError(`[${this.protocolName}] no vToken for asset ${asset}`);
|
|
5747
|
+
return v;
|
|
5748
|
+
}
|
|
5667
5749
|
async buildSupply(params) {
|
|
5668
|
-
const
|
|
5669
|
-
|
|
5670
|
-
functionName: "mint",
|
|
5671
|
-
args: [params.amount]
|
|
5672
|
-
});
|
|
5750
|
+
const vtoken = await this.vtokenFor(params.asset);
|
|
5751
|
+
const data = encodeFunctionData16({ abi: CTOKEN_ABI, functionName: "mint", args: [params.amount] });
|
|
5673
5752
|
return {
|
|
5674
|
-
description: `[${this.protocolName}] Supply ${params.amount} to Venus`,
|
|
5675
|
-
to:
|
|
5753
|
+
description: `[${this.protocolName}] Supply ${params.amount} of ${params.asset} to Venus`,
|
|
5754
|
+
to: vtoken,
|
|
5676
5755
|
data,
|
|
5677
5756
|
value: 0n,
|
|
5678
|
-
gas_estimate: 3e5
|
|
5757
|
+
gas_estimate: 3e5,
|
|
5758
|
+
approvals: [{ token: params.asset, spender: vtoken, amount: params.amount }]
|
|
5679
5759
|
};
|
|
5680
5760
|
}
|
|
5681
5761
|
async buildBorrow(params) {
|
|
5682
|
-
const
|
|
5683
|
-
|
|
5684
|
-
functionName: "borrow",
|
|
5685
|
-
args: [params.amount]
|
|
5686
|
-
});
|
|
5762
|
+
const vtoken = await this.vtokenFor(params.asset);
|
|
5763
|
+
const data = encodeFunctionData16({ abi: CTOKEN_ABI, functionName: "borrow", args: [params.amount] });
|
|
5687
5764
|
return {
|
|
5688
|
-
description: `[${this.protocolName}] Borrow ${params.amount} from Venus`,
|
|
5689
|
-
to:
|
|
5765
|
+
description: `[${this.protocolName}] Borrow ${params.amount} of ${params.asset} from Venus`,
|
|
5766
|
+
to: vtoken,
|
|
5690
5767
|
data,
|
|
5691
5768
|
value: 0n,
|
|
5692
5769
|
gas_estimate: 35e4
|
|
5693
5770
|
};
|
|
5694
5771
|
}
|
|
5695
5772
|
async buildRepay(params) {
|
|
5696
|
-
const
|
|
5697
|
-
|
|
5698
|
-
functionName: "repayBorrow",
|
|
5699
|
-
args: [params.amount]
|
|
5700
|
-
});
|
|
5773
|
+
const vtoken = await this.vtokenFor(params.asset);
|
|
5774
|
+
const data = encodeFunctionData16({ abi: CTOKEN_ABI, functionName: "repayBorrow", args: [params.amount] });
|
|
5701
5775
|
return {
|
|
5702
|
-
description: `[${this.protocolName}] Repay ${params.amount} to Venus`,
|
|
5703
|
-
to:
|
|
5776
|
+
description: `[${this.protocolName}] Repay ${params.amount} of ${params.asset} to Venus`,
|
|
5777
|
+
to: vtoken,
|
|
5704
5778
|
data,
|
|
5705
5779
|
value: 0n,
|
|
5706
|
-
gas_estimate: 3e5
|
|
5780
|
+
gas_estimate: 3e5,
|
|
5781
|
+
approvals: [{ token: params.asset, spender: vtoken, amount: params.amount }]
|
|
5707
5782
|
};
|
|
5708
5783
|
}
|
|
5709
5784
|
async buildWithdraw(params) {
|
|
5710
|
-
const
|
|
5711
|
-
|
|
5712
|
-
functionName: "redeem",
|
|
5713
|
-
args: [params.amount]
|
|
5714
|
-
});
|
|
5785
|
+
const vtoken = await this.vtokenFor(params.asset);
|
|
5786
|
+
const data = encodeFunctionData16({ abi: CTOKEN_ABI, functionName: "redeemUnderlying", args: [params.amount] });
|
|
5715
5787
|
return {
|
|
5716
|
-
description: `[${this.protocolName}] Withdraw from Venus`,
|
|
5717
|
-
to:
|
|
5788
|
+
description: `[${this.protocolName}] Withdraw ${params.amount} of ${params.asset} from Venus`,
|
|
5789
|
+
to: vtoken,
|
|
5718
5790
|
data,
|
|
5719
5791
|
value: 0n,
|
|
5720
5792
|
gas_estimate: 25e4
|
|
@@ -8534,8 +8606,9 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
8534
8606
|
}
|
|
8535
8607
|
if (protocol.interface === "uniswap_v2" && protocol.contracts?.["lb_factory"]) {
|
|
8536
8608
|
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
8537
|
-
const
|
|
8538
|
-
|
|
8609
|
+
const rewardedPools = await adapter.discoverRewardedPools();
|
|
8610
|
+
const rewardedSet = new Set(rewardedPools.map((p) => p.pool.toLowerCase()));
|
|
8611
|
+
for (const p of rewardedPools) {
|
|
8539
8612
|
if (!opts.emissionOnly || !p.stopped) {
|
|
8540
8613
|
results.push({
|
|
8541
8614
|
protocol: protocol.slug,
|
|
@@ -8557,6 +8630,19 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
8557
8630
|
});
|
|
8558
8631
|
}
|
|
8559
8632
|
}
|
|
8633
|
+
if (!opts.emissionOnly) {
|
|
8634
|
+
const allPools = await adapter.discoverAllPools().catch(() => []);
|
|
8635
|
+
for (const p of allPools) {
|
|
8636
|
+
if (rewardedSet.has(p.pool.toLowerCase())) continue;
|
|
8637
|
+
results.push({
|
|
8638
|
+
protocol: protocol.slug,
|
|
8639
|
+
pool: p.pool,
|
|
8640
|
+
pair: `${p.symbolX}/${p.symbolY}`,
|
|
8641
|
+
type: "FEE",
|
|
8642
|
+
source: "lb_hooks"
|
|
8643
|
+
});
|
|
8644
|
+
}
|
|
8645
|
+
}
|
|
8560
8646
|
}
|
|
8561
8647
|
if (protocol.interface === "uniswap_v3" && protocol.contracts?.["masterchef"]) {
|
|
8562
8648
|
const mcAddr = protocol.contracts["masterchef"];
|
|
@@ -8688,7 +8774,7 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
8688
8774
|
const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
|
|
8689
8775
|
const poolAddr = opts.pool ? resolvePoolAddress(registry, opts.protocol, opts.pool) : void 0;
|
|
8690
8776
|
if (protocol.interface === "uniswap_v2" && protocol.contracts?.["lb_factory"]) {
|
|
8691
|
-
if (!poolAddr) throw new Error(
|
|
8777
|
+
if (!poolAddr) throw new Error(`--pool is required for ${protocol.name} (Liquidity Book \u2014 pass --pool <addr>; use \`lp discover --protocol ${protocol.slug}\` to list active pools)`);
|
|
8692
8778
|
const lbAdapter = createMerchantMoeLB(protocol, chain.effectiveRpcUrl());
|
|
8693
8779
|
const [tokenX, tokenY, amountX, amountY] = tokenA.toLowerCase() < tokenB.toLowerCase() ? [tokenA, tokenB, BigInt(opts.amountA), BigInt(opts.amountB)] : [tokenB, tokenA, BigInt(opts.amountB), BigInt(opts.amountA)];
|
|
8694
8780
|
const client = createPublicClient23({ transport: http23(chain.effectiveRpcUrl()) });
|
|
@@ -8931,7 +9017,7 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
8931
9017
|
return;
|
|
8932
9018
|
}
|
|
8933
9019
|
if (iface === "uniswap_v2" && protocol.contracts?.["lb_factory"]) {
|
|
8934
|
-
if (!opts.pool) throw new Error(
|
|
9020
|
+
if (!opts.pool) throw new Error(`--pool is required for ${protocol.name} (Liquidity Book \u2014 pass --pool <addr>)`);
|
|
8935
9021
|
const adapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
8936
9022
|
const binIds = opts.bins ? opts.bins.split(",").map((s) => parseInt(s.trim())) : void 0;
|
|
8937
9023
|
const tx = await adapter.buildClaimRewards(account, opts.pool, binIds);
|
|
@@ -9007,7 +9093,7 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
9007
9093
|
const iface = protocol.interface;
|
|
9008
9094
|
const recipient = opts.recipient ?? process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
|
|
9009
9095
|
if (iface === "uniswap_v2" && protocol.contracts?.["lb_factory"]) {
|
|
9010
|
-
if (!opts.pool) throw new Error(
|
|
9096
|
+
if (!opts.pool) throw new Error(`--pool is required for ${protocol.name} (Liquidity Book \u2014 pass --pool <addr>)`);
|
|
9011
9097
|
if (!opts.bins) throw new Error("--bins <id1,id2,...> is required for Merchant Moe LB remove");
|
|
9012
9098
|
const lbAdapter = createMerchantMoeLB(protocol, rpcUrl);
|
|
9013
9099
|
const tokenA2 = opts.tokenA.startsWith("0x") ? opts.tokenA : registry.resolveToken(chainName, opts.tokenA).address;
|