diff --git a/README.md b/README.md index c816df1..646124c 100644 --- a/README.md +++ b/README.md @@ -389,6 +389,40 @@ Example query to Claude: > "Buy $20 worth of OpenRouter credits." +### Advanced Contract Tools + +The Base MCP server now includes advanced contract interaction capabilities: + +#### execute-batch-transactions +Execute multiple transactions in a batch with optimized gas usage. + +Example query to Claude: +> "Execute these transactions in a batch: transfer 0.1 ETH to 0x123... and 0.2 ETH to 0x456..." + +#### subscribe-contract-events +Subscribe to contract events with filtering capabilities. + +Example query to Claude: +> "Subscribe to Transfer events from contract 0x789..." + +#### execute-contract-call +Execute a contract call with advanced options and gas optimization. + +Example query to Claude: +> "Call the mint function on contract 0xabc... with parameters [1, 2, 3]" + +#### optimize-gas +Optimize gas usage based on different strategies (fast, medium, slow). + +Example query to Claude: +> "What's the optimal gas price for a fast transaction?" + +#### validate-abi +Validate contract ABI with comprehensive checks. + +Example query to Claude: +> "Validate this contract ABI for any issues" + ## Security Considerations - The configuration file contains sensitive information (API keys and seed phrases). Ensure it's properly secured and not shared. diff --git a/examples.md b/examples.md index 075dfb2..8a05848 100644 --- a/examples.md +++ b/examples.md @@ -231,3 +231,92 @@ _Claude uses the `buy_openrouter_credits` tool with the following parameters:_ 6. **Verify contract interactions** - When interacting with smart contracts, verify the contract address and function parameters before confirming transactions. 7. **Use onramp responsibly** - When onramping funds, be aware of any fees or limits that may apply. + +## Advanced Contract Tools Examples + +### Batch Transactions + +Execute multiple transactions in a single batch to save gas and ensure atomicity: + +```typescript +// Example batch transaction +const batchTx = { + transactions: [ + { + to: "0x1234567890123456789012345678901234567890", + data: "0x...", + value: "0.1" + }, + { + to: "0x0987654321098765432109876543210987654321", + data: "0x...", + value: "0.2" + } + ], + gasLimit: "300000", + maxFeePerGas: "50", + maxPriorityFeePerGas: "2" +}; +``` + +### Contract Event Subscription + +Subscribe to specific contract events with filtering: + +```typescript +// Example event subscription +const subscription = { + contractAddress: "0x1234567890123456789012345678901234567890", + eventName: "Transfer", + fromBlock: 1000000, + toBlock: 2000000, + filter: { + from: "0x123...", + to: "0x456..." + } +}; +``` + +### Advanced Contract Calls + +Execute contract calls with optimized gas and advanced options: + +```typescript +// Example contract call +const contractCall = { + contractAddress: "0x1234567890123456789012345678901234567890", + abi: [...], + functionName: "mint", + args: [1, 2, 3], + value: "0.1", + gasLimit: "200000" +}; +``` + +### Gas Optimization + +Optimize gas usage based on different strategies: + +```typescript +// Example gas optimization +const gasOptimization = { + strategy: "fast", // or "medium" or "slow" + maxGasPrice: "100", // in gwei + priorityFee: "2" // in gwei +}; +``` + +### ABI Validation + +Validate contract ABIs for potential issues: + +```typescript +// Example ABI validation +const abiValidation = { + abi: [...], + bytecode: "0x...", + validateConstructor: true, + validateFunctions: true, + validateEvents: true +}; +``` diff --git a/package.json b/package.json index cb3df63..cbb8a1f 100644 --- a/package.json +++ b/package.json @@ -2,9 +2,7 @@ "name": "base-mcp", "version": "1.0.11", "description": "A Model Context Protocol (MCP) server that provides onchain tools for Claude AI, allowing it to interact with the Base blockchain and Coinbase API", - "bin": { - "base-mcp": "build/index.js" - }, + "bin": "build/index.js", "type": "module", "scripts": { "run": "tsx src/index.ts", @@ -47,11 +45,14 @@ "@coinbase/agentkit-model-context-protocol": "^0.2.0", "@coinbase/coinbase-sdk": "^0.21.0", "@coinbase/onchainkit": "^0.37.6", + "@ethersproject/contracts": "^5.7.0", + "@ethersproject/providers": "^5.7.2", "@inquirer/prompts": "^7.4.0", "@modelcontextprotocol/sdk": "^1.6.1", "@privy-io/public-api": "^2.20.5", "chalk": "^5.4.1", "dotenv": "^16.4.7", + "ethers": "^5.7.2", "graphql": "^16.10.0", "graphql-request": "^7.1.2", "reflect-metadata": "^0.2.2", diff --git a/src/tools/advanced-contracts/handlers.ts b/src/tools/advanced-contracts/handlers.ts new file mode 100644 index 0000000..baa6a29 --- /dev/null +++ b/src/tools/advanced-contracts/handlers.ts @@ -0,0 +1,178 @@ +import { ethers } from 'ethers'; +import { BaseProvider } from '@ethersproject/providers'; +import { Contract } from '@ethersproject/contracts'; +import { + BatchTransactionSchema, + ContractEventSubscriptionSchema, + ContractCallSchema, + GasOptimizationSchema, + ABIValidationSchema +} from './schemas.js'; + +export class AdvancedContractHandler { + private provider: BaseProvider; + private wallet: ethers.Wallet; + + constructor(provider: BaseProvider, wallet: ethers.Wallet) { + this.provider = provider; + this.wallet = wallet; + } + + async executeBatchTransactions(params: typeof BatchTransactionSchema._type) { + const { transactions, gasLimit, maxFeePerGas, maxPriorityFeePerGas } = params; + + // Prepare batch transaction + const batchTx = await Promise.all( + transactions.map(async (tx) => { + const nonce = await this.wallet.getTransactionCount(); + return { + ...tx, + nonce, + gasLimit: gasLimit || await this.estimateGas(tx), + maxFeePerGas, + maxPriorityFeePerGas, + }; + }) + ); + + // Execute batch transaction + const batchReceipt = await this.wallet.sendTransaction(batchTx[0]); + return batchReceipt; + } + + async subscribeToContractEvents(params: typeof ContractEventSubscriptionSchema._type) { + const { contractAddress, eventName } = params; + + const contract = new Contract( + contractAddress, + ['event ' + eventName], + this.provider + ); + + return new Promise((resolve, reject) => { + contract.on(eventName, (...args: unknown[]) => { + resolve({ event: eventName, args }); + }); + + // Set up error handling + contract.on('error', (error: Error) => { + reject(error); + }); + }); + } + + async executeContractCall(params: typeof ContractCallSchema._type) { + const { contractAddress, abi, functionName, args, value, gasLimit } = params; + + const contract = new Contract(contractAddress, abi, this.wallet); + + // Prepare transaction options + const txOptions: Record = {}; + if (value) txOptions.value = ethers.utils.parseEther(value); + if (gasLimit) txOptions.gasLimit = ethers.BigNumber.from(gasLimit); + + // Execute contract call + const tx = await contract[functionName](...(args || []), txOptions); + const receipt = await tx.wait(); + + return { + transactionHash: receipt.transactionHash, + blockNumber: receipt.blockNumber, + gasUsed: receipt.gasUsed.toString(), + }; + } + + async optimizeGas(params: typeof GasOptimizationSchema._type) { + const { strategy, maxGasPrice } = params; + + const feeData = await this.provider.getFeeData(); + + let gasPrice: ethers.BigNumber; + switch (strategy) { + case 'fast': + gasPrice = feeData.maxFeePerGas || feeData.gasPrice || ethers.BigNumber.from(0); + break; + case 'medium': + gasPrice = feeData.maxPriorityFeePerGas || feeData.gasPrice || ethers.BigNumber.from(0); + break; + case 'slow': + gasPrice = feeData.gasPrice || ethers.BigNumber.from(0); + break; + } + + if (maxGasPrice) { + const maxGas = ethers.utils.parseUnits(maxGasPrice, 'gwei'); + if (gasPrice.gt(maxGas)) { + gasPrice = maxGas; + } + } + + return { + gasPrice: gasPrice.toString(), + strategy, + }; + } + + async validateABI(params: typeof ABIValidationSchema._type) { + const { abi, bytecode, validateConstructor, validateFunctions, validateEvents } = params; + + const validationResults = { + isValid: true, + errors: [] as string[], + warnings: [] as string[], + }; + + try { + // Validate ABI structure + if (!Array.isArray(abi)) { + validationResults.isValid = false; + validationResults.errors.push('ABI must be an array'); + return validationResults; + } + + // Validate constructor if bytecode is provided + if (validateConstructor && bytecode) { + const constructorAbi = abi.find(item => item.type === 'constructor'); + if (!constructorAbi) { + validationResults.warnings.push('No constructor found in ABI'); + } + } + + // Validate functions + if (validateFunctions) { + const functions = abi.filter(item => item.type === 'function'); + for (const func of functions) { + if (!func.name || !func.inputs || !func.outputs) { + validationResults.errors.push(`Invalid function definition: ${func.name || 'unnamed'}`); + } + } + } + + // Validate events + if (validateEvents) { + const events = abi.filter(item => item.type === 'event'); + for (const event of events) { + if (!event.name || !event.inputs) { + validationResults.errors.push(`Invalid event definition: ${event.name || 'unnamed'}`); + } + } + } + + validationResults.isValid = validationResults.errors.length === 0; + return validationResults; + } catch (error: unknown) { + validationResults.isValid = false; + validationResults.errors.push(`Validation error: ${error instanceof Error ? error.message : String(error)}`); + return validationResults; + } + } + + private async estimateGas(tx: Record): Promise { + try { + const gasEstimate = await this.provider.estimateGas(tx); + return gasEstimate.toString(); + } catch (error: unknown) { + throw new Error(`Gas estimation failed: ${error instanceof Error ? error.message : String(error)}`); + } + } +} \ No newline at end of file diff --git a/src/tools/advanced-contracts/index.ts b/src/tools/advanced-contracts/index.ts new file mode 100644 index 0000000..e63b5dc --- /dev/null +++ b/src/tools/advanced-contracts/index.ts @@ -0,0 +1,57 @@ +import { Tool } from '../types'; +import { AdvancedContractHandler } from './handlers'; +import { + BatchTransactionSchema, + ContractEventSubscriptionSchema, + ContractCallSchema, + GasOptimizationSchema, + ABIValidationSchema +} from './schemas'; + +export const advancedContractTools: Tool[] = [ + { + name: 'execute-batch-transactions', + description: 'Execute multiple transactions in a batch with optimized gas usage', + parameters: BatchTransactionSchema, + handler: async (params, context) => { + const handler = new AdvancedContractHandler(context.provider, context.wallet); + return await handler.executeBatchTransactions(params); + } + }, + { + name: 'subscribe-contract-events', + description: 'Subscribe to contract events with filtering capabilities', + parameters: ContractEventSubscriptionSchema, + handler: async (params, context) => { + const handler = new AdvancedContractHandler(context.provider, context.wallet); + return await handler.subscribeToContractEvents(params); + } + }, + { + name: 'execute-contract-call', + description: 'Execute a contract call with advanced options and gas optimization', + parameters: ContractCallSchema, + handler: async (params, context) => { + const handler = new AdvancedContractHandler(context.provider, context.wallet); + return await handler.executeContractCall(params); + } + }, + { + name: 'optimize-gas', + description: 'Optimize gas usage based on different strategies', + parameters: GasOptimizationSchema, + handler: async (params, context) => { + const handler = new AdvancedContractHandler(context.provider, context.wallet); + return await handler.optimizeGas(params); + } + }, + { + name: 'validate-abi', + description: 'Validate contract ABI with comprehensive checks', + parameters: ABIValidationSchema, + handler: async (params, context) => { + const handler = new AdvancedContractHandler(context.provider, context.wallet); + return await handler.validateABI(params); + } + } +]; \ No newline at end of file diff --git a/src/tools/advanced-contracts/schemas.ts b/src/tools/advanced-contracts/schemas.ts new file mode 100644 index 0000000..033edbc --- /dev/null +++ b/src/tools/advanced-contracts/schemas.ts @@ -0,0 +1,43 @@ +import { z } from 'zod'; + +export const BatchTransactionSchema = z.object({ + transactions: z.array(z.object({ + to: z.string(), + data: z.string(), + value: z.string().optional(), + })), + gasLimit: z.string().optional(), + maxFeePerGas: z.string().optional(), + maxPriorityFeePerGas: z.string().optional(), +}); + +export const ContractEventSubscriptionSchema = z.object({ + contractAddress: z.string(), + eventName: z.string(), + fromBlock: z.number().optional(), + toBlock: z.number().optional(), + filter: z.record(z.any()).optional(), +}); + +export const ContractCallSchema = z.object({ + contractAddress: z.string(), + abi: z.any(), + functionName: z.string(), + args: z.array(z.any()).optional(), + value: z.string().optional(), + gasLimit: z.string().optional(), +}); + +export const GasOptimizationSchema = z.object({ + strategy: z.enum(['fast', 'medium', 'slow']), + maxGasPrice: z.string().optional(), + priorityFee: z.string().optional(), +}); + +export const ABIValidationSchema = z.object({ + abi: z.any(), + bytecode: z.string().optional(), + validateConstructor: z.boolean().optional(), + validateFunctions: z.boolean().optional(), + validateEvents: z.boolean().optional(), +}); \ No newline at end of file diff --git a/src/tools/index.ts b/src/tools/index.ts index 51bc97e..ad8d784 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -4,6 +4,7 @@ import { getMorphoVaultsTool } from './morpho/index.js'; import { listNftsTool, transferNftTool } from './nft/index.js'; import { getOnrampAssetsTool, onrampTool } from './onramp/index.js'; import { buyOpenRouterCreditsTool } from './open-router/index.js'; +import { advancedContractTools } from './advanced-contracts/index.js'; import type { ToolHandler, ToolWithHandler } from './types.js'; export const baseMcpTools: ToolWithHandler[] = [ @@ -16,6 +17,10 @@ export const baseMcpTools: ToolWithHandler[] = [ listNftsTool, transferNftTool, buyOpenRouterCreditsTool, + ...advancedContractTools.map(tool => ({ + definition: tool, + handler: tool.handler + })) ]; export const toolToHandler: Record = baseMcpTools.reduce< diff --git a/yarn.lock b/yarn.lock index e8b2848..f6e49fa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -818,6 +818,408 @@ __metadata: languageName: node linkType: hard +"@ethersproject/abi@npm:5.8.0, @ethersproject/abi@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/abi@npm:5.8.0" + dependencies: + "@ethersproject/address": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/constants": "npm:^5.8.0" + "@ethersproject/hash": "npm:^5.8.0" + "@ethersproject/keccak256": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/strings": "npm:^5.8.0" + checksum: 10c0/6b759247a2f43ecc1548647d0447d08de1e946dfc7e71bfb014fa2f749c1b76b742a1d37394660ebab02ff8565674b3593fdfa011e16a5adcfc87ca4d85af39c + languageName: node + linkType: hard + +"@ethersproject/abstract-provider@npm:5.8.0, @ethersproject/abstract-provider@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/abstract-provider@npm:5.8.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/networks": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/transactions": "npm:^5.8.0" + "@ethersproject/web": "npm:^5.8.0" + checksum: 10c0/9c183da1d037b272ff2b03002c3d801088d0534f88985f4983efc5f3ebd59b05f04bc05db97792fe29ddf87eeba3c73416e5699615f183126f85f877ea6c8637 + languageName: node + linkType: hard + +"@ethersproject/abstract-signer@npm:5.8.0, @ethersproject/abstract-signer@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/abstract-signer@npm:5.8.0" + dependencies: + "@ethersproject/abstract-provider": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + checksum: 10c0/143f32d7cb0bc7064e45674d4a9dffdb90d6171425d20e8de9dc95765be960534bae7246ead400e6f52346624b66569d9585d790eedd34b0b6b7f481ec331cc2 + languageName: node + linkType: hard + +"@ethersproject/address@npm:5.8.0, @ethersproject/address@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/address@npm:5.8.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/keccak256": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/rlp": "npm:^5.8.0" + checksum: 10c0/8bac8a4b567c75c1abc00eeca08c200de1a2d5cf76d595dc04fa4d7bff9ffa5530b2cdfc5e8656cfa8f6fa046de54be47620a092fb429830a8ddde410b9d50bc + languageName: node + linkType: hard + +"@ethersproject/base64@npm:5.8.0, @ethersproject/base64@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/base64@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + checksum: 10c0/60ae6d1e2367d70f4090b717852efe62075442ae59aeac9bb1054fe8306a2de8ef0b0561e7fb4666ecb1f8efa1655d683dd240675c3a25d6fa867245525a63ca + languageName: node + linkType: hard + +"@ethersproject/basex@npm:5.8.0, @ethersproject/basex@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/basex@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + checksum: 10c0/46a94ba9678fc458ab0bee4a0af9f659f1d3f5df5bb98485924fe8ecbd46eda37d81f95f882243d56f0f5efe051b0749163f5056e48ff836c5fba648754d4956 + languageName: node + linkType: hard + +"@ethersproject/bignumber@npm:5.8.0, @ethersproject/bignumber@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/bignumber@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + bn.js: "npm:^5.2.1" + checksum: 10c0/8e87fa96999d59d0ab4c814c79e3a8354d2ba914dfa78cf9ee688f53110473cec0df0db2aaf9d447e84ab2dbbfca39979abac4f2dac69fef4d080f4cc3e29613 + languageName: node + linkType: hard + +"@ethersproject/bytes@npm:5.8.0, @ethersproject/bytes@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/bytes@npm:5.8.0" + dependencies: + "@ethersproject/logger": "npm:^5.8.0" + checksum: 10c0/47ef798f3ab43b95dc74097b2c92365c919308ecabc3e34d9f8bf7f886fa4b99837ba5cf4dc8921baaaafe6899982f96b0e723b3fc49132c061f83d1ca3fed8b + languageName: node + linkType: hard + +"@ethersproject/constants@npm:5.8.0, @ethersproject/constants@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/constants@npm:5.8.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.8.0" + checksum: 10c0/374b3c2c6da24f8fef62e2316eae96faa462826c0774ef588cd7313ae7ddac8eb1bb85a28dad80123148be2ba0821c217c14ecfc18e2e683c72adc734b6248c9 + languageName: node + linkType: hard + +"@ethersproject/contracts@npm:5.8.0, @ethersproject/contracts@npm:^5.7.0": + version: 5.8.0 + resolution: "@ethersproject/contracts@npm:5.8.0" + dependencies: + "@ethersproject/abi": "npm:^5.8.0" + "@ethersproject/abstract-provider": "npm:^5.8.0" + "@ethersproject/abstract-signer": "npm:^5.8.0" + "@ethersproject/address": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/constants": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/transactions": "npm:^5.8.0" + checksum: 10c0/49961b92334c4f2fab5f4da8f3119e97c1dc39cc8695e3043931757968213f5e732c00bf896193cf0186dcb33101dcd6efb70690dee0dd2cfbfd3843f55485aa + languageName: node + linkType: hard + +"@ethersproject/hash@npm:5.8.0, @ethersproject/hash@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/hash@npm:5.8.0" + dependencies: + "@ethersproject/abstract-signer": "npm:^5.8.0" + "@ethersproject/address": "npm:^5.8.0" + "@ethersproject/base64": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/keccak256": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/strings": "npm:^5.8.0" + checksum: 10c0/72a287d4d70fae716827587339ffb449b8c23ef8728db6f8a661f359f7cb1e5ffba5b693c55e09d4e7162bf56af4a0e98a334784e0706d98102d1a5786241537 + languageName: node + linkType: hard + +"@ethersproject/hdnode@npm:5.8.0, @ethersproject/hdnode@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/hdnode@npm:5.8.0" + dependencies: + "@ethersproject/abstract-signer": "npm:^5.8.0" + "@ethersproject/basex": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/pbkdf2": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/sha2": "npm:^5.8.0" + "@ethersproject/signing-key": "npm:^5.8.0" + "@ethersproject/strings": "npm:^5.8.0" + "@ethersproject/transactions": "npm:^5.8.0" + "@ethersproject/wordlists": "npm:^5.8.0" + checksum: 10c0/da0ac7d60e76a76471be1f4f3bba3f28a24165dc3b63c6930a9ec24481e9f8b23936e5fc96363b3591cdfda4381d4623f25b06898b89bf5530b158cb5ea58fdd + languageName: node + linkType: hard + +"@ethersproject/json-wallets@npm:5.8.0, @ethersproject/json-wallets@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/json-wallets@npm:5.8.0" + dependencies: + "@ethersproject/abstract-signer": "npm:^5.8.0" + "@ethersproject/address": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/hdnode": "npm:^5.8.0" + "@ethersproject/keccak256": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/pbkdf2": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/random": "npm:^5.8.0" + "@ethersproject/strings": "npm:^5.8.0" + "@ethersproject/transactions": "npm:^5.8.0" + aes-js: "npm:3.0.0" + scrypt-js: "npm:3.0.1" + checksum: 10c0/6c5cac87bdfac9ac47bf6ac25168a85865dc02e398e97f83820568c568a8cb27cf13a3a5d482f71a2534c7d704a3faa46023bb7ebe8737872b376bec1b66c67b + languageName: node + linkType: hard + +"@ethersproject/keccak256@npm:5.8.0, @ethersproject/keccak256@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/keccak256@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + js-sha3: "npm:0.8.0" + checksum: 10c0/cd93ac6a5baf842313cde7de5e6e2c41feeea800db9e82955f96e7f3462d2ac6a6a29282b1c9e93b84ce7c91eec02347043c249fd037d6051214275bfc7fe99f + languageName: node + linkType: hard + +"@ethersproject/logger@npm:5.8.0, @ethersproject/logger@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/logger@npm:5.8.0" + checksum: 10c0/7f39f33e8f254ee681d4778bb71ce3c5de248e1547666f85c43bfbc1c18996c49a31f969f056b66d23012f2420f2d39173107284bc41eb98d0482ace1d06403e + languageName: node + linkType: hard + +"@ethersproject/networks@npm:5.8.0, @ethersproject/networks@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/networks@npm:5.8.0" + dependencies: + "@ethersproject/logger": "npm:^5.8.0" + checksum: 10c0/3f23bcc4c3843cc9b7e4b9f34df0a1f230b24dc87d51cdad84552302159a84d7899cd80c8a3d2cf8007b09ac373a5b10407007adde23d4c4881a4d6ee6bc4b9c + languageName: node + linkType: hard + +"@ethersproject/pbkdf2@npm:5.8.0, @ethersproject/pbkdf2@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/pbkdf2@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/sha2": "npm:^5.8.0" + checksum: 10c0/0397cf5370cfd568743c3e46ac431f1bd425239baa2691689f1430997d44d310cef5051ea9ee53fabe444f96aced8d6324b41da698e8d7021389dce36251e7e9 + languageName: node + linkType: hard + +"@ethersproject/properties@npm:5.8.0, @ethersproject/properties@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/properties@npm:5.8.0" + dependencies: + "@ethersproject/logger": "npm:^5.8.0" + checksum: 10c0/20256d7eed65478a38dabdea4c3980c6591b7b75f8c45089722b032ceb0e1cd3dd6dd60c436cfe259337e6909c28d99528c172d06fc74bbd61be8eb9e68be2e6 + languageName: node + linkType: hard + +"@ethersproject/providers@npm:5.8.0, @ethersproject/providers@npm:^5.7.2": + version: 5.8.0 + resolution: "@ethersproject/providers@npm:5.8.0" + dependencies: + "@ethersproject/abstract-provider": "npm:^5.8.0" + "@ethersproject/abstract-signer": "npm:^5.8.0" + "@ethersproject/address": "npm:^5.8.0" + "@ethersproject/base64": "npm:^5.8.0" + "@ethersproject/basex": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/constants": "npm:^5.8.0" + "@ethersproject/hash": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/networks": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/random": "npm:^5.8.0" + "@ethersproject/rlp": "npm:^5.8.0" + "@ethersproject/sha2": "npm:^5.8.0" + "@ethersproject/strings": "npm:^5.8.0" + "@ethersproject/transactions": "npm:^5.8.0" + "@ethersproject/web": "npm:^5.8.0" + bech32: "npm:1.1.4" + ws: "npm:8.18.0" + checksum: 10c0/893dba429443bbf0a3eadef850e772ad1c706cf17ae6ae48b73467a23b614a3f461e9004850e24439b5c73d30e9259bc983f0f90a911ba11af749e6384fd355a + languageName: node + linkType: hard + +"@ethersproject/random@npm:5.8.0, @ethersproject/random@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/random@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + checksum: 10c0/e44c010715668fc29383141ae16cd2ec00c34a434d47e23338e740b8c97372515d95d3b809b969eab2055c19e92b985ca591d326fbb71270c26333215f9925d1 + languageName: node + linkType: hard + +"@ethersproject/rlp@npm:5.8.0, @ethersproject/rlp@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/rlp@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + checksum: 10c0/db742ec9c1566d6441242cc2c2ae34c1e5304d48e1fe62bc4e53b1791f219df211e330d2de331e0e4f74482664e205c2e4220e76138bd71f1ec07884e7f5221b + languageName: node + linkType: hard + +"@ethersproject/sha2@npm:5.8.0, @ethersproject/sha2@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/sha2@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + hash.js: "npm:1.1.7" + checksum: 10c0/eab941907b7d40ee8436acaaedee32306ed4de2cb9ab37543bc89b1dd2a78f28c8da21efd848525fa1b04a78575be426cfca28f5392f4d28ce6c84e7c26a9421 + languageName: node + linkType: hard + +"@ethersproject/signing-key@npm:5.8.0, @ethersproject/signing-key@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/signing-key@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + bn.js: "npm:^5.2.1" + elliptic: "npm:6.6.1" + hash.js: "npm:1.1.7" + checksum: 10c0/a7ff6cd344b0609737a496b6d5b902cf5528ed5a7ce2c0db5e7b69dc491d1810d1d0cd51dddf9dc74dd562ab4961d76e982f1750359b834c53c202e85e4c8502 + languageName: node + linkType: hard + +"@ethersproject/solidity@npm:5.8.0": + version: 5.8.0 + resolution: "@ethersproject/solidity@npm:5.8.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/keccak256": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/sha2": "npm:^5.8.0" + "@ethersproject/strings": "npm:^5.8.0" + checksum: 10c0/5b5e0531bcec1d919cfbd261694694c8999ca5c379c1bb276ec779b896d299bb5db8ed7aa5652eb2c7605fe66455832b56ef123dec07f6ddef44231a7aa6fe6c + languageName: node + linkType: hard + +"@ethersproject/strings@npm:5.8.0, @ethersproject/strings@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/strings@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/constants": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + checksum: 10c0/6db39503c4be130110612b6d593a381c62657e41eebf4f553247ebe394fda32cdf74ff645daee7b7860d209fd02c7e909a95b1f39a2f001c662669b9dfe81d00 + languageName: node + linkType: hard + +"@ethersproject/transactions@npm:5.8.0, @ethersproject/transactions@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/transactions@npm:5.8.0" + dependencies: + "@ethersproject/address": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/constants": "npm:^5.8.0" + "@ethersproject/keccak256": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/rlp": "npm:^5.8.0" + "@ethersproject/signing-key": "npm:^5.8.0" + checksum: 10c0/dd32f090df5945313aafa8430ce76834479750d6655cb786c3b65ec841c94596b14d3c8c59ee93eed7b4f32f27d321a9b8b43bc6bb51f7e1c6694f82639ffe68 + languageName: node + linkType: hard + +"@ethersproject/units@npm:5.8.0": + version: 5.8.0 + resolution: "@ethersproject/units@npm:5.8.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/constants": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + checksum: 10c0/5f92b8379a58024078fce6a4cbf7323cfd79bc41ef8f0a7bbf8be9c816ce18783140ab0d5c8d34ed615639aef7fc3a2ed255e92809e3558a510c4f0d49e27309 + languageName: node + linkType: hard + +"@ethersproject/wallet@npm:5.8.0": + version: 5.8.0 + resolution: "@ethersproject/wallet@npm:5.8.0" + dependencies: + "@ethersproject/abstract-provider": "npm:^5.8.0" + "@ethersproject/abstract-signer": "npm:^5.8.0" + "@ethersproject/address": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/hash": "npm:^5.8.0" + "@ethersproject/hdnode": "npm:^5.8.0" + "@ethersproject/json-wallets": "npm:^5.8.0" + "@ethersproject/keccak256": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/random": "npm:^5.8.0" + "@ethersproject/signing-key": "npm:^5.8.0" + "@ethersproject/transactions": "npm:^5.8.0" + "@ethersproject/wordlists": "npm:^5.8.0" + checksum: 10c0/6da450872dda3d9008bad3ccf8467816a63429241e51c66627647123c0fe5625494c4f6c306e098eb8419cc5702ac017d41f5161af5ff670a41fe5d199883c09 + languageName: node + linkType: hard + +"@ethersproject/web@npm:5.8.0, @ethersproject/web@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/web@npm:5.8.0" + dependencies: + "@ethersproject/base64": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/strings": "npm:^5.8.0" + checksum: 10c0/e3cd547225638db6e94fcd890001c778d77adb0d4f11a7f8c447e961041678f3fbfaffe77a962c7aa3f6597504232442e7015f2335b1788508a108708a30308a + languageName: node + linkType: hard + +"@ethersproject/wordlists@npm:5.8.0, @ethersproject/wordlists@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/wordlists@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/hash": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/strings": "npm:^5.8.0" + checksum: 10c0/e230a2ba075006bc3a2538e096003e43ef9ba453317f37a4d99638720487ec447c1fa61a592c80483f8a8ad6466511cf4cf5c49cf84464a1679999171ce311f4 + languageName: node + linkType: hard + "@farcaster/frame-core@npm:0.0.26": version: 0.0.26 resolution: "@farcaster/frame-core@npm:0.0.26" @@ -2812,6 +3214,13 @@ __metadata: languageName: node linkType: hard +"aes-js@npm:3.0.0": + version: 3.0.0 + resolution: "aes-js@npm:3.0.0" + checksum: 10c0/87dd5b2363534b867db7cef8bc85a90c355460783744877b2db7c8be09740aac5750714f9e00902822f692662bda74cdf40e03fbb5214ffec75c2666666288b8 + languageName: node + linkType: hard + "aes-js@npm:4.0.0-beta.5": version: 4.0.0-beta.5 resolution: "aes-js@npm:4.0.0-beta.5" @@ -3095,6 +3504,8 @@ __metadata: "@coinbase/coinbase-sdk": "npm:^0.21.0" "@coinbase/onchainkit": "npm:^0.37.6" "@eslint/js": "npm:^9.22.0" + "@ethersproject/contracts": "npm:^5.7.0" + "@ethersproject/providers": "npm:^5.7.2" "@ianvs/prettier-plugin-sort-imports": "npm:^4.4.1" "@inquirer/prompts": "npm:^7.4.0" "@modelcontextprotocol/sdk": "npm:^1.6.1" @@ -3110,6 +3521,7 @@ __metadata: eslint: "npm:^9.22.0" eslint-config-prettier: "npm:^10.1.1" eslint-plugin-import: "npm:^2.31.0" + ethers: "npm:^5.7.2" globals: "npm:^16.0.0" graphql: "npm:^16.10.0" graphql-request: "npm:^7.1.2" @@ -3158,6 +3570,13 @@ __metadata: languageName: node linkType: hard +"bech32@npm:1.1.4": + version: 1.1.4 + resolution: "bech32@npm:1.1.4" + checksum: 10c0/5f62ca47b8df99ace9c0e0d8deb36a919d91bf40066700aaa9920a45f86bb10eb56d537d559416fd8703aa0fb60dddb642e58f049701e7291df678b2033e5ee5 + languageName: node + linkType: hard + "better-path-resolve@npm:1.0.0": version: 1.0.0 resolution: "better-path-resolve@npm:1.0.0" @@ -4026,7 +4445,7 @@ __metadata: languageName: node linkType: hard -"elliptic@npm:^6.5.7": +"elliptic@npm:6.6.1, elliptic@npm:^6.5.7": version: 6.6.1 resolution: "elliptic@npm:6.6.1" dependencies: @@ -4634,6 +5053,44 @@ __metadata: languageName: node linkType: hard +"ethers@npm:^5.7.2": + version: 5.8.0 + resolution: "ethers@npm:5.8.0" + dependencies: + "@ethersproject/abi": "npm:5.8.0" + "@ethersproject/abstract-provider": "npm:5.8.0" + "@ethersproject/abstract-signer": "npm:5.8.0" + "@ethersproject/address": "npm:5.8.0" + "@ethersproject/base64": "npm:5.8.0" + "@ethersproject/basex": "npm:5.8.0" + "@ethersproject/bignumber": "npm:5.8.0" + "@ethersproject/bytes": "npm:5.8.0" + "@ethersproject/constants": "npm:5.8.0" + "@ethersproject/contracts": "npm:5.8.0" + "@ethersproject/hash": "npm:5.8.0" + "@ethersproject/hdnode": "npm:5.8.0" + "@ethersproject/json-wallets": "npm:5.8.0" + "@ethersproject/keccak256": "npm:5.8.0" + "@ethersproject/logger": "npm:5.8.0" + "@ethersproject/networks": "npm:5.8.0" + "@ethersproject/pbkdf2": "npm:5.8.0" + "@ethersproject/properties": "npm:5.8.0" + "@ethersproject/providers": "npm:5.8.0" + "@ethersproject/random": "npm:5.8.0" + "@ethersproject/rlp": "npm:5.8.0" + "@ethersproject/sha2": "npm:5.8.0" + "@ethersproject/signing-key": "npm:5.8.0" + "@ethersproject/solidity": "npm:5.8.0" + "@ethersproject/strings": "npm:5.8.0" + "@ethersproject/transactions": "npm:5.8.0" + "@ethersproject/units": "npm:5.8.0" + "@ethersproject/wallet": "npm:5.8.0" + "@ethersproject/web": "npm:5.8.0" + "@ethersproject/wordlists": "npm:5.8.0" + checksum: 10c0/8f187bb6af3736fbafcb613d8fb5be31fe7667a1bae480dd0a4c31b597ed47e0693d552adcababcb05111da39a059fac22e44840ce1671b1cc972de22d6d85d9 + languageName: node + linkType: hard + "ethers@npm:^6.12.1, ethers@npm:^6.13.5, ethers@npm:^6.9.0": version: 6.13.5 resolution: "ethers@npm:6.13.5" @@ -5345,7 +5802,7 @@ __metadata: languageName: node linkType: hard -"hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": +"hash.js@npm:1.1.7, hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": version: 1.1.7 resolution: "hash.js@npm:1.1.7" dependencies: @@ -5935,6 +6392,13 @@ __metadata: languageName: node linkType: hard +"js-sha3@npm:0.8.0": + version: 0.8.0 + resolution: "js-sha3@npm:0.8.0" + checksum: 10c0/43a21dc7967c871bd2c46cb1c2ae97441a97169f324e509f382d43330d8f75cf2c96dba7c806ab08a425765a9c847efdd4bffbac2d99c3a4f3de6c0218f40533 + languageName: node + linkType: hard + "js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -7624,6 +8088,13 @@ __metadata: languageName: node linkType: hard +"scrypt-js@npm:3.0.1": + version: 3.0.1 + resolution: "scrypt-js@npm:3.0.1" + checksum: 10c0/e2941e1c8b5c84c7f3732b0153fee624f5329fc4e772a06270ee337d4d2df4174b8abb5e6ad53804a29f53890ecbc78f3775a319323568c0313040c0e55f5b10 + languageName: node + linkType: hard + "secp256k1@npm:^5.0.0": version: 5.0.1 resolution: "secp256k1@npm:5.0.1"