meme模拟器

Monitor box with input, button, and display on gmgn.ai

  1. // ==UserScript==
  2. // @name meme模拟器
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.11
  5. // @description Monitor box with input, button, and display on gmgn.ai
  6. // @author nians
  7. // @match https://gmgn.ai/*/token/*
  8. // @grant none
  9. // @license MIT
  10. // @license
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. // 根据URL确定货币单位
  17. const getCurrencyUnit = () => {
  18. const url = window.location.href;
  19. if (url.includes('https://gmgn.ai/sol/token/')) return 'SOL';
  20. if (url.includes('https://gmgn.ai/bsc/token/')) return 'BNB';
  21. if (url.includes('https://gmgn.ai/eth/token/')) return 'ETH';
  22. if (url.includes('https://gmgn.ai/base/token/')) return 'ETH';
  23. if (url.includes('https://gmgn.ai/tron/token/')) return 'TRX';
  24. return 'Unknown';
  25. };
  26.  
  27. const currencyUnit = getCurrencyUnit();
  28.  
  29. // 创建容器
  30. const container = document.createElement('div');
  31. container.id = 'monitorBox';
  32. document.body.appendChild(container);
  33.  
  34. // 添加样式
  35. const styles = `
  36. #monitorBox {
  37. position: fixed;
  38. top: 60%;
  39. right: 81%;
  40. width: 280px;
  41. height: 350px;
  42. background: linear-gradient(135deg, #1e1e1e, #2a2a2a);
  43. border-radius: 15px;
  44. box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
  45. padding: 20px;
  46. display: flex;
  47. flex-direction: column;
  48. justify-content: space-between;
  49. z-index: 9999;
  50. color: #fff;
  51. font-family: 'Courier New', monospace;
  52. }
  53.  
  54. #monitorInput, #monitorButton, #monitorDisplay, #closeButton {
  55. width: 100%;
  56. box-sizing: border-box;
  57. border: none;
  58. border-radius: 8px;
  59. padding: 10px;
  60. font-size: 14px;
  61. }
  62.  
  63. #monitorInput {
  64. background: #333;
  65. color: #fff;
  66. outline: none;
  67. }
  68.  
  69. #monitorButton {
  70. background: #007bff;
  71. color: #fff;
  72. cursor: pointer;
  73. transition: background 0.3s;
  74. }
  75.  
  76. #monitorButton:hover {
  77. background: #0056b3;
  78. }
  79.  
  80. #monitorDisplay {
  81. background: #444;
  82. color: #0f0;
  83. height: 120px;
  84. overflow-y: auto;
  85. resize: none;
  86. font-family: 'Courier New', monospace;
  87. text-shadow: 0 0 5px rgba(0, 255, 0, 0.5);
  88. }
  89.  
  90. #buttonContainer {
  91. display: flex;
  92. gap: 10px;
  93. margin-top: 10px;
  94. }
  95.  
  96. #channelButton, #authorButton, #closeButton {
  97. flex: 1;
  98. padding: 8px;
  99. border: none;
  100. border-radius: 8px;
  101. color: #fff;
  102. cursor: pointer;
  103. font-size: 14px;
  104. transition: transform 0.2s, box-shadow 0.2s;
  105. text-align: center;
  106. text-decoration: none;
  107. }
  108.  
  109. #channelButton {
  110. background: #87CEEB;
  111. }
  112.  
  113. #authorButton {
  114. background: #FFB6C1;
  115. }
  116.  
  117. #closeButton {
  118. background: #ff0000;
  119. margin-top: 10px;
  120. }
  121.  
  122. #channelButton:hover, #authorButton:hover, #closeButton:hover {
  123. transform: translateY(-2px);
  124. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
  125. }
  126.  
  127. #channelButton:active, #authorButton:active, #closeButton:active {
  128. transform: translateY(0);
  129. }
  130. `;
  131.  
  132. const styleSheet = document.createElement('style');
  133. styleSheet.textContent = styles;
  134. document.head.appendChild(styleSheet);
  135.  
  136. // 创建输入框
  137. const input = document.createElement('input');
  138. input.id = 'monitorInput';
  139. input.placeholder = `请输入购买金额 (${currencyUnit})...`;
  140. container.appendChild(input);
  141.  
  142. // 创建货币单位标签
  143. const currencyLabel = document.createElement('span');
  144. currencyLabel.textContent = ` ${currencyUnit}`;
  145. currencyLabel.style.color = '#fff';
  146. currencyLabel.style.position = 'absolute';
  147. currencyLabel.style.right = '30px';
  148. currencyLabel.style.top = '25px';
  149. container.appendChild(currencyLabel);
  150.  
  151. // 创建按钮
  152. const button = document.createElement('button');
  153. button.id = 'monitorButton';
  154. button.textContent = '购买';
  155. container.appendChild(button);
  156.  
  157. // 创建显示框
  158. const display = document.createElement('textarea');
  159. display.id = 'monitorDisplay';
  160. display.readOnly = true;
  161. display.placeholder = '显示收益...';
  162. container.appendChild(display);
  163.  
  164. // 创建按钮容器
  165. const buttonContainer = document.createElement('div');
  166. buttonContainer.id = 'buttonContainer';
  167. container.appendChild(buttonContainer);
  168.  
  169. // 创建频道按钮
  170. const channelButton = document.createElement('a');
  171. channelButton.id = 'channelButton';
  172. channelButton.textContent = '频道';
  173. channelButton.href = 'https://t.me/pumpadd';
  174. channelButton.target = '_blank';
  175. buttonContainer.appendChild(channelButton);
  176.  
  177. // 创建作者按钮
  178. const authorButton = document.createElement('a');
  179. authorButton.id = 'authorButton';
  180. authorButton.textContent = '作者';
  181. authorButton.href = 'https://t.me/nians26';
  182. authorButton.target = '_blank';
  183. buttonContainer.appendChild(authorButton);
  184.  
  185. // 创建关闭按钮
  186. const closeButton = document.createElement('button');
  187. closeButton.id = 'closeButton';
  188. closeButton.textContent = '关闭模拟';
  189. container.appendChild(closeButton);
  190.  
  191. // 数据存储
  192. let purchaseData = {
  193. amount: 0,
  194. initialMarketCap: 0,
  195. tokenName: '',
  196. currentMarketCap: 0,
  197. solPrice: 0
  198. };
  199.  
  200. let updateInterval = null;
  201.  
  202. // 转换市值单位
  203. function parseMarketCap(text) {
  204. text = text.replace('$', '');
  205. if (text.includes('K')) return parseFloat(text.replace('K', '')) * 1000;
  206. if (text.includes('M')) return parseFloat(text.replace('M', '')) * 1000000;
  207. if (text.includes('B')) return parseFloat(text.replace('B', '')) * 1000000000;
  208. return parseFloat(text);
  209. }
  210.  
  211. // 获取市场和代币名称的函数
  212. function getMarketData() {
  213. try {
  214. const marketCapElement = document.querySelector('div.css-b5f2qn');
  215. const tokenNameElement = document.querySelector('p.css-1jhlptf');
  216. const solPriceElement = document.querySelector('div.css-1czhozd');
  217.  
  218. if (!marketCapElement) throw new Error('无法找到市值元素 (div.css-b5f2qn)');
  219. if (!tokenNameElement) throw new Error('无法找到代币名称元素 (p.css-1jhlptf)');
  220. if (!solPriceElement) throw new Error('无法找到SOL价格元素 (div.css-1czhozd)');
  221.  
  222. const marketCapText = marketCapElement.textContent.trim();
  223. const tokenNameText = tokenNameElement.textContent.trim();
  224. const solPriceText = solPriceElement.textContent.trim();
  225.  
  226. const marketCap = parseMarketCap(marketCapText);
  227. const tokenName = tokenNameText;
  228.  
  229. const solPriceMatch = solPriceText.match(/\$[\d.]+/);
  230. if (!solPriceMatch) throw new Error(`无法解析${currencyUnit}价格\n市值原始文本: "${marketCapText}"\n代币名称原始文本: "${tokenNameText}"\n${currencyUnit}价格原始文本: "${solPriceText}"`);
  231.  
  232. const solPrice = parseFloat(solPriceMatch[0].replace('$', ''));
  233. if (isNaN(solPrice)) throw new Error(`${currencyUnit}价格解析结果不是有效数字: "${solPriceMatch[0]}"\n市值原始文本: "${marketCapText}"\n代币名称原始文本: "${tokenNameText}"\n${currencyUnit}价格原始文本: "${solPriceText}"`);
  234.  
  235. return { marketCap, tokenName, solPrice };
  236. } catch (error) {
  237. display.value = `错误: ${error.message}`;
  238. return null;
  239. }
  240. }
  241.  
  242. // 计算收益百分比
  243. function calculateProfit(initialCap, currentCap) {
  244. const change = ((currentCap - initialCap) / initialCap) * 100;
  245. return change.toFixed(2);
  246. }
  247.  
  248. // 计算USD收益
  249. function calculateUSDProfit(amount, solPrice, profitPercent) {
  250. const usdInvested = amount * solPrice;
  251. const profit = (usdInvested * profitPercent) / 100;
  252. return profit.toFixed(2);
  253. }
  254.  
  255. // 更新显示
  256. function updateDisplay() {
  257. if (purchaseData.amount > 0) {
  258. const data = getMarketData();
  259. if (data) {
  260. purchaseData.currentMarketCap = data.marketCap;
  261. purchaseData.solPrice = data.solPrice || 0;
  262. const profitPercent = calculateProfit(purchaseData.initialMarketCap, purchaseData.currentMarketCap);
  263. const usdProfit = purchaseData.solPrice > 0
  264. ? calculateUSDProfit(purchaseData.amount, purchaseData.solPrice, profitPercent)
  265. : "未知 (-50%)";
  266.  
  267. const formatMarketCap = (cap) => {
  268. if (cap >= 1000000000) return (cap / 1000000000).toFixed(2) + 'B';
  269. if (cap >= 1000000) return (cap / 1000000).toFixed(2) + 'M';
  270. if (cap >= 1000) return (cap / 1000).toFixed(2) + 'K';
  271. return cap.toFixed(2);
  272. };
  273.  
  274. const initialCapFormatted = formatMarketCap(purchaseData.initialMarketCap);
  275. const currentCapFormatted = formatMarketCap(purchaseData.currentMarketCap);
  276.  
  277. display.value = `购买的市值为: $${initialCapFormatted}\n当前的市值为: $${currentCapFormatted}\n本次模拟收益为: $${usdProfit} (${profitPercent}%)`;
  278. }
  279. }
  280. }
  281.  
  282. // 按钮点击事件
  283. button.addEventListener('click', () => {
  284. const inputValue = parseFloat(input.value.trim());
  285. if (inputValue && inputValue > 0) {
  286. const data = getMarketData();
  287. if (data) {
  288. purchaseData.amount = inputValue;
  289. purchaseData.initialMarketCap = data.marketCap;
  290. purchaseData.tokenName = data.tokenName;
  291. purchaseData.currentMarketCap = data.marketCap;
  292. purchaseData.solPrice = data.solPrice;
  293. display.value = `购买 ${data.tokenName}\n金额: ${inputValue} ${currencyUnit}\n市值: $${data.marketCap}`;
  294.  
  295. if (updateInterval) clearInterval(updateInterval);
  296. updateInterval = setInterval(updateDisplay, 5000);
  297. }
  298. } else {
  299. display.value = '请输入有效金额!';
  300. }
  301. });
  302.  
  303. // 关闭按钮事件
  304. closeButton.addEventListener('click', () => {
  305. if (updateInterval) {
  306. clearInterval(updateInterval);
  307. updateInterval = null;
  308. }
  309. purchaseData = {
  310. amount: 0,
  311. initialMarketCap: 0,
  312. tokenName: '',
  313. currentMarketCap: 0,
  314. solPrice: 0
  315. };
  316. input.value = '';
  317. display.value = '模拟已关闭';
  318. });
  319. })();