Skip to main content
Glama

MCP Ethers Wallet

erc1155.ts11.9 kB
/** * @file ERC1155 Tool Handlers * @version 1.0.0 * * Tool handlers for ERC1155 multi-token standard operations */ import { z } from 'zod'; import { TokenOperationOptions } from '../../services/erc/types.js'; import { validateWithFriendlyErrors, createErrorResponse, CommonSchemas } from '../../utils/validation.js'; // This will be injected during initialization let ethersService: any; export function initializeErc1155Handlers(service: any) { ethersService = service; } // Common schemas with user-friendly messages const contractAddressSchema = CommonSchemas.ethereumAddress.describe('ERC1155 contract address'); const providerSchema = CommonSchemas.provider; const chainIdSchema = CommonSchemas.chainId; const tokenIdSchema = z.union([z.string(), z.number()]).describe('Token ID (numeric identifier for the specific token type)'); const amountSchema = CommonSchemas.amountString.describe('Amount of tokens in smallest unit'); // Options schema for transaction operations const optionsSchema = z.object({ gasLimit: z.union([z.string(), z.number()]).optional(), gasPrice: z.union([z.string(), z.number()]).optional(), maxFeePerGas: z.union([z.string(), z.number()]).optional(), maxPriorityFeePerGas: z.union([z.string(), z.number()]).optional(), nonce: z.number().optional(), value: z.string().optional(), }).optional(); export const erc1155Handlers = { getERC1155Balance: async (args: unknown) => { const schema = z.object({ contractAddress: contractAddressSchema, ownerAddress: CommonSchemas.ethereumAddress.describe('Address to check balance for'), tokenId: tokenIdSchema, provider: providerSchema, chainId: chainIdSchema }); try { const { contractAddress, ownerAddress, tokenId, provider, chainId } = validateWithFriendlyErrors( schema, args, 'Get ERC1155 Balance' ); const balance = await ethersService.getERC1155Balance( contractAddress, ownerAddress, tokenId, provider, chainId ); return { content: [{ type: "text", text: `${ownerAddress} has a balance of ${balance} of token ID ${tokenId} in contract ${contractAddress}` }] }; } catch (error) { return { isError: true, content: [{ type: "text", text: `Error getting token balance: ${error instanceof Error ? error.message : String(error)}` }] }; } }, getERC1155BatchBalances: async (args: unknown) => { const schema = z.object({ contractAddress: contractAddressSchema, ownerAddresses: z.array(z.string()), tokenIds: z.array(tokenIdSchema), provider: providerSchema, chainId: chainIdSchema }); try { const { contractAddress, ownerAddresses, tokenIds, provider, chainId } = schema.parse(args); // Validate arrays have the same length if (ownerAddresses.length !== tokenIds.length) { return { isError: true, content: [{ type: "text", text: "Error: ownerAddresses and tokenIds arrays must have the same length" }] }; } const balances = await ethersService.getERC1155BatchBalances( contractAddress, ownerAddresses, tokenIds, provider, chainId ); // Build a formatted response let responseText = `Batch balances for contract ${contractAddress}:`; for (let i = 0; i < ownerAddresses.length; i++) { responseText += `\n${ownerAddresses[i]} has ${balances[i]} of token ID ${tokenIds[i]}`; } return { content: [{ type: "text", text: responseText }] }; } catch (error) { return { isError: true, content: [{ type: "text", text: `Error getting batch balances: ${error instanceof Error ? error.message : String(error)}` }] }; } }, getERC1155Metadata: async (args: unknown) => { const schema = z.object({ contractAddress: contractAddressSchema, tokenId: tokenIdSchema, provider: providerSchema, chainId: chainIdSchema }); try { const { contractAddress, tokenId, provider, chainId } = schema.parse(args); const metadata = await ethersService.getERC1155Metadata( contractAddress, tokenId, provider, chainId ); // Build a formatted response with all metadata properties let metadataText = `Token Metadata for ${contractAddress} (ID: ${tokenId}):`; if (metadata.name) metadataText += `\nName: ${metadata.name}`; if (metadata.description) metadataText += `\nDescription: ${metadata.description}`; if (metadata.image) metadataText += `\nImage URL: ${metadata.image}`; if (metadata.external_url) metadataText += `\nExternal URL: ${metadata.external_url}`; // Add attributes if they exist if (metadata.attributes && metadata.attributes.length > 0) { metadataText += '\n\nAttributes:'; for (const attr of metadata.attributes) { if (attr.trait_type && attr.value !== undefined) { metadataText += `\n- ${attr.trait_type}: ${attr.value}`; } } } return { content: [{ type: "text", text: metadataText }] }; } catch (error) { return { isError: true, content: [{ type: "text", text: `Error getting token metadata: ${error instanceof Error ? error.message : String(error)}` }] }; } }, getERC1155TokensOfOwner: async (args: unknown) => { const schema = z.object({ contractAddress: contractAddressSchema, ownerAddress: z.string(), tokenIds: z.array(tokenIdSchema).optional(), includeMetadata: z.boolean().optional().default(false), provider: providerSchema, chainId: chainIdSchema }); try { const { contractAddress, ownerAddress, tokenIds, includeMetadata, provider, chainId } = schema.parse(args); const tokens = await ethersService.getERC1155TokensOfOwner( contractAddress, ownerAddress, tokenIds, includeMetadata, provider, chainId ); if (tokens.length === 0) { return { content: [{ type: "text", text: `${ownerAddress} doesn't own any tokens in contract ${contractAddress}.` }] }; } let responseText = `${ownerAddress} owns ${tokens.length} token type(s) in contract ${contractAddress}:`; for (const token of tokens) { responseText += `\n\nToken ID: ${token.tokenId}`; responseText += `\nBalance: ${token.balance}`; if (token.metadata) { if (token.metadata.name) responseText += `\nName: ${token.metadata.name}`; if (token.metadata.image) responseText += `\nImage URL: ${token.metadata.image}`; // Add a few attributes if they exist (limited to avoid very long responses) if (token.metadata.attributes && token.metadata.attributes.length > 0) { responseText += '\nAttributes:'; const limit = Math.min(3, token.metadata.attributes.length); for (let i = 0; i < limit; i++) { const attr = token.metadata.attributes[i]; if (attr.trait_type && attr.value !== undefined) { responseText += `\n- ${attr.trait_type}: ${attr.value}`; } } if (token.metadata.attributes.length > limit) { responseText += `\n- ... ${token.metadata.attributes.length - limit} more attributes`; } } } } return { content: [{ type: "text", text: responseText }] }; } catch (error) { return { isError: true, content: [{ type: "text", text: `Error getting tokens owned by address: ${error instanceof Error ? error.message : String(error)}` }] }; } }, safeTransferERC1155: async (args: unknown) => { const schema = z.object({ contractAddress: contractAddressSchema, fromAddress: z.string(), toAddress: z.string(), tokenId: tokenIdSchema, amount: amountSchema, data: z.string().optional().default('0x'), provider: providerSchema, chainId: chainIdSchema, gasLimit: z.string().optional(), gasPrice: z.string().optional(), }); try { const { contractAddress, fromAddress, toAddress, tokenId, amount, data, provider, chainId, gasLimit, gasPrice } = schema.parse(args); // Create options object for transaction parameters const options: TokenOperationOptions = {}; if (gasLimit) options.gasLimit = gasLimit; if (gasPrice) options.gasPrice = gasPrice; const tx = await ethersService.safeTransferERC1155( contractAddress, fromAddress, toAddress, tokenId, amount, data, provider, chainId, options ); return { content: [{ type: "text", text: `Successfully transferred ${amount} of token ID ${tokenId} from ${fromAddress} to ${toAddress}.\nTransaction Hash: ${tx.hash}` }] }; } catch (error) { return { isError: true, content: [{ type: "text", text: `Error transferring tokens: ${error instanceof Error ? error.message : String(error)}` }] }; } }, safeBatchTransferERC1155: async (args: unknown) => { const schema = z.object({ contractAddress: contractAddressSchema, fromAddress: z.string(), toAddress: z.string(), tokenIds: z.array(tokenIdSchema), amounts: z.array(amountSchema), data: z.string().optional().default('0x'), provider: providerSchema, chainId: chainIdSchema, gasLimit: z.string().optional(), gasPrice: z.string().optional(), }); try { const { contractAddress, fromAddress, toAddress, tokenIds, amounts, data, provider, chainId, gasLimit, gasPrice } = schema.parse(args); // Validate arrays have the same length if (tokenIds.length !== amounts.length) { return { isError: true, content: [{ type: "text", text: "Error: tokenIds and amounts arrays must have the same length" }] }; } // Create options object for transaction parameters const options: TokenOperationOptions = {}; if (gasLimit) options.gasLimit = gasLimit; if (gasPrice) options.gasPrice = gasPrice; const tx = await ethersService.safeBatchTransferERC1155( contractAddress, fromAddress, toAddress, tokenIds, amounts, data, provider, chainId, options ); // Format the token transfers for the response let transfersText = ''; for (let i = 0; i < tokenIds.length; i++) { transfersText += `\n- ${amounts[i]} of token ID ${tokenIds[i]}`; } return { content: [{ type: "text", text: `Successfully batch transferred the following tokens from ${fromAddress} to ${toAddress}:${transfersText}\n\nTransaction Hash: ${tx.hash}` }] }; } catch (error) { return { isError: true, content: [{ type: "text", text: `Error batch transferring tokens: ${error instanceof Error ? error.message : String(error)}` }] }; } } };

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/crazyrabbitLTC/mcp-ethers-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server