@moly-mcp/lido 1.1.6 → 1.1.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/bin.js CHANGED
@@ -352,7 +352,7 @@ async function main() {
352
352
  case "setup": {
353
353
  const { cfg, terminalMode } = await runWizard();
354
354
  if (terminalMode) {
355
- const { startChatSession } = await import("./session-TQ2F7RWC.js");
355
+ const { startChatSession } = await import("./session-APNAIZ7W.js");
356
356
  await startChatSession(cfg);
357
357
  } else {
358
358
  await startServer();
@@ -432,7 +432,7 @@ async function main() {
432
432
  console.log("No config. Run: moly setup");
433
433
  process.exit(1);
434
434
  }
435
- const { runDaemon } = await import("./daemon-QQW5XDFW.js");
435
+ const { runDaemon } = await import("./daemon-FNV7KTYR.js");
436
436
  await runDaemon();
437
437
  break;
438
438
  }
@@ -590,7 +590,7 @@ async function main() {
590
590
  console.log("No config. Run: moly setup");
591
591
  process.exit(1);
592
592
  }
593
- const { getTotalPosition } = await import("./position-7UQ3RE3M.js");
593
+ const { getTotalPosition } = await import("./position-PZ363YFM.js");
594
594
  const address = args[1];
595
595
  const pos = await getTotalPosition(address);
596
596
  console.log(JSON.stringify(pos, null, 2));
@@ -601,14 +601,14 @@ async function main() {
601
601
  if (!configExists()) {
602
602
  const { cfg, terminalMode } = await runWizard();
603
603
  if (terminalMode) {
604
- const { startChatSession } = await import("./session-TQ2F7RWC.js");
604
+ const { startChatSession } = await import("./session-APNAIZ7W.js");
605
605
  await startChatSession(cfg);
606
606
  } else {
607
607
  await startServer();
608
608
  }
609
609
  } else {
610
610
  const cfg = loadConfig();
611
- const { startChatSession } = await import("./session-TQ2F7RWC.js");
611
+ const { startChatSession } = await import("./session-APNAIZ7W.js");
612
612
  await startChatSession(cfg);
613
613
  }
614
614
  break;
@@ -680,7 +680,7 @@ Commands:
680
680
  if (!configExists()) {
681
681
  const { cfg, terminalMode } = await runWizard();
682
682
  if (terminalMode) {
683
- const { startChatSession } = await import("./session-TQ2F7RWC.js");
683
+ const { startChatSession } = await import("./session-APNAIZ7W.js");
684
684
  await startChatSession(cfg);
685
685
  } else {
686
686
  await startServer();
@@ -66,10 +66,20 @@ function buildRuntime() {
66
66
  chain: viemChain,
67
67
  transport: http(rpcUrl)
68
68
  });
69
- const sdk = new LidoSDK({
70
- chainId: chainCfg.chainId,
71
- rpcProvider: publicClient
72
- });
69
+ let _sdk = null;
70
+ function getSdk() {
71
+ if (_sdk) return _sdk;
72
+ const sdkOpts = {
73
+ chainId: chainCfg.chainId,
74
+ rpcProvider: publicClient
75
+ };
76
+ try {
77
+ sdkOpts.web3Provider = getWallet();
78
+ } catch {
79
+ }
80
+ _sdk = new LidoSDK(sdkOpts);
81
+ return _sdk;
82
+ }
73
83
  let _wallet = null;
74
84
  let _resolvedAccount = null;
75
85
  function resolveAccount() {
@@ -89,7 +99,14 @@ function buildRuntime() {
89
99
  }
90
100
  }
91
101
  if (!owsSdk) throw new Error("OWS SDK not installed. Run: npm install -g @open-wallet-standard/core");
92
- const keyHex = owsSdk.exportWallet(config.ows.walletName, config.ows.passphrase ?? void 0);
102
+ const exported = owsSdk.exportWallet(config.ows.walletName, config.ows.passphrase ?? void 0);
103
+ let keyHex;
104
+ try {
105
+ const parsed = JSON.parse(exported);
106
+ keyHex = parsed.secp256k1 ?? parsed;
107
+ } catch {
108
+ keyHex = exported;
109
+ }
93
110
  const pk2 = keyHex.startsWith("0x") ? keyHex : "0x" + keyHex;
94
111
  _resolvedAccount = privateKeyToAccount(pk2);
95
112
  return _resolvedAccount;
@@ -134,7 +151,9 @@ function buildRuntime() {
134
151
  config,
135
152
  chainAddresses: chainCfg,
136
153
  publicClient,
137
- sdk,
154
+ get sdk() {
155
+ return getSdk();
156
+ },
138
157
  getWallet,
139
158
  getAddress,
140
159
  getL2PublicClient,
@@ -160,139 +179,8 @@ function applySettingsUpdate(patch) {
160
179
  return current;
161
180
  }
162
181
 
163
- // src/tools/balance.ts
164
- import { formatEther } from "viem";
165
- async function getBalance(address) {
166
- const rt = getRuntime();
167
- const addr = address ?? rt.getAddress();
168
- const [eth, steth, wsteth] = await Promise.all([
169
- rt.sdk.core.balanceETH(addr),
170
- rt.sdk.steth.balance(addr),
171
- rt.sdk.wsteth.balance(addr)
172
- ]);
173
- return {
174
- address: addr,
175
- mode: rt.config.mode,
176
- network: rt.chainAddresses.name,
177
- balances: {
178
- eth: formatEther(eth),
179
- stETH: formatEther(steth),
180
- wstETH: formatEther(wsteth)
181
- }
182
- };
183
- }
184
- async function getRewards(address, days = 7) {
185
- const rt = getRuntime();
186
- const addr = address ?? rt.getAddress();
187
- const rewards = await rt.sdk.rewards.getRewardsFromChain({
188
- address: addr,
189
- stepBlock: 1e3,
190
- back: { days: BigInt(days) }
191
- });
192
- return {
193
- address: addr,
194
- period: `${days} days`,
195
- totalRewards: formatEther(rewards.totalRewards),
196
- baseBalance: formatEther(rewards.baseBalance),
197
- rewards: rewards.rewards.slice(0, 10).map((e) => ({
198
- type: e.type,
199
- change: formatEther(e.change),
200
- balance: formatEther(e.balance)
201
- }))
202
- };
203
- }
204
-
205
- // src/tools/wrap.ts
206
- import { parseEther, formatEther as formatEther2 } from "viem";
207
- async function wrapSteth(amountSteth, dryRun) {
208
- const rt = getRuntime();
209
- const amount = parseEther(amountSteth);
210
- const shouldDryRun = rt.config.mode === "simulation" ? dryRun !== false : !!dryRun;
211
- const expectedWstETH = await rt.sdk.wrap.convertStethToWsteth(amount);
212
- if (shouldDryRun) {
213
- return {
214
- simulated: true,
215
- mode: rt.config.mode,
216
- network: rt.chainAddresses.name,
217
- action: "wrap_steth",
218
- amountSteth,
219
- expectedWstETH: formatEther2(expectedWstETH),
220
- note: "wstETH is non-rebasing \u2014 balance stays fixed while value grows. Better for DeFi."
221
- };
222
- }
223
- const account = rt.getAddress();
224
- const tx = await rt.sdk.wrap.wrapSteth({
225
- value: amount,
226
- account,
227
- callback: () => {
228
- }
229
- });
230
- return {
231
- simulated: false,
232
- mode: rt.config.mode,
233
- network: rt.chainAddresses.name,
234
- action: "wrap_steth",
235
- amountSteth,
236
- txHash: tx.hash,
237
- wstethReceived: formatEther2(tx.result?.wstethReceived ?? 0n)
238
- };
239
- }
240
- async function unwrapWsteth(amountWsteth, dryRun) {
241
- const rt = getRuntime();
242
- const amount = parseEther(amountWsteth);
243
- const shouldDryRun = rt.config.mode === "simulation" ? dryRun !== false : !!dryRun;
244
- const expectedStETH = await rt.sdk.wrap.convertWstethToSteth(amount);
245
- if (shouldDryRun) {
246
- return {
247
- simulated: true,
248
- mode: rt.config.mode,
249
- network: rt.chainAddresses.name,
250
- action: "unwrap_wsteth",
251
- amountWsteth,
252
- expectedStETH: formatEther2(expectedStETH),
253
- note: "Unwrapping gives rebasing stETH back. Balance updates daily with rewards."
254
- };
255
- }
256
- const account = rt.getAddress();
257
- const tx = await rt.sdk.wrap.unwrap({
258
- value: amount,
259
- account,
260
- callback: () => {
261
- }
262
- });
263
- return {
264
- simulated: false,
265
- mode: rt.config.mode,
266
- network: rt.chainAddresses.name,
267
- action: "unwrap_wsteth",
268
- amountWsteth,
269
- txHash: tx.hash,
270
- stethReceived: formatEther2(tx.result?.stethReceived ?? 0n)
271
- };
272
- }
273
- async function getConversionRate() {
274
- const rt = getRuntime();
275
- const oneEther = parseEther("1");
276
- const [wstethPerSteth, stethPerWsteth] = await Promise.all([
277
- rt.sdk.wrap.convertStethToWsteth(oneEther),
278
- rt.sdk.wrap.convertWstethToSteth(oneEther)
279
- ]);
280
- return {
281
- mode: rt.config.mode,
282
- network: rt.chainAddresses.name,
283
- "1_stETH_in_wstETH": formatEther2(wstethPerSteth),
284
- "1_wstETH_in_stETH": formatEther2(stethPerWsteth),
285
- note: "wstETH/stETH ratio increases over time as staking rewards accumulate."
286
- };
287
- }
288
-
289
182
  export {
290
183
  L2_CHAINS,
291
184
  getRuntime,
292
- applySettingsUpdate,
293
- getBalance,
294
- getRewards,
295
- wrapSteth,
296
- unwrapWsteth,
297
- getConversionRate
185
+ applySettingsUpdate
298
186
  };
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- L2_CHAINS,
4
3
  getBalance,
5
- getConversionRate,
4
+ getConversionRate
5
+ } from "./chunk-EG76IABG.js";
6
+ import {
7
+ L2_CHAINS,
6
8
  getRuntime
7
- } from "./chunk-TISPNEN6.js";
9
+ } from "./chunk-2MF5MDUT.js";
8
10
 
9
11
  // src/tools/bridge.ts
10
12
  import { formatEther, parseEther, parseAbi } from "viem";
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ getRuntime
4
+ } from "./chunk-2MF5MDUT.js";
5
+
6
+ // src/tools/balance.ts
7
+ import { formatEther } from "viem";
8
+ async function getBalance(address) {
9
+ const rt = getRuntime();
10
+ const addr = address ?? rt.getAddress();
11
+ const [eth, steth, wsteth] = await Promise.all([
12
+ rt.sdk.core.balanceETH(addr),
13
+ rt.sdk.steth.balance(addr),
14
+ rt.sdk.wsteth.balance(addr)
15
+ ]);
16
+ return {
17
+ address: addr,
18
+ mode: rt.config.mode,
19
+ network: rt.chainAddresses.name,
20
+ balances: {
21
+ eth: formatEther(eth),
22
+ stETH: formatEther(steth),
23
+ wstETH: formatEther(wsteth)
24
+ }
25
+ };
26
+ }
27
+ async function getRewards(address, days = 7) {
28
+ const rt = getRuntime();
29
+ const addr = address ?? rt.getAddress();
30
+ const rewards = await rt.sdk.rewards.getRewardsFromChain({
31
+ address: addr,
32
+ stepBlock: 1e3,
33
+ back: { days: BigInt(days) }
34
+ });
35
+ return {
36
+ address: addr,
37
+ period: `${days} days`,
38
+ totalRewards: formatEther(rewards.totalRewards),
39
+ baseBalance: formatEther(rewards.baseBalance),
40
+ rewards: rewards.rewards.slice(0, 10).map((e) => ({
41
+ type: e.type,
42
+ change: formatEther(e.change),
43
+ balance: formatEther(e.balance)
44
+ }))
45
+ };
46
+ }
47
+
48
+ // src/tools/wrap.ts
49
+ import { parseEther, formatEther as formatEther2 } from "viem";
50
+ async function wrapSteth(amountSteth, dryRun) {
51
+ const rt = getRuntime();
52
+ const amount = parseEther(amountSteth);
53
+ const shouldDryRun = rt.config.mode === "simulation" ? dryRun !== false : !!dryRun;
54
+ const expectedWstETH = await rt.sdk.wrap.convertStethToWsteth(amount);
55
+ if (shouldDryRun) {
56
+ return {
57
+ simulated: true,
58
+ mode: rt.config.mode,
59
+ network: rt.chainAddresses.name,
60
+ action: "wrap_steth",
61
+ amountSteth,
62
+ expectedWstETH: formatEther2(expectedWstETH),
63
+ note: "wstETH is non-rebasing \u2014 balance stays fixed while value grows. Better for DeFi."
64
+ };
65
+ }
66
+ const account = rt.getAddress();
67
+ const tx = await rt.sdk.wrap.wrapSteth({
68
+ value: amount,
69
+ account,
70
+ callback: () => {
71
+ }
72
+ });
73
+ return {
74
+ simulated: false,
75
+ mode: rt.config.mode,
76
+ network: rt.chainAddresses.name,
77
+ action: "wrap_steth",
78
+ amountSteth,
79
+ txHash: tx.hash,
80
+ wstethReceived: formatEther2(tx.result?.wstethReceived ?? 0n)
81
+ };
82
+ }
83
+ async function unwrapWsteth(amountWsteth, dryRun) {
84
+ const rt = getRuntime();
85
+ const amount = parseEther(amountWsteth);
86
+ const shouldDryRun = rt.config.mode === "simulation" ? dryRun !== false : !!dryRun;
87
+ const expectedStETH = await rt.sdk.wrap.convertWstethToSteth(amount);
88
+ if (shouldDryRun) {
89
+ return {
90
+ simulated: true,
91
+ mode: rt.config.mode,
92
+ network: rt.chainAddresses.name,
93
+ action: "unwrap_wsteth",
94
+ amountWsteth,
95
+ expectedStETH: formatEther2(expectedStETH),
96
+ note: "Unwrapping gives rebasing stETH back. Balance updates daily with rewards."
97
+ };
98
+ }
99
+ const account = rt.getAddress();
100
+ const tx = await rt.sdk.wrap.unwrap({
101
+ value: amount,
102
+ account,
103
+ callback: () => {
104
+ }
105
+ });
106
+ return {
107
+ simulated: false,
108
+ mode: rt.config.mode,
109
+ network: rt.chainAddresses.name,
110
+ action: "unwrap_wsteth",
111
+ amountWsteth,
112
+ txHash: tx.hash,
113
+ stethReceived: formatEther2(tx.result?.stethReceived ?? 0n)
114
+ };
115
+ }
116
+ async function getConversionRate() {
117
+ const rt = getRuntime();
118
+ const oneEther = parseEther("1");
119
+ const [wstethPerSteth, stethPerWsteth] = await Promise.all([
120
+ rt.sdk.wrap.convertStethToWsteth(oneEther),
121
+ rt.sdk.wrap.convertWstethToSteth(oneEther)
122
+ ]);
123
+ return {
124
+ mode: rt.config.mode,
125
+ network: rt.chainAddresses.name,
126
+ "1_stETH_in_wstETH": formatEther2(wstethPerSteth),
127
+ "1_wstETH_in_stETH": formatEther2(stethPerWsteth),
128
+ note: "wstETH/stETH ratio increases over time as staking rewards accumulate."
129
+ };
130
+ }
131
+
132
+ export {
133
+ getBalance,
134
+ getRewards,
135
+ wrapSteth,
136
+ unwrapWsteth,
137
+ getConversionRate
138
+ };
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  applySettingsUpdate,
4
4
  getRuntime
5
- } from "./chunk-TISPNEN6.js";
5
+ } from "./chunk-2MF5MDUT.js";
6
6
  import {
7
7
  loadConfig,
8
8
  redactedConfig
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  getRuntime
4
- } from "./chunk-TISPNEN6.js";
4
+ } from "./chunk-2MF5MDUT.js";
5
5
 
