@hypurrquant/defi-cli 0.3.4 → 0.3.5
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 +209 -1
- package/dist/index.js.map +1 -1
- package/dist/main.js +211 -2
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -6966,7 +6966,11 @@ function registerLP(parent, getOpts, makeExecutor2) {
|
|
|
6966
6966
|
pair: `${p.symbolX}/${p.symbolY}`,
|
|
6967
6967
|
type: "EMISSION",
|
|
6968
6968
|
source: "lb_hooks",
|
|
6969
|
-
stopped: p.stopped
|
|
6969
|
+
stopped: p.stopped,
|
|
6970
|
+
moePerDay: p.moePerDay,
|
|
6971
|
+
aprPercent: p.aprPercent,
|
|
6972
|
+
rangeTvlUsd: p.rangeTvlUsd,
|
|
6973
|
+
isTopPool: p.isTopPool
|
|
6970
6974
|
});
|
|
6971
6975
|
}
|
|
6972
6976
|
}
|
|
@@ -9968,6 +9972,209 @@ function registerBridge(parent, getOpts) {
|
|
|
9968
9972
|
});
|
|
9969
9973
|
}
|
|
9970
9974
|
|
|
9975
|
+
// src/commands/swap.ts
|
|
9976
|
+
var CHAIN_NAMES = {
|
|
9977
|
+
hyperevm: { kyber: "hyperevm", openocean: "hyperevm" },
|
|
9978
|
+
mantle: { openocean: "mantle" }
|
|
9979
|
+
};
|
|
9980
|
+
var KYBER_API = "https://aggregator-api.kyberswap.com";
|
|
9981
|
+
async function kyberGetQuote(chain, tokenIn, tokenOut, amountIn) {
|
|
9982
|
+
const params = new URLSearchParams({ tokenIn, tokenOut, amountIn });
|
|
9983
|
+
const url = `${KYBER_API}/${chain}/api/v1/routes?${params}`;
|
|
9984
|
+
const res = await fetch(url, { headers: { "x-client-id": "defi-cli" } });
|
|
9985
|
+
if (!res.ok) throw new Error(`KyberSwap quote failed: ${res.status} ${await res.text()}`);
|
|
9986
|
+
const json = await res.json();
|
|
9987
|
+
const data = json.data;
|
|
9988
|
+
if (!data?.routeSummary) throw new Error(`KyberSwap: no route found`);
|
|
9989
|
+
return data;
|
|
9990
|
+
}
|
|
9991
|
+
async function kyberBuildTx(chain, routeSummary, sender, recipient, slippageTolerance) {
|
|
9992
|
+
const url = `${KYBER_API}/${chain}/api/v1/route/build`;
|
|
9993
|
+
const res = await fetch(url, {
|
|
9994
|
+
method: "POST",
|
|
9995
|
+
headers: { "Content-Type": "application/json", "x-client-id": "defi-cli" },
|
|
9996
|
+
body: JSON.stringify({ routeSummary, sender, recipient, slippageTolerance })
|
|
9997
|
+
});
|
|
9998
|
+
if (!res.ok) throw new Error(`KyberSwap build failed: ${res.status} ${await res.text()}`);
|
|
9999
|
+
const json = await res.json();
|
|
10000
|
+
const data = json.data;
|
|
10001
|
+
if (!data) throw new Error("KyberSwap: no build data");
|
|
10002
|
+
return {
|
|
10003
|
+
to: String(data.routerAddress),
|
|
10004
|
+
data: String(data.data),
|
|
10005
|
+
value: String(data.value ?? "0x0")
|
|
10006
|
+
};
|
|
10007
|
+
}
|
|
10008
|
+
var OPENOCEAN_API = "https://open-api.openocean.finance/v4";
|
|
10009
|
+
async function openoceanSwap(chain, inTokenAddress, outTokenAddress, amountIn, slippagePct, account) {
|
|
10010
|
+
const params = new URLSearchParams({
|
|
10011
|
+
inTokenAddress,
|
|
10012
|
+
outTokenAddress,
|
|
10013
|
+
amount: amountIn,
|
|
10014
|
+
gasPrice: "0.1",
|
|
10015
|
+
slippage: slippagePct,
|
|
10016
|
+
account
|
|
10017
|
+
});
|
|
10018
|
+
const url = `${OPENOCEAN_API}/${chain}/swap?${params}`;
|
|
10019
|
+
const res = await fetch(url);
|
|
10020
|
+
if (!res.ok) throw new Error(`OpenOcean swap failed: ${res.status} ${await res.text()}`);
|
|
10021
|
+
const json = await res.json();
|
|
10022
|
+
const data = json.data;
|
|
10023
|
+
if (!data) throw new Error("OpenOcean: no swap data");
|
|
10024
|
+
return {
|
|
10025
|
+
to: String(data.to),
|
|
10026
|
+
data: String(data.data),
|
|
10027
|
+
value: String(data.value ?? "0x0"),
|
|
10028
|
+
outAmount: String(data.outAmount ?? "0")
|
|
10029
|
+
};
|
|
10030
|
+
}
|
|
10031
|
+
var LIQD_API = "https://api.liqd.ag/v2";
|
|
10032
|
+
var LIQD_ROUTER = "0x744489ee3d540777a66f2cf297479745e0852f7a";
|
|
10033
|
+
async function liquidSwapRoute(tokenIn, tokenOut, amountIn, slippagePct) {
|
|
10034
|
+
const params = new URLSearchParams({ tokenIn, tokenOut, amountIn, slippage: slippagePct });
|
|
10035
|
+
const url = `${LIQD_API}/route?${params}`;
|
|
10036
|
+
const res = await fetch(url);
|
|
10037
|
+
if (!res.ok) throw new Error(`LiquidSwap route failed: ${res.status} ${await res.text()}`);
|
|
10038
|
+
const json = await res.json();
|
|
10039
|
+
const execution = json.execution;
|
|
10040
|
+
if (!execution) throw new Error("LiquidSwap: no execution data in response");
|
|
10041
|
+
const details = json.details;
|
|
10042
|
+
return {
|
|
10043
|
+
to: String(execution.to ?? LIQD_ROUTER),
|
|
10044
|
+
data: String(execution.calldata),
|
|
10045
|
+
value: String(execution.value ?? "0x0"),
|
|
10046
|
+
outAmount: String(details?.amountOut ?? json.amountOut ?? "0")
|
|
10047
|
+
};
|
|
10048
|
+
}
|
|
10049
|
+
function registerSwap(parent, getOpts, makeExecutor2) {
|
|
10050
|
+
parent.command("swap").description("Swap tokens via DEX aggregator (KyberSwap, OpenOcean, LiquidSwap)").requiredOption("--from <token>", "Input token symbol or address").requiredOption("--to <token>", "Output token symbol or address").requiredOption("--amount <amount>", "Amount of input token in wei").option("--provider <name>", "Aggregator: kyber, openocean, liquid", "kyber").option("--slippage <bps>", "Slippage tolerance in bps", "50").action(async (opts) => {
|
|
10051
|
+
const executor = makeExecutor2();
|
|
10052
|
+
const chainName = parent.opts().chain ?? "hyperevm";
|
|
10053
|
+
const registry = Registry.loadEmbedded();
|
|
10054
|
+
const provider = opts.provider.toLowerCase();
|
|
10055
|
+
const slippageBps = parseInt(opts.slippage, 10);
|
|
10056
|
+
const fromAddr = opts.from.startsWith("0x") ? opts.from : registry.resolveToken(chainName, opts.from).address;
|
|
10057
|
+
const toAddr = opts.to.startsWith("0x") ? opts.to : registry.resolveToken(chainName, opts.to).address;
|
|
10058
|
+
const wallet = process.env["DEFI_WALLET_ADDRESS"] ?? "0x0000000000000000000000000000000000000001";
|
|
10059
|
+
if (provider === "kyber") {
|
|
10060
|
+
const chainNames = CHAIN_NAMES[chainName];
|
|
10061
|
+
if (!chainNames?.kyber) {
|
|
10062
|
+
printOutput({ error: `KyberSwap: unsupported chain '${chainName}'. Supported: hyperevm` }, getOpts());
|
|
10063
|
+
return;
|
|
10064
|
+
}
|
|
10065
|
+
const kyberChain = chainNames.kyber;
|
|
10066
|
+
try {
|
|
10067
|
+
const quoteData = await kyberGetQuote(kyberChain, fromAddr, toAddr, opts.amount);
|
|
10068
|
+
const routeSummary = quoteData.routeSummary;
|
|
10069
|
+
const amountOut = String(routeSummary.amountOut ?? "0");
|
|
10070
|
+
const txData = await kyberBuildTx(
|
|
10071
|
+
kyberChain,
|
|
10072
|
+
routeSummary,
|
|
10073
|
+
wallet,
|
|
10074
|
+
wallet,
|
|
10075
|
+
slippageBps
|
|
10076
|
+
);
|
|
10077
|
+
const tx = {
|
|
10078
|
+
description: `KyberSwap: swap ${opts.amount} of ${fromAddr} -> ${toAddr}`,
|
|
10079
|
+
to: txData.to,
|
|
10080
|
+
data: txData.data,
|
|
10081
|
+
value: txData.value.startsWith("0x") ? BigInt(txData.value) : BigInt(txData.value || 0),
|
|
10082
|
+
approvals: [{ token: fromAddr, spender: txData.to, amount: BigInt(opts.amount) }]
|
|
10083
|
+
};
|
|
10084
|
+
const result = await executor.execute(tx);
|
|
10085
|
+
printOutput({
|
|
10086
|
+
provider: "kyber",
|
|
10087
|
+
chain: kyberChain,
|
|
10088
|
+
from_token: fromAddr,
|
|
10089
|
+
to_token: toAddr,
|
|
10090
|
+
amount_in: opts.amount,
|
|
10091
|
+
amount_out: amountOut,
|
|
10092
|
+
router: txData.to,
|
|
10093
|
+
...result
|
|
10094
|
+
}, getOpts());
|
|
10095
|
+
} catch (e) {
|
|
10096
|
+
printOutput({ error: `KyberSwap error: ${e instanceof Error ? e.message : String(e)}` }, getOpts());
|
|
10097
|
+
}
|
|
10098
|
+
return;
|
|
10099
|
+
}
|
|
10100
|
+
if (provider === "openocean") {
|
|
10101
|
+
const chainNames = CHAIN_NAMES[chainName];
|
|
10102
|
+
if (!chainNames) {
|
|
10103
|
+
printOutput({ error: `OpenOcean: unsupported chain '${chainName}'. Supported: ${Object.keys(CHAIN_NAMES).join(", ")}` }, getOpts());
|
|
10104
|
+
return;
|
|
10105
|
+
}
|
|
10106
|
+
const ooChain = chainNames.openocean;
|
|
10107
|
+
const fromToken = opts.from.startsWith("0x") ? registry.tokens.get(chainName)?.find((t) => t.address.toLowerCase() === opts.from.toLowerCase()) : registry.tokens.get(chainName)?.find((t) => t.symbol.toLowerCase() === opts.from.toLowerCase());
|
|
10108
|
+
const fromDecimals = fromToken?.decimals ?? 18;
|
|
10109
|
+
const humanAmount = (Number(opts.amount) / 10 ** fromDecimals).toString();
|
|
10110
|
+
const slippagePct = (slippageBps / 100).toFixed(2);
|
|
10111
|
+
try {
|
|
10112
|
+
const swap = await openoceanSwap(
|
|
10113
|
+
ooChain,
|
|
10114
|
+
fromAddr,
|
|
10115
|
+
toAddr,
|
|
10116
|
+
humanAmount,
|
|
10117
|
+
slippagePct,
|
|
10118
|
+
wallet
|
|
10119
|
+
);
|
|
10120
|
+
const tx = {
|
|
10121
|
+
description: `OpenOcean: swap ${opts.amount} of ${fromAddr} -> ${toAddr}`,
|
|
10122
|
+
to: swap.to,
|
|
10123
|
+
data: swap.data,
|
|
10124
|
+
value: swap.value.startsWith("0x") ? BigInt(swap.value) : BigInt(swap.value || 0),
|
|
10125
|
+
approvals: [{ token: fromAddr, spender: swap.to, amount: BigInt(opts.amount) }]
|
|
10126
|
+
};
|
|
10127
|
+
const result = await executor.execute(tx);
|
|
10128
|
+
printOutput({
|
|
10129
|
+
provider: "openocean",
|
|
10130
|
+
chain: ooChain,
|
|
10131
|
+
from_token: fromAddr,
|
|
10132
|
+
to_token: toAddr,
|
|
10133
|
+
amount_in: opts.amount,
|
|
10134
|
+
amount_out: swap.outAmount,
|
|
10135
|
+
router: swap.to,
|
|
10136
|
+
...result
|
|
10137
|
+
}, getOpts());
|
|
10138
|
+
} catch (e) {
|
|
10139
|
+
printOutput({ error: `OpenOcean error: ${e instanceof Error ? e.message : String(e)}` }, getOpts());
|
|
10140
|
+
}
|
|
10141
|
+
return;
|
|
10142
|
+
}
|
|
10143
|
+
if (provider === "liquid") {
|
|
10144
|
+
if (chainName !== "hyperevm") {
|
|
10145
|
+
printOutput({ error: `LiquidSwap only supports hyperevm, got '${chainName}'` }, getOpts());
|
|
10146
|
+
return;
|
|
10147
|
+
}
|
|
10148
|
+
const slippagePct = (slippageBps / 100).toFixed(2);
|
|
10149
|
+
try {
|
|
10150
|
+
const route = await liquidSwapRoute(fromAddr, toAddr, opts.amount, slippagePct);
|
|
10151
|
+
const tx = {
|
|
10152
|
+
description: `LiquidSwap: swap ${opts.amount} of ${fromAddr} -> ${toAddr}`,
|
|
10153
|
+
to: route.to,
|
|
10154
|
+
data: route.data,
|
|
10155
|
+
value: route.value.startsWith("0x") ? BigInt(route.value) : BigInt(route.value || 0),
|
|
10156
|
+
approvals: [{ token: fromAddr, spender: route.to, amount: BigInt(opts.amount) }]
|
|
10157
|
+
};
|
|
10158
|
+
const result = await executor.execute(tx);
|
|
10159
|
+
printOutput({
|
|
10160
|
+
provider: "liquid",
|
|
10161
|
+
chain: chainName,
|
|
10162
|
+
from_token: fromAddr,
|
|
10163
|
+
to_token: toAddr,
|
|
10164
|
+
amount_in: opts.amount,
|
|
10165
|
+
amount_out: route.outAmount,
|
|
10166
|
+
router: route.to,
|
|
10167
|
+
...result
|
|
10168
|
+
}, getOpts());
|
|
10169
|
+
} catch (e) {
|
|
10170
|
+
printOutput({ error: `LiquidSwap error: ${e instanceof Error ? e.message : String(e)}` }, getOpts());
|
|
10171
|
+
}
|
|
10172
|
+
return;
|
|
10173
|
+
}
|
|
10174
|
+
printOutput({ error: `Unknown provider '${opts.provider}'. Choose: kyber, openocean, liquid` }, getOpts());
|
|
10175
|
+
});
|
|
10176
|
+
}
|
|
10177
|
+
|
|
9971
10178
|
// src/commands/setup.ts
|
|
9972
10179
|
import pc2 from "picocolors";
|
|
9973
10180
|
import { createInterface } from "readline";
|
|
@@ -10156,6 +10363,7 @@ registerWallet(program, getOutputMode);
|
|
|
10156
10363
|
registerToken(program, getOutputMode, makeExecutor);
|
|
10157
10364
|
registerWhales(program, getOutputMode);
|
|
10158
10365
|
registerBridge(program, getOutputMode);
|
|
10366
|
+
registerSwap(program, getOutputMode, makeExecutor);
|
|
10159
10367
|
registerSetup(program);
|
|
10160
10368
|
|
|
10161
10369
|
// src/landing.ts
|
|
@@ -10263,7 +10471,7 @@ async function showLandingPage(isJson) {
|
|
|
10263
10471
|
console.log(" Commands:");
|
|
10264
10472
|
console.log(pc3.dim(" defi status Protocol overview"));
|
|
10265
10473
|
console.log(pc3.dim(" defi lending rates Compare lending APYs"));
|
|
10266
|
-
console.log(pc3.dim(" defi
|
|
10474
|
+
console.log(pc3.dim(" defi lp discover Find LP farming pools"));
|
|
10267
10475
|
console.log(pc3.dim(" defi portfolio View all positions"));
|
|
10268
10476
|
console.log(pc3.dim(" defi scan Exploit detection"));
|
|
10269
10477
|
console.log(pc3.dim(" defi --help Full command list"));
|
|
@@ -10351,6 +10559,7 @@ async function main() {
|
|
|
10351
10559
|
"token",
|
|
10352
10560
|
"whales",
|
|
10353
10561
|
"bridge",
|
|
10562
|
+
"swap",
|
|
10354
10563
|
"agent",
|
|
10355
10564
|
"setup",
|
|
10356
10565
|
"init"
|