web3-tools-mcp 2.0.2 → 3.0.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 (162) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/README.md +5 -0
  3. package/dist/anvil.d.ts +17 -19
  4. package/dist/anvil.d.ts.map +1 -1
  5. package/dist/anvil.js +124 -228
  6. package/dist/anvil.js.map +1 -1
  7. package/dist/chains.d.ts +9 -1
  8. package/dist/chains.d.ts.map +1 -1
  9. package/dist/chains.js +11 -2
  10. package/dist/chains.js.map +1 -1
  11. package/dist/client.d.ts.map +1 -1
  12. package/dist/client.js.map +1 -1
  13. package/dist/context.d.ts +22 -0
  14. package/dist/context.d.ts.map +1 -0
  15. package/dist/context.js +24 -0
  16. package/dist/context.js.map +1 -0
  17. package/dist/hosted.d.ts +12 -0
  18. package/dist/hosted.d.ts.map +1 -0
  19. package/dist/hosted.js +12 -0
  20. package/dist/hosted.js.map +1 -0
  21. package/dist/http-server.d.ts +13 -0
  22. package/dist/http-server.d.ts.map +1 -1
  23. package/dist/http-server.js +13 -4
  24. package/dist/http-server.js.map +1 -1
  25. package/dist/index.js +15 -11
  26. package/dist/index.js.map +1 -1
  27. package/dist/lib.d.ts +24 -0
  28. package/dist/lib.d.ts.map +1 -0
  29. package/dist/lib.js +23 -0
  30. package/dist/lib.js.map +1 -0
  31. package/dist/mcp-server.d.ts +4 -0
  32. package/dist/mcp-server.d.ts.map +1 -0
  33. package/dist/mcp-server.js +43 -0
  34. package/dist/mcp-server.js.map +1 -0
  35. package/dist/oauth.d.ts +41 -6
  36. package/dist/oauth.d.ts.map +1 -1
  37. package/dist/oauth.js +75 -41
  38. package/dist/oauth.js.map +1 -1
  39. package/dist/preview.d.ts +7 -0
  40. package/dist/preview.d.ts.map +1 -1
  41. package/dist/preview.js +14 -2
  42. package/dist/preview.js.map +1 -1
  43. package/dist/signing-requests.d.ts +81 -0
  44. package/dist/signing-requests.d.ts.map +1 -0
  45. package/dist/signing-requests.js +138 -0
  46. package/dist/signing-requests.js.map +1 -0
  47. package/dist/tools/index.d.ts +27 -1
  48. package/dist/tools/index.d.ts.map +1 -1
  49. package/dist/tools/index.js +37 -15
  50. package/dist/tools/index.js.map +1 -1
  51. package/dist/tools/{advanced.d.ts → read/advanced.d.ts} +30 -26
  52. package/dist/tools/read/advanced.d.ts.map +1 -0
  53. package/dist/tools/{advanced.js → read/advanced.js} +10 -10
  54. package/dist/tools/read/advanced.js.map +1 -0
  55. package/dist/tools/{balance.d.ts → read/balance.d.ts} +8 -7
  56. package/dist/tools/read/balance.d.ts.map +1 -0
  57. package/dist/tools/{balance.js → read/balance.js} +2 -2
  58. package/dist/tools/read/balance.js.map +1 -0
  59. package/dist/tools/{contract-info.d.ts → read/contract-info.d.ts} +18 -15
  60. package/dist/tools/read/contract-info.d.ts.map +1 -0
  61. package/dist/tools/{contract-info.js → read/contract-info.js} +2 -2
  62. package/dist/tools/read/contract-info.js.map +1 -0
  63. package/dist/tools/{contract.d.ts → read/contract.d.ts} +14 -12
  64. package/dist/tools/read/contract.d.ts.map +1 -0
  65. package/dist/tools/{contract.js → read/contract.js} +2 -2
  66. package/dist/tools/read/contract.js.map +1 -0
  67. package/dist/tools/{ens.d.ts → read/ens.d.ts} +30 -25
  68. package/dist/tools/read/ens.d.ts.map +1 -0
  69. package/dist/tools/{ens.js → read/ens.js} +2 -2
  70. package/dist/tools/read/ens.js.map +1 -0
  71. package/dist/tools/read/gas.d.ts +171 -0
  72. package/dist/tools/read/gas.d.ts.map +1 -0
  73. package/dist/tools/read/gas.js +368 -0
  74. package/dist/tools/read/gas.js.map +1 -0
  75. package/dist/tools/{logs.d.ts → read/logs.d.ts} +6 -5
  76. package/dist/tools/read/logs.d.ts.map +1 -0
  77. package/dist/tools/{logs.js → read/logs.js} +2 -2
  78. package/dist/tools/read/logs.js.map +1 -0
  79. package/dist/tools/{signatures.d.ts → read/signatures.d.ts} +8 -4
  80. package/dist/tools/read/signatures.d.ts.map +1 -0
  81. package/dist/tools/{signatures.js → read/signatures.js} +1 -1
  82. package/dist/tools/read/signatures.js.map +1 -0
  83. package/dist/tools/read/signing.d.ts +27 -0
  84. package/dist/tools/read/signing.d.ts.map +1 -0
  85. package/dist/tools/read/signing.js +75 -0
  86. package/dist/tools/read/signing.js.map +1 -0
  87. package/dist/tools/sign/errors.d.ts +9 -0
  88. package/dist/tools/sign/errors.d.ts.map +1 -0
  89. package/dist/tools/sign/errors.js +29 -0
  90. package/dist/tools/sign/errors.js.map +1 -0
  91. package/dist/tools/{transactions.d.ts → sign/transactions.d.ts} +48 -62
  92. package/dist/tools/sign/transactions.d.ts.map +1 -0
  93. package/dist/tools/sign/transactions.js +316 -0
  94. package/dist/tools/sign/transactions.js.map +1 -0
  95. package/dist/tools/sign/wallet.d.ts +50 -0
  96. package/dist/tools/sign/wallet.d.ts.map +1 -0
  97. package/dist/tools/sign/wallet.js +180 -0
  98. package/dist/tools/sign/wallet.js.map +1 -0
  99. package/dist/utils.d.ts +5 -2
  100. package/dist/utils.d.ts.map +1 -1
  101. package/dist/utils.js +5 -2
  102. package/dist/utils.js.map +1 -1
  103. package/dist/wallet-client.d.ts +33 -4
  104. package/dist/wallet-client.d.ts.map +1 -1
  105. package/dist/wallet-client.js +90 -24
  106. package/dist/wallet-client.js.map +1 -1
  107. package/dist/walletconnect.d.ts +100 -13
  108. package/dist/walletconnect.d.ts.map +1 -1
  109. package/dist/walletconnect.js +215 -50
  110. package/dist/walletconnect.js.map +1 -1
  111. package/package.json +10 -4
  112. package/src/anvil.ts +150 -271
  113. package/src/chains.ts +14 -2
  114. package/src/client.ts +0 -1
  115. package/src/context.ts +27 -0
  116. package/src/hosted.ts +11 -0
  117. package/src/http-server.ts +30 -5
  118. package/src/index.ts +15 -12
  119. package/src/lib.ts +24 -0
  120. package/src/mcp-server.ts +47 -0
  121. package/src/oauth.ts +98 -45
  122. package/src/preview.ts +21 -2
  123. package/src/signing-requests.ts +198 -0
  124. package/src/tools/index.ts +67 -16
  125. package/src/tools/{advanced.ts → read/advanced.ts} +13 -11
  126. package/src/tools/{balance.ts → read/balance.ts} +3 -3
  127. package/src/tools/{contract-info.ts → read/contract-info.ts} +3 -3
  128. package/src/tools/{contract.ts → read/contract.ts} +3 -3
  129. package/src/tools/{ens.ts → read/ens.ts} +3 -3
  130. package/src/tools/read/gas.ts +480 -0
  131. package/src/tools/{logs.ts → read/logs.ts} +3 -3
  132. package/src/tools/{signatures.ts → read/signatures.ts} +2 -2
  133. package/src/tools/read/signing.ts +86 -0
  134. package/src/tools/sign/errors.ts +28 -0
  135. package/src/tools/sign/transactions.ts +428 -0
  136. package/src/tools/sign/wallet.ts +216 -0
  137. package/src/utils.ts +5 -2
  138. package/src/wallet-client.ts +91 -22
  139. package/src/walletconnect.ts +250 -48
  140. package/dist/tools/advanced.d.ts.map +0 -1
  141. package/dist/tools/advanced.js.map +0 -1
  142. package/dist/tools/balance.d.ts.map +0 -1
  143. package/dist/tools/balance.js.map +0 -1
  144. package/dist/tools/contract-info.d.ts.map +0 -1
  145. package/dist/tools/contract-info.js.map +0 -1
  146. package/dist/tools/contract.d.ts.map +0 -1
  147. package/dist/tools/contract.js.map +0 -1
  148. package/dist/tools/ens.d.ts.map +0 -1
  149. package/dist/tools/ens.js.map +0 -1
  150. package/dist/tools/gas.d.ts +0 -99
  151. package/dist/tools/gas.d.ts.map +0 -1
  152. package/dist/tools/gas.js +0 -181
  153. package/dist/tools/gas.js.map +0 -1
  154. package/dist/tools/logs.d.ts.map +0 -1
  155. package/dist/tools/logs.js.map +0 -1
  156. package/dist/tools/signatures.d.ts.map +0 -1
  157. package/dist/tools/signatures.js.map +0 -1
  158. package/dist/tools/transactions.d.ts.map +0 -1
  159. package/dist/tools/transactions.js +0 -365
  160. package/dist/tools/transactions.js.map +0 -1
  161. package/src/tools/gas.ts +0 -219
  162. package/src/tools/transactions.ts +0 -456