6
6
  // src/tools/unstake.ts
7
7
  import { parseEther, formatEther } from "viem";
@@ -3,7 +3,7 @@ import {
3
3
  getProposals,
4
4
  getWithdrawalRequests,
5
5
  getWithdrawalStatus
6
- } from "./chunk-6ZOV6GSP.js";
6
+ } from "./chunk-XXQ6WZSM.js";
7
7
  import {
8
8
  loadAlerts,
9
9
  loadChannelConfig,
@@ -12,9 +12,11 @@ import {
12
12
  import {
13
13
  getBalance,
14
14
  getConversionRate,
15
- getRewards,
15
+ getRewards
16
+ } from "./chunk-EG76IABG.js";
17
+ import {
16
18
  getRuntime
17
- } from "./chunk-TISPNEN6.js";
19
+ } from "./chunk-2MF5MDUT.js";
18
20
  import "./chunk-P6VFMSPM.js";
19
21
  import "./chunk-PDX44BCA.js";
20
22
 
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  getTotalPosition
4
- } from "./chunk-F4OVF3FT.js";
5
- import "./chunk-TISPNEN6.js";
4
+ } from "./chunk-7CNNGPGY.js";
5
+ import "./chunk-EG76IABG.js";
6
+ import "./chunk-2MF5MDUT.js";
6
7
  import "./chunk-P6VFMSPM.js";
