UNPKG

cotiv2-mcp

Version:

> A plug-and-play MCP tool server to **send COTI**, **transfer BEP-20 tokens**, **deploy tokens**, and **interact with smart contracts** on the **COTI v2 Network (COTI)** — built for **Claude Desktop**, **AI agents**, and **developers.**

122 lines (121 loc) 4.44 kB
import { z } from "zod"; import { parseUnits, toEventSelector, decodeEventLog } from "viem"; import { getAccount, getCotiAccount, publicClient, walletClient, } from "../config.js"; import { AddressConfig } from "../addressConfig.js"; import { supportedChain } from "../chains/index.js"; import { portfolioTokenFactoryAbi } from "../lib/portfolioTokenFactoryAbi.js"; import { toField } from "../lib/coti.js"; const abiEvent = { anonymous: false, inputs: [ { indexed: true, internalType: "bool", name: "isPrivate", type: "bool", }, { indexed: true, internalType: "address", name: "owner", type: "address", }, { indexed: false, internalType: "address", name: "newToken", type: "address", }, { indexed: false, internalType: "string", name: "name", type: "string", }, { indexed: false, internalType: "string", name: "symbol", type: "string", }, { indexed: false, internalType: "uint256", name: "maxSupply", type: "uint256", }, ], name: "TokenDeployed", type: "event", }; export function registerCreatePrivateERC20Token(server) { server.tool("Create_PrivateERC20_Token", "🔨Create a new ERC20 private token on COTI v2 network", { name: z.string(), symbol: z.string(), intialSupply: z.string(), maxSupply: z.string(), amountPerMint: z.string(), }, async ({ name, symbol, intialSupply, maxSupply, amountPerMint }) => { try { const contract = AddressConfig.PortfolioTokenFactoryContract; const cotiAccount = await getCotiAccount(); const functionSelector = "0xbd81f4f5"; const itAmountValue = (await cotiAccount.encryptValue(parseUnits(intialSupply, 6), contract, functionSelector)); const itMaxSupplyValue = (await cotiAccount.encryptValue(parseUnits(maxSupply, 6), contract, functionSelector)); const itMintAmountValue = (await cotiAccount.encryptValue(parseUnits(amountPerMint, 6), contract, functionSelector)); const account = await getAccount(); const hash = await walletClient(account).writeContract({ account, address: contract, abi: portfolioTokenFactoryAbi, functionName: "createPrivacyToken", args: [ name, symbol, toField(itAmountValue), toField(itMaxSupplyValue), toField(itMintAmountValue), ], }); const transaction = await publicClient.waitForTransactionReceipt({ hash: hash, retryCount: 300, retryDelay: 100, }); if (transaction.status != "success") { throw new Error("Transaction failed"); } const targetTopic = toEventSelector(abiEvent); const logData = transaction.logs.find((log) => log.topics.includes(targetTopic)); if (!logData) { throw new Error("Log not found"); } const decodedLog = decodeEventLog({ abi: [abiEvent], data: logData.data, topics: logData.topics, }); return { content: [ { type: "text", text: `Create token successfully. ${supportedChain.blockExplorers.default.url}/tx/${hash}, Token Address: ${decodedLog.args.newToken}`, url: `${supportedChain.blockExplorers.default.url}/tx/${hash}`, }, ], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: "text", text: `Transaction failed: ${errorMessage}. ${JSON.stringify(error)}`, }, ], isError: true, }; } }); }