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.**
116 lines (115 loc) • 3.87 kB
JavaScript
import { z } from "zod";
import { parseUnits, toEventSelector, decodeEventLog } from "viem";
import { getAccount, publicClient, walletClient } from "../config.js";
import { AddressConfig } from "../addressConfig.js";
import { supportedChain } from "../chains/index.js";
import { portfolioTokenFactoryAbi } from "../lib/portfolioTokenFactoryAbi.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 registerCreateERC20Token(server) {
server.tool("Create_ERC20_Token", "🔨Create a new ERC20 standard 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 account = await getAccount();
const contract = AddressConfig.PortfolioTokenFactoryContract;
const hash = await walletClient(account).writeContract({
account,
address: contract,
abi: portfolioTokenFactoryAbi,
functionName: "createStandardToken",
args: [
name,
symbol,
parseUnits(intialSupply, 18),
parseUnits(maxSupply, 18),
parseUnits(amountPerMint, 18),
],
});
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}`,
},
],
isError: true,
};
}
});
}