7
8
  import "./chunk-PDX44BCA.js";
8
9
  export {
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ applySettingsUpdate,
4
+ getRuntime
5
+ } from "./chunk-2MF5MDUT.js";
6
+ import "./chunk-P6VFMSPM.js";
7
+ import "./chunk-PDX44BCA.js";
8
+ export {
9
+ applySettingsUpdate,
10
+ getRuntime
11
+ };
@@ -3,7 +3,7 @@ import {
3
3
  getSettings,
4
4
  stakeEth,
5
5
  updateSettings
6
- } from "../chunk-DEQ35QKH.js";
6
+ } from "../chunk-L5CW67AP.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-6ZOV6GSP.js";
15
+ } from "../chunk-XXQ6WZSM.js";
16
16
  import {
17
17
  configureAlertChannels,
18
18
  listAlerts,
@@ -26,14 +26,15 @@ import {
26
26
  getBridgeStatus,
27
27
  getL2Balance,
28
28
  getTotalPosition
29
- } from "../chunk-F4OVF3FT.js";
29
+ } from "../chunk-7CNNGPGY.js";
30
30
  import {
31
31
  getBalance,
32
32
  getConversionRate,
33
33
  getRewards,
34
34
  unwrapWsteth,
35
35
  wrapSteth
36
- } from "../chunk-TISPNEN6.js";
36
+ } from "../chunk-EG76IABG.js";
37
+ import "../chunk-2MF5MDUT.js";
37
38
  import {
38
39
  loadConfig
39
40
  } from "../chunk-P6VFMSPM.js";
