UNPKG

bnbchain-mcp

Version:

---

283 lines (282 loc) 10.6 kB
import { z } from "zod"; import { parseEther, decodeEventLog, } from "viem"; import { client, account } from "../config.js"; export const CreateFourMemeSchema = z.object({ name: z.string().describe("name"), shortName: z.string().describe("short name"), imgUrl: z.string().describe("image url"), preSale: z.string().describe("pre sale value"), desc: z.string().describe("description"), twitterUrl: z.string().optional().describe("twitterUrl"), telegramUrl: z.string().optional().describe("telegramUrl"), webUrl: z.string().optional().describe("webUrl"), }); const fourMemeToken = { token: "", time: 0, }; export const loginFourMeme = async () => { if (Date.now() - fourMemeToken.time < 1000 * 60 * 10) { return fourMemeToken.token; } if (Date.now() - fourMemeToken.time < 1000 * 60 * 15) { const resp = await fetch("https://four.meme/meme-api/v1/private/user/info", { headers: { "meme-web-access": fourMemeToken.token, }, method: "GET", }); if (resp.status === 200) { const userInfo = await resp.json(); if (userInfo.msg === "success") { fourMemeToken.time = Date.now(); return fourMemeToken.token; } } } const generateResp = await fetch(`https://four.meme/meme-api/v1/private/user/nonce/generate`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ accountAddress: account.address, verifyType: "LOGIN", networkCode: "BSC", }), }); if (generateResp.status !== 200) { throw new Error("service error"); } const generateJson = await generateResp.json(); const data = `You are sign in Meme ${generateJson.data}`; const signature = await account.signMessage({ message: data, }); const loginResp = await fetch(`https://four.meme/meme-api/v1/private/user/login/dex`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ region: "WEB", langType: "EN", loginIp: "", inviteCode: "", verifyInfo: { address: account.address, networkCode: "BSC", signature: signature, verifyType: "LOGIN", }, walletName: "MetaMask", }), }); if (loginResp.status !== 200) { throw new Error("service error"); } const loginJson = await loginResp.json(); fourMemeToken.token = loginJson.data; fourMemeToken.time = Date.now(); return fourMemeToken.token; }; export const createMemeTokenData = async (data, token) => { const createResp = await fetch(`https://four.meme/meme-api/v1/private/token/create`, { method: "POST", headers: { "Content-Type": "application/json", "meme-web-access": token, }, body: JSON.stringify({ ...data, totalSupply: 1000000000, raisedAmount: 24, saleRate: 0.8, reserveRate: 0, raisedToken: { symbol: "BNB", nativeSymbol: "BNB", symbolAddress: "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c", deployCost: "0", buyFee: "0.01", sellFee: "0.01", minTradeFee: "0", b0Amount: "8", totalBAmount: "24", totalAmount: "1000000000", logoUrl: "https://static.four.meme/market/68b871b6-96f7-408c-b8d0-388d804b34275092658264263839640.png", tradeLevel: ["0.1", "0.5", "1"], status: "PUBLISH", buyTokenLink: "https://pancakeswap.finance/swap", reservedNumber: 10, saleRate: "0.8", networkCode: "BSC", platform: "MEME", }, launchTime: Date.now(), funGroup: false, clickFun: false, symbol: "BNB", label: "Meme", lpTradingFee: 0.0025, }), }); const createJson = await createResp.json(); if (createJson.msg !== "success") { throw new Error(`create token data error ${createJson.msg}`); } const preSaleNum = (parseEther(data.preSale) * BigInt(101)) / BigInt(100); return { createArg: createJson.data.createArg, signature: createJson.data.signature, value: preSaleNum, }; }; export function registerCreateMemeToken(server) { server.tool("createFourMeme", "create new meme token on four.meme", CreateFourMemeSchema.shape, async (args_) => { try { const { twitterUrl, telegramUrl, webUrl, ...data } = args_; const args = data; if (twitterUrl !== '') { args.twitterUrl = twitterUrl; } if (telegramUrl !== '') { args.telegramUrl = telegramUrl; } if (webUrl !== '') { args.webUrl = webUrl; } const loginToken = await loginFourMeme(account); const transactionData = await createMemeTokenData(args, loginToken); const contract = "0x5c952063c7fc8610FFDB798152D69F0B9550762b"; const hash = await client.writeContract({ account, address: contract, abi: [ { inputs: [ { internalType: "bytes", name: "args", type: "bytes", }, { internalType: "bytes", name: "signature", type: "bytes", }, ], name: "createToken", outputs: [], stateMutability: "payable", type: "function", }, ], functionName: "createToken", args: [ transactionData.createArg, transactionData.signature, ], value: transactionData.value, }); const transaction = await client.waitForTransactionReceipt({ hash: hash, retryCount: 300, retryDelay: 1000, }); if (transaction.status != "success") { console.log("Transaction failed", transaction); throw new Error("Transaction failed"); } const logData = transaction.logs.find((log) => log.topics.length != 0 && log.topics.includes("0x396d5e902b675b032348d3d2e9517ee8f0c4a926603fbc075d3d282ff00cad20")); if (!logData) { throw new Error("Log not found"); } const decodedLog = decodeEventLog({ abi: [ { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "creator", type: "address", }, { indexed: false, internalType: "address", name: "token", type: "address", }, { indexed: false, internalType: "uint256", name: "requestId", type: "uint256", }, { indexed: false, internalType: "string", name: "name", type: "string", }, { indexed: false, internalType: "string", name: "symbol", type: "string", }, { indexed: false, internalType: "uint256", name: "totalSupply", type: "uint256", }, { indexed: false, internalType: "uint256", name: "launchTime", type: "uint256", }, { indexed: false, internalType: "uint256", name: "launchFee", type: "uint256", }, ], name: "TokenCreate", type: "event", }, ], data: logData.data, topics: logData.topics, }); const address = decodedLog.args.token; return { content: [ { type: "text", text: `create token on four.meme successfully. https://four.meme/token/${address} `, url: ` https://four.meme/token/${address}`, }, ], }; } catch (error) { console.error("create token on four.meme failed:", error); const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: "text", text: `Transaction failed: ${errorMessage}`, }, ], isError: true, }; } }); }