@moly-mcp/lido 1.1.7 → 1.1.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
@@ -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-3DBQ42LL.js");
355
+ const { startChatSession } = await import("./session-PHGJFQSX.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-7RRWSIRO.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-KAQOSX2P.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-3DBQ42LL.js");
604
+ const { startChatSession } = await import("./session-PHGJFQSX.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-3DBQ42LL.js");
611
+ const { startChatSession } = await import("./session-PHGJFQSX.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-3DBQ42LL.js");
683
+ const { startChatSession } = await import("./session-PHGJFQSX.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() {
@@ -141,7 +151,9 @@ function buildRuntime() {
141
151
  config,
142
152
  chainAddresses: chainCfg,
143
153
  publicClient,
144
- sdk,
154
+ get sdk() {
155
+ return getSdk();
156
+ },
145
157
  getWallet,
146
158
  getAddress,
147
159
  getL2PublicClient,
@@ -167,139 +179,8 @@ function applySettingsUpdate(patch) {
167
179
  return current;
168
180
  }
169
181
 
170
- // src/tools/balance.ts
171
- import { formatEther } from "viem";
172
- async function getBalance(address) {
173
- const rt = getRuntime();
174
- const addr = address ?? rt.getAddress();
175
- const [eth, steth, wsteth] = await Promise.all([
176
- rt.sdk.core.balanceETH(addr),
177
- rt.sdk.steth.balance(addr),
178
- rt.sdk.wsteth.balance(addr)
179
- ]);
180
- return {
181
- address: addr,
182
- mode: rt.config.mode,
183
- network: rt.chainAddresses.name,
184
- balances: {
185
- eth: formatEther(eth),
186
- stETH: formatEther(steth),
187
- wstETH: formatEther(wsteth)
188
- }
189
- };
190
- }
191
- async function getRewards(address, days = 7) {
192
- const rt = getRuntime();
193
- const addr = address ?? rt.getAddress();
194
- const rewards = await rt.sdk.rewards.getRewardsFromChain({
195
- address: addr,
196
- stepBlock: 1e3,
197
- back: { days: BigInt(days) }
198
- });
199
- return {
200
- address: addr,
201
- period: `${days} days`,
202
- totalRewards: formatEther(rewards.totalRewards),
203
- baseBalance: formatEther(rewards.baseBalance),
204
- rewards: rewards.rewards.slice(0, 10).map((e) => ({
205
- type: e.type,
206
- change: formatEther(e.change),
207
- balance: formatEther(e.balance)
208
- }))
209
- };
210
- }
211
-
212
- // src/tools/wrap.ts
213
- import { parseEther, formatEther as formatEther2 } from "viem";
214
- async function wrapSteth(amountSteth, dryRun) {
215
- const rt = getRuntime();
216
- const amount = parseEther(amountSteth);
217
- const shouldDryRun = rt.config.mode === "simulation" ? dryRun !== false : !!dryRun;
218
- const expectedWstETH = await rt.sdk.wrap.convertStethToWsteth(amount);
219
- if (shouldDryRun) {
220
- return {
221
- simulated: true,
222
- mode: rt.config.mode,
223
- network: rt.chainAddresses.name,
224
- action: "wrap_steth",
225
- amountSteth,
226
- expectedWstETH: formatEther2(expectedWstETH),
227
- note: "wstETH is non-rebasing \u2014 balance stays fixed while value grows. Better for DeFi."
228
- };
229
- }
230
- const account = rt.getAddress();
231
- const tx = await rt.sdk.wrap.wrapSteth({
232
- value: amount,
233
- account,
234
- callback: () => {
235
- }
236
- });
237
- return {
238
- simulated: false,
239
- mode: rt.config.mode,
240
- network: rt.chainAddresses.name,
241
- action: "wrap_steth",
242
- amountSteth,
243
- txHash: tx.hash,
244
- wstethReceived: formatEther2(tx.result?.wstethReceived ?? 0n)
245
- };
246
- }
247
- async function unwrapWsteth(amountWsteth, dryRun) {
248
- const rt = getRuntime();
249
- const amount = parseEther(amountWsteth);
250
- const shouldDryRun = rt.config.mode === "simulation" ? dryRun !== false : !!dryRun;
251
- const expectedStETH = await rt.sdk.wrap.convertWstethToSteth(amount);
252
- if (shouldDryRun) {
253
- return {
254
- simulated: true,
255
- mode: rt.config.mode,
256
- network: rt.chainAddresses.name,
257
- action: "unwrap_wsteth",
258
- amountWsteth,
259
- expectedStETH: formatEther2(expectedStETH),
260
- note: "Unwrapping gives rebasing stETH back. Balance updates daily with rewards."
261
- };
262
- }
263
- const account = rt.getAddress();
264
- const tx = await rt.sdk.wrap.unwrap({
265
- value: amount,
266
- account,
267
- callback: () => {
268
- }
269
- });
270
- return {
271
- simulated: false,
272
- mode: rt.config.mode,
273
- network: rt.chainAddresses.name,
274
- action: "unwrap_wsteth",
275
- amountWsteth,
276
- txHash: tx.hash,
277
- stethReceived: formatEther2(tx.result?.stethReceived ?? 0n)
278
- };
279
- }
280
- async function getConversionRate() {
281
- const rt = getRuntime();
282
- const oneEther = parseEther("1");
283
- const [wstethPerSteth, stethPerWsteth] = await Promise.all([
284
- rt.sdk.wrap.convertStethToWsteth(oneEther),
285
- rt.sdk.wrap.convertWstethToSteth(oneEther)
286
- ]);
287
- return {
288
- mode: rt.config.mode,
289
- network: rt.chainAddresses.name,
290
- "1_stETH_in_wstETH": formatEther2(wstethPerSteth),
291
- "1_wstETH_in_stETH": formatEther2(stethPerWsteth),
292
- note: "wstETH/stETH ratio increases over time as staking rewards accumulate."
293
- };
294
- }
295
-
296
182
  export {
297
183
  L2_CHAINS,
298
184
  getRuntime,
299
- applySettingsUpdate,
300
- getBalance,
301
- getRewards,
302
- wrapSteth,
303
- unwrapWsteth,
304
- getConversionRate
185
+ applySettingsUpdate
305
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-RMJKM6MY.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,14 +2,14 @@
2
2
  import {
3
3
  applySettingsUpdate,
4
4
  getRuntime
5
- } from "./chunk-RMJKM6MY.js";
5
+ } from "./chunk-2MF5MDUT.js";
6
6
  import {
7
7
  loadConfig,
8
8
  redactedConfig
9
9
  } from "./chunk-P6VFMSPM.js";
10
10
 
11
11
  // src/tools/stake.ts
12
- import { parseEther, formatEther } from "viem";
12
+ import { parseEther } from "viem";
13
13
  var SUBMIT_ABI = [
14
14
  {
15
15
  name: "submit",
@@ -50,22 +50,24 @@ async function stakeEth(amountEth, dryRun) {
50
50
  note: "stETH rebases daily \u2014 your balance grows automatically after staking."
51
51
  };
52
52
  }
53
- const account = rt.getAddress();
54
- const tx = await rt.sdk.stake.stakeEth({
55
- value,
56
- account: { address: account },
57
- callback: () => {
58
- }
53
+ const wallet = rt.getWallet();
54
+ const hash = await wallet.writeContract({
55
+ address: lidoAddress,
56
+ abi: SUBMIT_ABI,
57
+ functionName: "submit",
58
+ args: [REFERRAL],
59
+ value
59
60
  });
61
+ const receipt = await rt.publicClient.waitForTransactionReceipt({ hash });
60
62
  return {
61
63
  simulated: false,
62
64
  mode: rt.config.mode,
63
65
  network: rt.chainAddresses.name,
64
66
  action: "stake",
65
67
  amountEth,
66
- txHash: tx.hash,
67
- stethReceived: formatEther(tx.result?.stethReceived ?? 0n),
68
- sharesReceived: formatEther(tx.result?.sharesReceived ?? 0n)
68
+ txHash: hash,
69
+ status: receipt.status,
70
+ gasUsed: receipt.gasUsed.toString()
69
71
  };
70
72
  }
71
73
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  getRuntime
4
- } from "./chunk-RMJKM6MY.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-4VFTMLNC.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-RMJKM6MY.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-M5H5IPOL.js";
5
- import "./chunk-RMJKM6MY.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-EGPNTAOB.js";
6
+ } from "../chunk-S4ONJBCI.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-4VFTMLNC.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-M5H5IPOL.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-RMJKM6MY.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-EGPNTAOB.js";
6
+ } from "./chunk-S4ONJBCI.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-4VFTMLNC.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-M5H5IPOL.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-RMJKM6MY.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.7",
3
+ "version": "1.1.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",