@@ -185,6 +186,15 @@ server.tool(
185
186
  content: [{ type: "text", text: JSON.stringify(await castVote(proposal_id, support, dry_run), null, 2) }]
186
187
  })
187
188
  );
189
+ server.tool(
190
+ "get_wallet",
191
+ "Get the configured wallet public address.",
192
+ {},
193
+ async () => {
194
+ const addr = rt.getAddress();
195
+ return { content: [{ type: "text", text: JSON.stringify({ address: addr }, null, 2) }] };
196
+ }
197
+ );
188
198
  server.tool(
189
199
  "get_settings",
190
200
  "Get current Moly configuration \u2014 mode, network, RPC, and AI provider. Private key and API keys are never exposed.",
@@ -3,7 +3,7 @@ import {
3
3
  getSettings,
4
4
  stakeEth,
5
5
  updateSettings
6
- } from "./chunk-DEQ35QKH.js";
6
+ } from "./chunk-L5CW67AP.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-6ZOV6GSP.js";
15
+ } from "./chunk-XXQ6WZSM.js";
16
16
  import {
17
17
  configureAlertChannels,
18
18
  listAlerts,
@@ -26,14 +26,15 @@ import {
26
26
  getBridgeStatus,
27
27
  getL2Balance,
28
28
  getTotalPosition
29
- } from "./chunk-F4OVF3FT.js";
29
+ } from "./chunk-7CNNGPGY.js";
30
30
  import {
31
31
  getBalance,
32
32
  getConversionRate,
33
33
  getRewards,
34
34
  unwrapWsteth,
35
35
  wrapSteth
36
- } from "./chunk-TISPNEN6.js";
36
+ } from "./chunk-EG76IABG.js";
37
+ import "./chunk-2MF5MDUT.js";
37
38
  import "./chunk-P6VFMSPM.js";
38
39
  import {
39
40
  loadBounds,
@@ -348,6 +349,11 @@ var TOOL_DEFS = [
348
349
  }
349
350
  }
350
351
  },
352
+ {
353
+ name: "get_wallet",
354
+ description: "Get the configured wallet public address.",
355
+ parameters: { type: "object", properties: {} }
356
+ },
351
357
  {
352
358
  name: "get_settings",
353
359
  description: "Get current Moly configuration.",
@@ -554,6 +560,12 @@ async function executeTool(name, args) {
554
560
  case "cast_vote":
555
561
  result = await castVote(args.proposal_id, args.support, args.dry_run);
556
562
  break;
563
+ case "get_wallet": {
564
+ const { getRuntime } = await import("./runtime-PGSRZ7YU.js");
565
+ const addr = getRuntime().getAddress();
566
+ result = { address: addr };
567
+ break;
568
+ }
557
569
  case "get_settings":
558
570
  result = getSettings();
559
571
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moly-mcp/lido",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
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",