web3-tools-mcp 1.3.3 → 1.4.0

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.
Files changed (57) hide show
  1. package/README.md +51 -4
  2. package/dist/anvil.d.ts +34 -0
  3. package/dist/anvil.d.ts.map +1 -0
  4. package/dist/anvil.js +254 -0
  5. package/dist/anvil.js.map +1 -0
  6. package/dist/client.d.ts +3 -0
  7. package/dist/client.d.ts.map +1 -1
  8. package/dist/client.js +13 -2
  9. package/dist/client.js.map +1 -1
  10. package/dist/index.js +25 -5
  11. package/dist/index.js.map +1 -1
  12. package/dist/preview.d.ts +55 -0
  13. package/dist/preview.d.ts.map +1 -0
  14. package/dist/preview.js +233 -0
  15. package/dist/preview.js.map +1 -0
  16. package/dist/tools/advanced.d.ts +67 -9
  17. package/dist/tools/advanced.d.ts.map +1 -1
  18. package/dist/tools/advanced.js +206 -67
  19. package/dist/tools/advanced.js.map +1 -1
  20. package/dist/tools/balance.d.ts +5 -5
  21. package/dist/tools/contract-info.d.ts +9 -9
  22. package/dist/tools/contract.d.ts +8 -8
  23. package/dist/tools/contract.d.ts.map +1 -1
  24. package/dist/tools/contract.js +3 -0
  25. package/dist/tools/contract.js.map +1 -1
  26. package/dist/tools/ens.d.ts +15 -15
  27. package/dist/tools/gas.d.ts +18 -18
  28. package/dist/tools/logs.d.ts +3 -3
  29. package/dist/tools/transactions.d.ts +9 -9
  30. package/dist/tools/transactions.d.ts.map +1 -1
  31. package/dist/tools/transactions.js +92 -113
  32. package/dist/tools/transactions.js.map +1 -1
  33. package/dist/utils.d.ts +13 -0
  34. package/dist/utils.d.ts.map +1 -1
  35. package/dist/utils.js +76 -0
  36. package/dist/utils.js.map +1 -1
  37. package/dist/wallet-client.d.ts +83 -0
  38. package/dist/wallet-client.d.ts.map +1 -0
  39. package/dist/wallet-client.js +357 -0
  40. package/dist/wallet-client.js.map +1 -0
  41. package/package.json +9 -8
  42. package/src/anvil.ts +323 -0
  43. package/src/client.ts +16 -2
  44. package/src/index.ts +26 -5
  45. package/src/preview.ts +320 -0
  46. package/src/tools/advanced.ts +239 -70
  47. package/src/tools/contract.ts +3 -0
  48. package/src/tools/transactions.ts +98 -125
  49. package/src/utils.ts +95 -0
  50. package/src/wallet-client.ts +380 -0
  51. package/dist/wallet-server.d.ts +0 -35
  52. package/dist/wallet-server.d.ts.map +0 -1
  53. package/dist/wallet-server.js +0 -232
  54. package/dist/wallet-server.js.map +0 -1
  55. package/public/wallet-app.js +0 -677
  56. package/public/wallet.html +0 -723
  57. package/src/wallet-server.ts +0 -283