@@ -1,365 +0,0 @@
1
- import { randomBytes } from 'node:crypto';
2
- import qrcode from 'qrcode-terminal';
3
- import { encodeFunctionData, isAddress, parseAbiItem, parseUnits, toHex } from 'viem';
4
- import { z } from 'zod';
5
- import { getClientManager, SUPPORTED_CHAINS } from '../client.js';
6
- import { log } from '../log.js';
7
- import { buildTxPreview } from '../preview.js';
8
- import { createTool, formatResponse } from '../utils.js';
9
- import { getWalletClient } from '../wallet-client.js';
10
- import { getPhoneSigner, pairingLinks } from '../walletconnect.js';
11
- /** Render a pairing URI as an ASCII QR, so it can be scanned straight from the chat. */
12
- function qrFor(uri) {
13
- return new Promise((resolve) => qrcode.generate(uri, { small: true }, resolve));
14
- }
15
- function generateRequestId() {
16
- return randomBytes(16).toString('hex');
17
- }
18
- function requireAddress(label, address) {
19
- if (!isAddress(address))
20
- throw new Error(`Invalid ${label}: ${address}`);
21
- return address;
22
- }
23
- function explorerTxUrl(chain, txHash) {
24
- return getClientManager().explorerUrl(chain, `/tx/${txHash}`);
25
- }
26
- /**
27
- * Which wallet to send the request to. Deliberately required on every signing tool: both
28
- * signers can be live at once, and only the person holding the devices knows which one is
29
- * actually to hand. Guessing strands the request in front of a screen nobody is looking at.
30
- *
31
- * Either way the transaction is decoded and simulated first — the wallet shows its own
32
- * summary, so the preview is returned to the caller too, to be read before approving.
33
- */
34
- const SignWithSchema = z
35
- .enum(['phone', 'browser'])
36
- .describe('Where to approve this: "phone" for a paired WalletConnect wallet, "browser" for the wallet signing page. Ask the user which they want — do not assume, even when only one is connected. Call wallet_status first: it says which signers are ready, and when no signing page is open it returns walletUrl. In that case give the user that link, ask them to open it and connect a wallet, and only call this once they confirm — a signing request cannot reach a page nobody has open.');
37
- async function signOnPhone(chain, tx) {
38
- const phone = getPhoneSigner();
39
- if (!phone) {
40
- throw new Error('Phone signing is not configured on this server. Set WALLETCONNECT_PROJECT_ID, or sign in the browser instead.');
41
- }
42
- if (!(await phone.isPaired())) {
43
- throw new Error('No phone wallet is paired. Run pair_phone_wallet and scan the QR, or sign in the browser instead.');
44
- }
45
- const session = await phone.session();
46
- const from = session?.accounts[0];
47
- const preview = await buildTxPreview(chain, tx, from);
48
- const txHash = await phone.request(chain, 'eth_sendTransaction', [
49
- { from, to: tx.to, value: tx.value ?? '0x0', ...(tx.data && { data: tx.data }) }
50
- ]);
51
- return { txHash, preview, signedWith: 'phone' };
52
- }
53
- async function requestSignature(chain, tx, signWith) {
54
- log('info', 'Transaction', `${chain} → ${tx.to}, signing with ${signWith}`);
55
- if (signWith === 'phone')
56
- return signOnPhone(chain, tx);
57
- const wallet = getWalletClient();
58
- await wallet.waitForSigner();
59
- const preview = await buildTxPreview(chain, tx, wallet.getAddress());
60
- return {
61
- txHash: await wallet.request({
62
- id: generateRequestId(),
63
- type: 'send_transaction',
64
- chain,
65
- data: { to: tx.to, value: tx.value ?? '0x0', ...(tx.data && { data: tx.data }) },
66
- preview
67
- }),
68
- preview,
69
- signedWith: 'browser'
70
- };
71
- }
72
- /** What the caller should see about a transaction before it is approved. */
73
- function previewSummary(preview) {
74
- return {
75
- action: preview.decoded?.intent ?? preview.decoded?.functionName,
76
- protocol: preview.decoded?.protocol ?? preview.toLabel,
77
- details: preview.decoded?.fields.map((f) => `${f.name}: ${f.value}${f.warning ? ` (${f.warning})` : ''}`),
78
- simulation: preview.simulation
79
- };
80
- }
81
- /**
82
- * WalletConnect rejects with a plain `{ code, message }` rather than an Error, which
83
- * String() renders as "[object Object]" — the reason a wallet gave for refusing is the
84
- * whole point of the message, so dig it out.
85
- */
86
- function describeError(error) {
87
- if (error instanceof Error)
88
- return error.message;
89
- if (error && typeof error === 'object') {
90
- const { message, code, reason } = error;
91
- const text = message ?? reason;
92
- if (text)
93
- return code === undefined ? text : `${text} (code ${code})`;
94
- return JSON.stringify(error);
95
- }
96
- return String(error);
97
- }
98
- function failure(error, message) {
99
- log('warning', 'Transaction', `${message} — ${describeError(error)}`);
100
- return formatResponse({
101
- success: false,
102
- error: describeError(error),
103
- message
104
- });
105
- }
106
- export default {
107
- send_native_token: createTool('Send Native Token', 'Send native tokens (ETH, MATIC, BNB, etc.) to an address. Simulates the transaction, then sends it to the signer you choose for approval.', z.object({
108
- chain: z.enum(SUPPORTED_CHAINS).describe('Blockchain network'),
109
- to: z.string().describe('Recipient address'),
110
- amount: z.string().describe('Amount in native token (e.g., "0.1" for 0.1 ETH)'),
111
- data: z.string().optional().describe('Optional hex-encoded data to include with transaction'),
112
- signWith: SignWithSchema
113
- }), async (args) => {
114
- try {
115
- const to = requireAddress('recipient address', args.to);
116
- const value = `0x${parseUnits(args.amount, 18).toString(16)}`;
117
- const { txHash, preview, signedWith } = await requestSignature(args.chain, { to, value, data: args.data }, args.signWith);
118
- return formatResponse({
119
- success: true,
120
- chain: args.chain,
121
- transactionHash: txHash,
122
- to,
123
- amount: args.amount,
124
- signedWith,
125
- preview: previewSummary(preview),
126
- explorerUrl: explorerTxUrl(args.chain, txHash)
127
- });
128
- }
129
- catch (error) {
130
- return failure(error, 'Transaction failed or was rejected');
131
- }
132
- }),
133
- send_erc20_token: createTool('Send ERC20 Token', 'Send ERC20 tokens to an address. Simulates the transfer, then sends it to the signer you choose for approval.', z.object({
134
- chain: z.enum(SUPPORTED_CHAINS).describe('Blockchain network'),
135
- tokenAddress: z.string().describe('ERC20 token contract address'),
136
- to: z.string().describe('Recipient address'),
137
- amount: z.string().describe('Amount in token units (e.g., "100" for 100 USDC)'),
138
- decimals: z.number().optional().default(18).describe('Token decimals (default: 18)'),
139
- signWith: SignWithSchema
140
- }), async (args) => {
141
- try {
142
- const tokenAddress = requireAddress('token address', args.tokenAddress);
143
- const to = requireAddress('recipient address', args.to);
144
- const data = encodeFunctionData({
145
- abi: [parseAbiItem('function transfer(address to, uint256 amount)')],
146
- args: [to, parseUnits(args.amount, args.decimals ?? 18)]
147
- });
148
- const { txHash, preview, signedWith } = await requestSignature(args.chain, {
149
- to: tokenAddress,
150
- data,
151
- value: '0x0'
152
- }, args.signWith);
153
- return formatResponse({
154
- success: true,
155
- chain: args.chain,
156
- transactionHash: txHash,
157
- tokenAddress,
158
- to,
159
- amount: args.amount,
160
- signedWith,
161
- preview: previewSummary(preview),
162
- explorerUrl: explorerTxUrl(args.chain, txHash)
163
- });
164
- }
165
- catch (error) {
166
- return failure(error, 'Token transfer failed or was rejected');
167
- }
168
- }),
169
- write_contract: createTool('Write Contract', 'Send a transaction that calls a state-changing contract function. Simulates it first, then asks your wallet to approve. Costs gas.', z.object({
170
- chain: z.enum(SUPPORTED_CHAINS).describe('Blockchain network'),
171
- contractAddress: z.string().describe('Contract address'),
172
- functionAbi: z.string().describe('Function ABI definition (e.g., "function transfer(address to, uint256 amount)")'),
173
- args: z
174
- .array(z.union([z.string(), z.number(), z.boolean()]))
175
- .optional()
176
- .describe('Function arguments in order matching the ABI signature'),
177
- value: z.string().optional().describe('Optional native value to send with transaction (in ETH units, e.g., "0.1")'),
178
- signWith: SignWithSchema
179
- }), async (args) => {
180
- try {
181
- const contractAddress = requireAddress('contract address', args.contractAddress);
182
- const abiItem = parseAbiItem(args.functionAbi);
183
- const data = encodeFunctionData({
184
- abi: [abiItem],
185
- functionName: abiItem.name,
186
- args: (args.args || [])
187
- });
188
- const value = args.value ? `0x${parseUnits(args.value, 18).toString(16)}` : '0x0';
189
- const { txHash, preview, signedWith } = await requestSignature(args.chain, {
190
- to: contractAddress,
191
- data,
192
- value
193
- }, args.signWith);
194
- return formatResponse({
195
- success: true,
196
- chain: args.chain,
197
- transactionHash: txHash,
198
- contractAddress,
199
- functionName: abiItem.name,
200
- signedWith,
201
- preview: previewSummary(preview),
202
- explorerUrl: explorerTxUrl(args.chain, txHash)
203
- });
204
- }
205
- catch (error) {
206
- return failure(error, 'Contract call failed or was rejected');
207
- }
208
- }),
209
- sign_message: createTool('Sign Message', 'Sign a message with your wallet, on whichever signer you choose.', z.object({
210
- message: z.string().describe('Message to sign'),
211
- signWith: SignWithSchema
212
- }), async (args) => {
213
- try {
214
- let signature;
215
- if (args.signWith === 'phone') {
216
- const phone = getPhoneSigner();
217
- const session = await phone?.session();
218
- if (!session) {
219
- throw new Error('No phone wallet is paired. Run pair_phone_wallet and scan the QR, or sign in the browser instead.');
220
- }
221
- signature = await phone.request('mainnet', 'personal_sign', [toHex(args.message), session.accounts[0]]);
222
- }
223
- else {
224
- await getWalletClient().waitForSigner();
225
- signature = await getWalletClient().request({
226
- id: generateRequestId(),
227
- type: 'sign_message',
228
- chain: 'any',
229
- data: { message: args.message }
230
- });
231
- }
232
- return formatResponse({
233
- success: true,
234
- message: args.message,
235
- signature,
236
- signedWith: args.signWith,
237
- signatureType: 'personal_sign'
238
- });
239
- }
240
- catch (error) {
241
- return failure(error, 'Message signing failed or was rejected');
242
- }
243
- }),
244
- pair_phone_wallet: createTool('Pair Phone Wallet', 'Pair a phone wallet over WalletConnect, so transactions are signed on the phone instead of in a browser. ' +
245
- 'Returns a QR to scan plus links that open a wallet directly — show those to the user as clickable links. ' +
246
- 'Requires a WalletConnect project id.', z.object({
247
- chains: z
248
- .array(z.enum(SUPPORTED_CHAINS))
249
- .optional()
250
- .describe('Chains to request access to (defaults to every supported network)'),
251
- wallet: z.string().optional().describe('Name of the wallet to open, e.g. "rabby" — omit to list the common ones'),
252
- agent: z
253
- .string()
254
- .optional()
255
- .describe('Who is asking, shown in the wallet approval dialog, e.g. "Claude Code". Say who you actually are — ' +
256
- 'the user reads this when deciding whether to grant signing access.')
257
- }), async (args) => {
258
- const phone = getPhoneSigner();
259
- if (!phone) {
260
- return formatResponse({
261
- success: false,
262
- message: 'No WalletConnect project id configured. Get a free one at https://dashboard.walletconnect.com and pass --walletconnect-project-id or set WALLETCONNECT_PROJECT_ID.'
263
- });
264
- }
265
- try {
266
- // Before anything starts the client: its name is fixed the moment it does.
267
- phone.nameAgent(args.agent);
268
- const existing = await phone.session();
269
- if (existing) {
270
- return formatResponse({
271
- alreadyPaired: true,
272
- address: existing.accounts[0],
273
- wallet: existing.peer,
274
- message: 'A phone wallet is already paired. Transactions will be sent to it.'
275
- });
276
- }
277
- const chains = (args.chains ?? SUPPORTED_CHAINS.filter((c) => c !== 'localhost'));
278
- const uri = await phone.pair(chains);
279
- const projectId = getClientManager().getConfig().walletConnectProjectId;
280
- return formatResponse({
281
- qr: await qrFor(uri),
282
- uri,
283
- // For an agent running on the phone itself there is nothing to scan, so hand over
284
- // links that open the wallet directly. `wallet` narrows the list to one.
285
- openOnThisDevice: await pairingLinks(projectId, uri, args.wallet),
286
- // Approving grants an agent standing permission to request signatures, so the
287
- // wallet dialog names the agent rather than implying a website is connecting.
288
- shownInWallet: args.agent ? `${args.agent} via web3-tools-mcp` : 'web3-tools-mcp (AI agent)',
289
- howToPresent: 'Render each openOnThisDevice entry as a clickable link labelled with the wallet name, and show the ' +
290
- 'uri as copyable text. On a phone that tap is the whole flow. Show the QR only when the user is on a ' +
291
- 'different device from their wallet — it is unreadable inline on the phone that holds the wallet. ' +
292
- 'If a link does nothing, some clients drop custom schemes like rabby://, so tell them to paste the uri.',
293
- message: 'On another device: scan the QR with your wallet. On this device: tap one of the openOnThisDevice ' +
294
- 'links, or copy the uri and paste it into your wallet under WalletConnect — every wallet supports ' +
295
- 'that, and it is the one that always works. Then run wallet_status to confirm.'
296
- });
297
- }
298
- catch (error) {
299
- return failure(error, 'Could not start WalletConnect pairing');
300
- }
301
- }),
302
- disconnect_phone_wallet: createTool('Disconnect Phone Wallet', 'End every WalletConnect session and drop the pairings underneath them. Use before pairing a different wallet, or to clear out attempts that were never approved.', z.object({}), async () => {
303
- const phone = getPhoneSigner();
304
- if (!phone) {
305
- return formatResponse({ success: false, message: 'No WalletConnect project id configured — nothing to disconnect.' });
306
- }
307
- try {
308
- const before = await phone.sessions();
309
- const removed = await phone.disconnectAll();
310
- return formatResponse({
311
- success: true,
312
- disconnectedSessions: removed.sessions,
313
- droppedPairings: removed.pairings,
314
- wallets: before.map((session) => `${session.peer ?? 'unknown wallet'} (${session.accounts[0]})`),
315
- message: removed.sessions || removed.pairings
316
- ? 'Disconnected. Transactions fall back to the browser wallet until a phone is paired again.'
317
- : 'Nothing was connected.'
318
- });
319
- }
320
- catch (error) {
321
- return failure(error, 'Could not disconnect the phone wallet');
322
- }
323
- }),
324
- wallet_status: createTool('Wallet Status', 'Report every signer and whether it is ready, so a signing tool can be given the right signWith.', z.object({}), async () => {
325
- // Both signers are reported, never just the first one found: signWith makes this a
326
- // choice the user owns, so the agent has to see everything available.
327
- const phone = getPhoneSigner();
328
- const phoneSession = await phone?.session().catch(() => undefined);
329
- const wallet = getWalletClient();
330
- const relayError = await wallet
331
- .connect()
332
- .then(() => undefined)
333
- .catch((error) => describeError(error));
334
- const browserReady = !relayError && wallet.isConnected();
335
- // Only raise a tab when there is no other way to sign — a status check should not
336
- // open a window at someone who is about to use their phone.
337
- if (!browserReady && !phoneSession && !relayError)
338
- wallet.openBrowser();
339
- const signers = {
340
- phone: phoneSession
341
- ? { ready: true, address: phoneSession.accounts[0], wallet: phoneSession.peer, chains: phoneSession.chains }
342
- : {
343
- ready: false,
344
- reason: phone
345
- ? 'No phone paired. Run pair_phone_wallet and scan the QR.'
346
- : 'Phone signing is not configured — set WALLETCONNECT_PROJECT_ID.'
347
- },
348
- browser: browserReady
349
- ? { ready: true, address: wallet.getAddress(), openTab: wallet.getPageUrl() }
350
- : {
351
- ready: false,
352
- reason: relayError ?? 'No signing page is open.',
353
- walletUrl: relayError ? undefined : wallet.getUrl()
354
- }
355
- };
356
- const ready = [phoneSession ? 'phone' : undefined, browserReady ? 'browser' : undefined].filter(Boolean);
357
- const message = ready.length === 2
358
- ? 'Both signers are ready. Ask the user which one to use, then pass it as signWith.'
359
- : ready.length === 1
360
- ? `Only ${ready[0]} is ready. Confirm with the user before signing there, or set the other one up.`
361
- : `No signer is ready. For a browser, give the user this link and ask them to open it and connect a wallet: ${signers.browser.walletUrl ?? '(relay unavailable)'}. For a phone, run pair_phone_wallet.`;
362
- return formatResponse({ ready, signers, message });
363
- })
364
- };
365
- //# sourceMappingURL=transactions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"transactions.js","sourceRoot":"","sources":["../../src/tools/transactions.ts"],"names":[],"mappings":"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"}
package/src/tools/gas.ts DELETED
@@ -1,219 +0,0 @@
1
- import { type AbiFunction, type Address, decodeFunctionResult, encodeFunctionData, isAddress, parseAbiItem } from 'viem'
2
- import { z } from 'zod'
3
- import { getClientManager, SUPPORTED_CHAINS } from '../client.js'
4
- import type { ChainName } from '../types.js'
5
- import { convertArgumentsToTypes, createTool, formatResponse } from '../utils.js'
6
-
7
- export default {
8
- simulate_contract: createTool(
9
- 'Simulate Contract Call',
10
- 'Simulate a contract call (including state-changing functions) without broadcasting. Returns simulation result and estimated gas.',
11
- z.object({
12
- chain: z.enum(SUPPORTED_CHAINS).describe('Blockchain network to simulate on'),
13
- contractAddress: z.string().describe('Contract address to call'),
14
- functionAbi: z
15
- .string()
16
- .describe('Function ABI signature (e.g., "function transfer(address to, uint256 amount)"). Can be any function type.'),
17
- args: z
18
- .array(z.union([z.string(), z.number(), z.boolean(), z.null()]))
19
- .optional()
20
- .describe('Function arguments in order matching the ABI signature'),
21
- from: z.string().optional().describe('Sender address (defaults to zero address)'),
22
- value: z.string().optional().describe('ETH value to send with the transaction (in wei as string)'),
23
- blockNumber: z.string().optional().describe('Block number for simulation (defaults to latest)')
24
- }),
25
- async (args) => {
26
- if (!isAddress(args.contractAddress)) {
27
- throw new Error(`Invalid contract address: ${args.contractAddress}`)
28
- }
29
-
30
- if (args.from && !isAddress(args.from)) {
31
- throw new Error(`Invalid from address: ${args.from}`)
32
- }
33
-
34
- const clientManager = getClientManager()
35
- const client = clientManager.getClient(args.chain as ChainName)
36
-
37
- try {
38
- const abiItem = parseAbiItem(args.functionAbi) as AbiFunction
39
- const convertedArgs = convertArgumentsToTypes(args.args || [], abiItem.inputs)
40
-
41
- const blockTag = args.blockNumber ? BigInt(args.blockNumber) : undefined
42
-
43
- // Simulate the call
44
- const result = await client.call({
45
- to: args.contractAddress as Address,
46
- data: encodeFunctionData({
47
- abi: [abiItem],
48
- functionName: abiItem.name,
49
- args: convertedArgs
50
- }),
51
- account: args.from ? (args.from as Address) : undefined,
52
- value: args.value ? BigInt(args.value) : undefined,
53
- blockNumber: blockTag
54
- })
55
-
56
- // Also estimate gas
57
- const gasEstimate = await client.estimateGas({
58
- to: args.contractAddress as Address,
59
- data: encodeFunctionData({
60
- abi: [abiItem],
61
- functionName: abiItem.name,
62
- args: convertedArgs
63
- }),
64
- account: args.from ? (args.from as Address) : undefined,
65
- value: args.value ? BigInt(args.value) : undefined,
66
- blockNumber: blockTag
67
- })
68
-
69
- // Decode the result if the function has outputs
70
- let decodedResult: unknown = result.data
71
- if (abiItem.outputs && abiItem.outputs.length > 0 && result.data) {
72
- decodedResult = decodeFunctionResult({
73
- abi: [abiItem],
74
- functionName: abiItem.name,
75
- data: result.data
76
- })
77
- }
78
-
79
- return formatResponse({
80
- success: true,
81
- chain: args.chain,
82
- contractAddress: args.contractAddress,
83
- functionName: abiItem.name,
84
- result: decodedResult,
85
- rawData: result.data,
86
- gasEstimate: gasEstimate.toString(),
87
- blockNumber: args.blockNumber || 'latest'
88
- })
89
- } catch (error) {
90
- // Check if it's a revert error
91
- const errorMessage = error instanceof Error ? error.message : String(error)
92
-
93
- return formatResponse({
94
- success: false,
95
- chain: args.chain,
96
- contractAddress: args.contractAddress,
97
- error: errorMessage,
98
- reverted: errorMessage.includes('revert') || errorMessage.includes('execution reverted')
99
- })
100
- }
101
- }
102
- ),
103
-
104
- estimate_gas: createTool(
105
- 'Estimate Gas',
106
- 'Estimate gas required for a transaction. Supports contract calls, transfers, and deployments.',
107
- z.object({
108
- chain: z.enum(SUPPORTED_CHAINS).describe('Blockchain network'),
109
- to: z.string().optional().describe('Recipient address (omit for contract deployment)'),
110
- from: z.string().optional().describe('Sender address (optional)'),
111
- value: z.string().optional().describe('ETH value to send (in wei as string)'),
112
- data: z.string().optional().describe('Transaction data (hex string for contract calls or deployment bytecode)'),
113
- functionAbi: z.string().optional().describe('Optional: Function ABI signature to encode call data automatically'),
114
- args: z
115
- .array(z.union([z.string(), z.number(), z.boolean(), z.null()]))
116
- .optional()
117
- .describe('Optional: Function arguments (only used with functionAbi)')
118
- }),
119
- async (args) => {
120
- if (args.to && !isAddress(args.to)) {
121
- throw new Error(`Invalid to address: ${args.to}`)
122
- }
123
-
124
- if (args.from && !isAddress(args.from)) {
125
- throw new Error(`Invalid from address: ${args.from}`)
126
- }
127
-
128
- const clientManager = getClientManager()
129
- const client = clientManager.getClient(args.chain as ChainName)
130
-
131
- let callData = args.data
132
-
133
- // If functionAbi is provided, encode the call data
134
- if (args.functionAbi) {
135
- const abiItem = parseAbiItem(args.functionAbi) as AbiFunction
136
- const convertedArgs = convertArgumentsToTypes(args.args || [], abiItem.inputs)
137
- callData = encodeFunctionData({
138
- abi: [abiItem],
139
- functionName: abiItem.name,
140
- args: convertedArgs
141
- })
142
- }
143
-
144
- const gasEstimate = await client.estimateGas({
145
- to: args.to ? (args.to as Address) : undefined,
146
- account: args.from ? (args.from as Address) : undefined,
147
- value: args.value ? BigInt(args.value) : undefined,
148
- data: callData as `0x${string}` | undefined
149
- })
150
-
151
- return formatResponse({
152
- success: true,
153
- chain: args.chain,
154
- gasEstimate: gasEstimate.toString(),
155
- to: args.to,
156
- from: args.from,
157
- value: args.value
158
- })
159
- }
160
- ),
161
-
162
- get_gas_price: createTool(
163
- 'Get Gas Price',
164
- 'Get current gas prices for a chain. Returns both legacy gasPrice and EIP-1559 fees (maxFeePerGas, maxPriorityFeePerGas).',
165
- z.object({
166
- chain: z.enum(SUPPORTED_CHAINS).describe('Blockchain network'),
167
- formatted: z.boolean().optional().default(true).describe('Return prices in Gwei (default: true). If false, returns wei.')
168
- }),
169
- async (args) => {
170
- const clientManager = getClientManager()
171
- const client = clientManager.getClient(args.chain as ChainName)
172
-
173
- // Get both legacy and EIP-1559 gas prices
174
- const [gasPrice, feeData] = await Promise.all([
175
- client.getGasPrice(),
176
- client.estimateFeesPerGas().catch(() => null) // Some chains don't support EIP-1559
177
- ])
178
-
179
- const formatPrice = (wei: bigint): string => {
180
- if (args.formatted) {
181
- // Convert to Gwei (1 Gwei = 1e9 wei)
182
- const gwei = Number(wei) / 1e9
183
- return `${gwei.toFixed(2)} Gwei`
184
- }
185
- return wei.toString()
186
- }
187
-
188
- const response: any = {
189
- chain: args.chain,
190
- timestamp: new Date().toISOString(),
191
- legacy: {
192
- gasPrice: args.formatted ? formatPrice(gasPrice) : gasPrice.toString(),
193
- gasPriceWei: gasPrice.toString()
194
- }
195
- }
196
-
197
- // Add EIP-1559 data if available
198
- if (feeData) {
199
- response.eip1559 = {
200
- maxFeePerGas: args.formatted ? formatPrice(feeData.maxFeePerGas) : feeData.maxFeePerGas.toString(),
201
- maxPriorityFeePerGas: args.formatted
202
- ? formatPrice(feeData.maxPriorityFeePerGas)
203
- : feeData.maxPriorityFeePerGas.toString(),
204
- maxFeePerGasWei: feeData.maxFeePerGas.toString(),
205
- maxPriorityFeePerGasWei: feeData.maxPriorityFeePerGas.toString()
206
- }
207
-
208
- // Calculate estimated total cost for a standard 21000 gas transaction
209
- const standardGasLimit = 21000n
210
- const estimatedCost = feeData.maxFeePerGas * standardGasLimit
211
- response.eip1559.estimatedCostFor21kGas = args.formatted
212
- ? `${(Number(estimatedCost) / 1e18).toFixed(6)} ETH`
213
- : estimatedCost.toString()
214
- }
215
-
216
- return formatResponse(response)
217
- }
218
- )
219
- }