@moly-mcp/lido 1.0.7 → 1.0.9

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/bin.js CHANGED
@@ -18,8 +18,10 @@ import {
18
18
  password,
19
19
  note,
20
20
  cancel,
21
- isCancel
21
+ isCancel,
22
+ spinner
22
23
  } from "@clack/prompts";
24
+ import { generatePrivateKey } from "viem/accounts";
23
25
  function bail(value) {
24
26
  cancel("Setup cancelled.");
25
27
  process.exit(0);
@@ -147,14 +149,17 @@ async function runWizard() {
147
149
  })
148
150
  );
149
151
  if (keySource === "ows") {
152
+ let owsSdk = null;
150
153
  let wallets = [];
151
154
  try {
152
- const owsSdk = await import("@open-wallet-standard/core");
155
+ const { createRequire } = await import("module");
156
+ const _req = createRequire(import.meta.url);
157
+ owsSdk = _req("@open-wallet-standard/core");
153
158
  wallets = owsSdk.listWallets();
154
159
  } catch {
155
- note("Could not load OWS. Install it first:\ncurl -fsSL https://openwallet.sh/install.sh | bash\nnpm install @open-wallet-standard/core", "OWS not found");
160
+ note("OWS SDK not found. Install it first:\ncurl -fsSL https://openwallet.sh/install.sh | bash\nnpm install @open-wallet-standard/core\nFalling back to raw key storage.", "OWS not available");
156
161
  }
157
- if (wallets.length > 0) {
162
+ if (owsSdk && wallets.length > 0) {
158
163
  const walletName = check(
159
164
  await select({
160
165
  message: "Which OWS wallet?",
@@ -171,8 +176,29 @@ async function runWizard() {
171
176
  })
172
177
  );
173
178
  ows = { walletName, passphrase: passphrase.trim() };
174
- } else if (wallets.length === 0) {
175
- note('No OWS wallets found. Create one first:\nows wallet create --name "moly"', "Empty vault");
179
+ } else if (owsSdk && wallets.length === 0) {
180
+ note("No OWS wallets found. Creating one for you...", "New OWS wallet");
181
+ const walletName = check(
182
+ await text({ message: "Wallet name:", placeholder: "moly", initialValue: "moly" })
183
+ );
184
+ const passphrase = check(
185
+ await password({ message: "Set a passphrase (used to encrypt the key):", mask: "*" })
186
+ );
187
+ const s = spinner();
188
+ s.start("Generating wallet...");
189
+ try {
190
+ const privateKey2 = generatePrivateKey();
191
+ owsSdk.createWallet(walletName.trim() || "moly", passphrase.trim(), privateKey2);
192
+ s.stop("Wallet created.");
193
+ ows = { walletName: walletName.trim() || "moly", passphrase: passphrase.trim() };
194
+ } catch (err) {
195
+ s.stop("Auto-create failed: " + err.message);
196
+ note("Falling back to raw private key storage.", "Fallback");
197
+ const pk = check(
198
+ await password({ message: "Enter or paste a private key (0x...) \u2014 or generate one:", mask: "*" })
199
+ );
200
+ privateKey = pk.trim() || null;
201
+ }
176
202
  }
177
203
  } else if (keySource === "raw") {
178
204
  const pk = check(
@@ -254,7 +280,7 @@ async function main() {
254
280
  case "setup": {
255
281
  const { cfg, terminalMode } = await runWizard();
256
282
  if (terminalMode) {
257
- const { startChatSession } = await import("./session-2BM4AYLG.js");
283
+ const { startChatSession } = await import("./session-ZIAXZNTD.js");
258
284
  await startChatSession(cfg);
259
285
  } else {
260
286
  await startServer();
@@ -334,7 +360,7 @@ async function main() {
334
360
  console.log("No config. Run: moly setup");
335
361
  process.exit(1);
336
362
  }
337
- const { runDaemon } = await import("./daemon-GU45VVNU.js");
363
+ const { runDaemon } = await import("./daemon-RZA4HEUI.js");
338
364
  await runDaemon();
339
365
  break;
340
366
  }
@@ -492,7 +518,7 @@ async function main() {
492
518
  console.log("No config. Run: moly setup");
493
519
  process.exit(1);
494
520
  }
495
- const { getTotalPosition } = await import("./position-LKVHTEKX.js");
521
+ const { getTotalPosition } = await import("./position-ANCFIWD6.js");
496
522
  const address = args[1];
497
523
  const pos = await getTotalPosition(address);
498
524
  console.log(JSON.stringify(pos, null, 2));
@@ -514,7 +540,7 @@ async function main() {
514
540
  if (!configExists()) {
515
541
  const { cfg, terminalMode } = await runWizard();
516
542
  if (terminalMode) {
517
- const { startChatSession } = await import("./session-2BM4AYLG.js");
543
+ const { startChatSession } = await import("./session-ZIAXZNTD.js");
518
544
  await startChatSession(cfg);
519
545
  } else {
520
546
  await startServer();
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  getRuntime
4
- } from "./chunk-EKZFGIVK.js";
4
+ } from "./chunk-WMGNTYBF.js";
5
5
 
6
6
  // src/tools/unstake.ts
7
7
  import { parseEther, formatEther } from "viem";
@@ -4,7 +4,7 @@ import {
4
4
  getBalance,
5
5
  getConversionRate,
6
6
  getRuntime
7
- } from "./chunk-EKZFGIVK.js";
7
+ } from "./chunk-WMGNTYBF.js";
8
8
 
9
9
  // src/tools/bridge.ts
10
10
  import { formatEther, parseEther, parseAbi } from "viem";
@@ -3,15 +3,13 @@ import {
3
3
  loadConfig,
4
4
  saveConfig
5
5
  } from "./chunk-P6VFMSPM.js";
6
- import {
7
- __require
8
- } from "./chunk-PDX44BCA.js";
9
6
 
10
7
  // src/server/runtime.ts
11
8
  import { createPublicClient, createWalletClient, http, defineChain } from "viem";
12
9
  import { mainnet, base, arbitrum } from "viem/chains";
13
10
  import { privateKeyToAccount } from "viem/accounts";
14
11
  import { LidoSDK } from "@lidofinance/lido-ethereum-sdk";
12
+ import { createRequire } from "module";
15
13
 
16
14
  // src/config/types.ts
17
15
  var L2_CHAINS = {
@@ -48,6 +46,7 @@ var CHAIN_CONFIG = {
48
46
  };
49
47
 
50
48
  // src/server/runtime.ts
49
+ var _require = createRequire(import.meta.url);
51
50
  var hoodi = defineChain({
52
51
  id: 560048,
53
52
  name: "Hoodi Testnet",
@@ -74,13 +73,13 @@ function buildRuntime() {
74
73
  function resolveAccount() {
75
74
  if (_resolvedAccount) return _resolvedAccount;
76
75
  if (config.ows) {
77
- let exportWallet;
76
+ let owsSdk;
78
77
  try {
79
- exportWallet = __require("@open-wallet-standard/core").exportWallet;
78
+ owsSdk = _require("@open-wallet-standard/core");
80
79
  } catch {
81
80
  throw new Error("OWS SDK not installed. Run: npm install @open-wallet-standard/core");
82
81
  }
83
- const exported = exportWallet(config.ows.walletName, config.ows.passphrase);
82
+ const exported = owsSdk.exportWallet(config.ows.walletName, config.ows.passphrase);
84
83
  const keyHex = exported.secp256k1 ?? exported;
85
84
  const pk2 = keyHex.startsWith("0x") ? keyHex : "0x" + keyHex;
86
85
  _resolvedAccount = privateKeyToAccount(pk2);
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  applySettingsUpdate,
4
4
  getRuntime
5
- } from "./chunk-EKZFGIVK.js";
5
+ } from "./chunk-WMGNTYBF.js";
6
6
  import {
7
7
  loadConfig,
8
8
  redactedConfig
@@ -23,7 +23,6 @@ var REFERRAL = "0x0000000000000000000000000000000000000000";
23
23
  async function stakeEth(amountEth, dryRun) {
24
24
  const rt = getRuntime();
25
25
  const value = parseEther(amountEth);
26
- const account = rt.getAddress();
27
26
  const lidoAddress = rt.chainAddresses.stETH;
28
27
  const shouldDryRun = rt.config.mode === "simulation" ? dryRun !== false : !!dryRun;
29
28
  if (shouldDryRun) {
@@ -51,6 +50,7 @@ async function stakeEth(amountEth, dryRun) {
51
50
  note: "stETH rebases daily \u2014 your balance grows automatically after staking."
52
51
  };
53
52
  }
53
+ const account = rt.getAddress();
54
54
  const tx = await rt.sdk.stake.stakeEth({
55
55
  value,
56
56
  account: { address: account },
@@ -3,7 +3,7 @@ import {
3
3
  getProposals,
4
4
  getWithdrawalRequests,
5
5
  getWithdrawalStatus
6
- } from "./chunk-EQYEWCQO.js";
6
+ } from "./chunk-C7R33HEF.js";
7
7
  import {
8
8
  loadAlerts,
9
9
  loadChannelConfig,
@@ -14,7 +14,7 @@ import {
14
14
  getConversionRate,
15
15
  getRewards,
16
16
  getRuntime
17
- } from "./chunk-EKZFGIVK.js";
17
+ } from "./chunk-WMGNTYBF.js";
18
18
  import "./chunk-P6VFMSPM.js";
19
19
  import "./chunk-PDX44BCA.js";
20
20
 
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  getTotalPosition
4
- } from "./chunk-GL6TLHSF.js";
5
- import "./chunk-EKZFGIVK.js";
4
+ } from "./chunk-LRR663PB.js";
5
+ import "./chunk-WMGNTYBF.js";
6
6
  import "./chunk-P6VFMSPM.js";
7
7
  import "./chunk-PDX44BCA.js";
8
8
  export {
@@ -3,7 +3,7 @@ import {
3
3
  getSettings,
4
4
  stakeEth,
5
5
  updateSettings
6
- } from "../chunk-CQ6ZSCMZ.js";
6
+ } from "../chunk-ZX6OYPKV.js";
7
7
  import {
8
8
  castVote,
9
9
  claimWithdrawals,
@@ -12,7 +12,7 @@ import {
12
12
  getWithdrawalRequests,
13
13
  getWithdrawalStatus,
14
14
  requestWithdrawal
15
- } from "../chunk-EQYEWCQO.js";
15
+ } from "../chunk-C7R33HEF.js";
16
16
  import {
17
17
  configureAlertChannels,
18
18
  listAlerts,
@@ -26,14 +26,14 @@ import {
26
26
  getBridgeStatus,
27
27
  getL2Balance,
28
28
  getTotalPosition
29
- } from "../chunk-GL6TLHSF.js";
29
+ } from "../chunk-LRR663PB.js";
30
30
  import {
31
31
  getBalance,
32
32
  getConversionRate,
33
33
  getRewards,
34
34
  unwrapWsteth,
35
35
  wrapSteth
36
- } from "../chunk-EKZFGIVK.js";
36
+ } from "../chunk-WMGNTYBF.js";
37
37
  import {
38
38
  loadConfig
39
39
  } from "../chunk-P6VFMSPM.js";
@@ -3,7 +3,7 @@ import {
3
3
  getSettings,
4
4
  stakeEth,
5
5
  updateSettings
6
- } from "./chunk-CQ6ZSCMZ.js";
6
+ } from "./chunk-ZX6OYPKV.js";
7
7
  import {
8
8
  castVote,
9
9
  claimWithdrawals,
@@ -12,7 +12,7 @@ import {
12
12
  getWithdrawalRequests,
13
13
  getWithdrawalStatus,
14
14
  requestWithdrawal
15
- } from "./chunk-EQYEWCQO.js";
15
+ } from "./chunk-C7R33HEF.js";
16
16
  import {
17
17
  configureAlertChannels,
18
18
  listAlerts,
@@ -26,14 +26,14 @@ import {
26
26
  getBridgeStatus,
27
27
  getL2Balance,
28
28
  getTotalPosition
29
- } from "./chunk-GL6TLHSF.js";
29
+ } from "./chunk-LRR663PB.js";
30
30
  import {
31
31
  getBalance,
32
32
  getConversionRate,
33
33
  getRewards,
34
34
  unwrapWsteth,
35
35
  wrapSteth
36
- } from "./chunk-EKZFGIVK.js";
36
+ } from "./chunk-WMGNTYBF.js";
37
37
  import "./chunk-P6VFMSPM.js";
38
38
  import {
39
39
  loadBounds,
@@ -683,6 +683,16 @@ ${D} powered by Lido${R}
683
683
  function ln(text = "") {
684
684
  process.stdout.write(text + "\n");
685
685
  }
686
+ function printResponse(text) {
687
+ const lines = text.split("\n");
688
+ const prefix = `${B}${GR}moly${R} \u203A `;
689
+ const indent = " ";
690
+ ln();
691
+ lines.forEach((line, i) => {
692
+ process.stdout.write((i === 0 ? prefix : indent) + line + "\n");
693
+ });
694
+ ln();
695
+ }
686
696
  function saveTrade(toolName, args, result) {
687
697
  try {
688
698
  let txHash;
@@ -742,7 +752,20 @@ async function startChatSession(cfg) {
742
752
  const messages = [
743
753
  {
744
754
  role: "user",
745
- content: skillContext + `You are Moly, a terminal assistant for Lido Finance on ${cfg.network}. Mode: ${cfg.mode} (${cfg.mode === "simulation" ? "dry-run, nothing broadcast" : "LIVE - real on-chain transactions"}). Chain scope: ${cfg.chainScope ?? "ethereum"}. You can only do what your tools support: staking ETH, withdrawals, wrap/unwrap stETH/wstETH, balances, rewards, Lido DAO governance${cfg.chainScope === "all" ? ", and L2 bridging from Base/Arbitrum to Ethereum via LI.FI" : ""}. ${cfg.chainScope === "all" ? "If the user wants to stake ETH from Base or Arbitrum, first check their L2 balance with get_l2_balance, then bridge to Ethereum with bridge_to_ethereum, then after bridging completes use stake_eth. Bridge takes 1-20 min, tell user to check with get_bridge_status. " : ""}If asked about anything outside those tools (e.g. Lido Vaults, validators, node operators, DeFi integrations), say clearly and briefly that it is not supported. IMPORTANT: This is a terminal. Never use markdown. No **bold**, no bullet points, no headers, no backticks. Plain text only. Be concise. For live transactions always confirm first.`
755
+ content: skillContext + `You are Moly, a terminal assistant for Lido Finance on ${cfg.network}.
756
+ Mode: ${cfg.mode} (${cfg.mode === "simulation" ? "dry-run, nothing broadcast" : "LIVE - real on-chain transactions"}).
757
+ Chain scope: ${cfg.chainScope ?? "ethereum"}.
758
+
759
+ You can only do what your tools support: staking ETH, withdrawals, wrap/unwrap stETH/wstETH, balances, rewards, Lido DAO governance${cfg.chainScope === "all" ? ", and L2 bridging from Base/Arbitrum to Ethereum via LI.FI" : ""}.
760
+ ${cfg.chainScope === "all" ? "If the user wants to stake ETH from Base or Arbitrum, first check their L2 balance with get_l2_balance, then bridge to Ethereum with bridge_to_ethereum, then after bridging completes use stake_eth. Bridge takes 1-20 min, tell user to check with get_bridge_status.\n" : ""}If asked about anything outside those tools (e.g. Lido Vaults, validators, node operators, DeFi integrations), say clearly and briefly that it is not supported.
761
+
762
+ OUTPUT FORMAT RULES (terminal, no markdown):
763
+ - Never use **bold**, _italic_, # headers, or backtick code blocks.
764
+ - Use plain dashes (-) for lists, one item per line.
765
+ - Use blank lines to separate sections or groups of information.
766
+ - For key/value data (balances, settings, etc.) use " key: value" format, one per line.
767
+ - Keep prose concise. Lead with the answer, then details.
768
+ - For live transactions always confirm with the user first.`
746
769
  },
747
770
  {
748
771
  role: "assistant",
@@ -804,16 +827,12 @@ async function startChatSession(cfg) {
804
827
  }
805
828
  messages.push(...toolResults);
806
829
  if (response.text) {
807
- ln();
808
- ln(`${B}${GR}moly${R} \u203A ${response.text}`);
809
- ln();
830
+ printResponse(response.text);
810
831
  }
811
832
  continue;
812
833
  }
813
834
  if (response.text) {
814
- ln();
815
- ln(`${B}${GR}moly${R} \u203A ${response.text}`);
816
- ln();
835
+ printResponse(response.text);
817
836
  }
818
837
  break;
819
838
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moly-mcp/lido",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Lido MCP Server — stake, unstake, wrap, govern. Works with Claude Desktop, Cursor, Windsurf, and any MCP client.",
5
5
  "license": "MIT",
6
6
  "type": "module",