@@ -1,283 +0,0 @@
1
- import express from 'express'
2
- import cors from 'cors'
3
- import { WebSocketServer, WebSocket } from 'ws'
4
- import { createServer } from 'http'
5
- import { fileURLToPath } from 'url'
6
- import { dirname, join } from 'path'
7
- import { exec } from 'child_process'
8
-
9
- const __filename = fileURLToPath(import.meta.url)
10
- const __dirname = dirname(__filename)
11
-
12
- export interface TransactionRequest {
13
- id: string
14
- type: 'send_transaction' | 'sign_message' | 'sign_typed_data'
15
- chain: string
16
- data: unknown
17
- }
18
-
19
- export interface TransactionResponse {
20
- id: string
21
- success: boolean
22
- result?: unknown
23
- error?: string
24
- }
25
-
26
- export class WalletServer {
27
- private app: express.Application
28
- private httpServer: ReturnType<typeof createServer>
29
- private wss: WebSocketServer
30
- private clients: Set<WebSocket> = new Set()
31
- private pendingRequests: Map<string, {
32
- resolve: (value: unknown) => void
33
- reject: (error: Error) => void
34
- }> = new Map()
35
- private port: number
36
- private isStarted = false
37
-
38
- constructor(port = 3456) {
39
- this.port = port
40
- this.app = express()
41
- this.httpServer = createServer(this.app)
42
- this.wss = new WebSocketServer({ server: this.httpServer })
43
-
44
- this.setupExpress()
45
- this.setupWebSocket()
46
- }
47
-
48
- private setupExpress() {
49
- this.app.use(cors())
50
- this.app.use(express.json())
51
- this.app.use(express.static(join(__dirname, '..', 'public')))
52
-
53
- this.app.get('/', (_req, res) => {
54
- res.sendFile(join(__dirname, '..', 'public', 'wallet.html'))
55
- })
56
-
57
- this.app.get('/health', (_req, res) => {
58
- res.json({
59
- status: 'ok',
60
- clients: this.clients.size,
61
- pendingRequests: this.pendingRequests.size
62
- })
63
- })
64
- }
65
-
66
- private setupWebSocket() {
67
- this.wss.on('connection', (ws: WebSocket) => {
68
- console.error('[Wallet Server] Client connected')
69
- this.clients.add(ws)
70
-
71
- ws.on('message', (data: Buffer) => {
72
- try {
73
- const response: TransactionResponse = JSON.parse(data.toString())
74
- console.error('[Wallet Server] Received response:', response.id)
75
- console.error('[Wallet Server] Response data:', JSON.stringify(response))
76
-
77
- const pending = this.pendingRequests.get(response.id)
78
- if (pending) {
79
- if (response.success) {
80
- pending.resolve(response.result)
81
- } else {
82
- pending.reject(new Error(response.error || 'Transaction failed'))
83
- }
84
- this.pendingRequests.delete(response.id)
85
- }
86
- } catch (error) {
87
- console.error('[Wallet Server] Error parsing message:', error)
88
- }
89
- })
90
-
91
- ws.on('close', () => {
92
- console.error('[Wallet Server] Client disconnected')
93
- this.clients.delete(ws)
94
- })
95
-
96
- ws.on('error', (error) => {
97
- console.error('[Wallet Server] WebSocket error:', error)
98
- this.clients.delete(ws)
99
- })
100
- })
101
- }
102
-
103
- async start() {
104
- if (this.isStarted) {
105
- return
106
- }
107
-
108
- return this.startWithRetry()
109
- }
110
-
111
- private tryListen(port: number): Promise<void> {
112
- return new Promise((resolve, reject) => {
113
- // Create a fresh server for this attempt
114
- const tempServer = createServer(this.app)
115
-
116
- const cleanup = () => {
117
- tempServer.removeAllListeners()
118
- }
119
-
120
- const onError = (error: NodeJS.ErrnoException) => {
121
- cleanup()
122
- reject(error)
123
- }
124
-
125
- const onListening = () => {
126
- cleanup()
127
- // Success! Replace our server instance with this working one
128
- this.httpServer = tempServer
129
- this.wss = new WebSocketServer({ server: this.httpServer })
130
- this.setupWebSocket()
131
- resolve()
132
- }
133
-
134
- tempServer.once('error', onError)
135
- tempServer.once('listening', onListening)
136
- tempServer.listen(port)
137
- })
138
- }
139
-
140
- private async startWithRetry(maxAttempts = 10): Promise<void> {
141
- const originalPort = this.port
142
-
143
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
144
- try {
145
- await this.tryListen(this.port)
146
-
147
- // Success - server started
148
- this.isStarted = true
149
- if (this.port !== originalPort) {
150
- console.error(`[Wallet Server] Port ${originalPort} was in use, using port ${this.port} instead`)
151
- }
152
- console.error(`[Wallet Server] Running on http://localhost:${this.port}`)
153
- return
154
- } catch (error: unknown) {
155
- const errnoError = error as NodeJS.ErrnoException
156
- if (errnoError.code === 'EADDRINUSE') {
157
- console.error(`[Wallet Server] Port ${this.port} in use, trying port ${this.port + 1}...`)
158
- this.port++
159
- } else {
160
- throw error
161
- }
162
- }
163
- }
164
-
165
- // If we exhausted all attempts
166
- throw new Error(
167
- `Failed to start wallet server: Ports ${originalPort}-${originalPort + maxAttempts - 1} are all in use. ` +
168
- `Please free up a port or specify a different starting port.`
169
- )
170
- }
171
-
172
- async stop() {
173
- return new Promise<void>((resolve) => {
174
- this.clients.forEach(client => client.close())
175
- this.wss.close(() => {
176
- this.httpServer.close(() => {
177
- this.isStarted = false
178
- console.error('[Wallet Server] Stopped')
179
- resolve()
180
- })
181
- })
182
- })
183
- }
184
-
185
- openBrowser() {
186
- const url = `http://localhost:${this.port}`
187
- const platform = process.platform
188
-
189
- let command: string
190
- if (platform === 'darwin') {
191
- command = `open "${url}"`
192
- } else if (platform === 'win32') {
193
- command = `start "${url}"`
194
- } else {
195
- command = `xdg-open "${url}"`
196
- }
197
-
198
- exec(command, (error) => {
199
- if (error) {
200
- console.error('[Wallet Server] Failed to open browser:', error)
201
- console.error(`[Wallet Server] Please open manually: ${url}`)
202
- } else {
203
- console.error(`[Wallet Server] Opened browser at ${url}`)
204
- }
205
- })
206
- }
207
-
208
- async sendTransaction(request: TransactionRequest): Promise<unknown> {
209
- if (!this.isStarted) {
210
- await this.start()
211
- }
212
-
213
- // Always open/focus browser for transaction requests
214
- this.openBrowser()
215
-
216
- // Open browser if no clients connected
217
- if (this.clients.size === 0) {
218
- // Wait for client to connect (max 30 seconds)
219
- const timeout = 30000
220
- const startTime = Date.now()
221
- while (this.clients.size === 0 && Date.now() - startTime < timeout) {
222
- await new Promise(resolve => setTimeout(resolve, 500))
223
- }
224
-
225
- if (this.clients.size === 0) {
226
- throw new Error('No wallet connected. Please open the browser and connect your wallet.')
227
- }
228
- }
229
-
230
- return new Promise((resolve, reject) => {
231
- this.pendingRequests.set(request.id, { resolve, reject })
232
-
233
- // Send to first available connected client only
234
- const message = JSON.stringify(request)
235
- let sent = false
236
- for (const client of this.clients) {
237
- if (client.readyState === WebSocket.OPEN) {
238
- client.send(message)
239
- sent = true
240
- break
241
- }
242
- }
243
-
244
- if (!sent) {
245
- this.pendingRequests.delete(request.id)
246
- reject(new Error('No active wallet connection'))
247
- return
248
- }
249
-
250
- // Timeout after 5 minutes
251
- setTimeout(() => {
252
- if (this.pendingRequests.has(request.id)) {
253
- this.pendingRequests.delete(request.id)
254
- reject(new Error('Transaction request timed out'))
255
- }
256
- }, 300000)
257
- })
258
- }
259
-
260
- isConnected(): boolean {
261
- return this.clients.size > 0
262
- }
263
-
264
- getPort(): number {
265
- return this.port
266
- }
267
- }
268
-
269
- // Singleton instance
270
- let walletServer: WalletServer | null = null
271
-
272
- export function getWalletServer(): WalletServer {
273
- if (!walletServer) {
274
- walletServer = new WalletServer()
275
- }
276
- return walletServer
277
- }
278
-
279
- export async function startWalletServer(): Promise<WalletServer> {
280
- const server = getWalletServer()
281
- await server.start()
282
- return server
283
- }