// ==UserScript== // @name pancakeswapV3交易对盈利计算器 // @namespace pancakeswapV3 // @version 0.0.1 // @description 根据实时信息计算你当前的盈利 // @author shenchanran // @match https://pancakeswap.finance/liquidity/* // @grant unsafeWindow // @grant GM_setValue // @grant GM_getValue // @license MIT // ==/UserScript== (function () { 'use strict'; // 创建容器 const panel = document.createElement('div'), $s = Object.fromEntries(new URLSearchParams(unsafeWindow.location.search)); panel.id = 'tm-draggable-panel'; // 基础样式 Object.assign(panel.style, { position: 'fixed', width: '320px', // 改成固定像素更易读,也避免30%在超宽屏下太夸张 maxHeight: '60vh', // 防止太高溢出 right: '20px', top: '80px', background: 'rgba(0,0,0,0.7)', color: '#fff', fontSize: '13px', lineHeight: '1.4', padding: '8px', borderRadius: '8px', boxShadow: '0 8px 24px rgba(0,0,0,0.3)', border: '1px solid rgba(255,255,255,0.2)', zIndex: '999999999', cursor: 'move', userSelect: 'none', display: 'flex', flexDirection: 'column', boxSizing: 'border-box', backdropFilter: 'blur(6px)', WebkitBackdropFilter: 'blur(6px)', overflow: 'hidden' }); // 内部结构 panel.innerHTML = `
V3 盈利计算器 beta
是否在区间内
--
投入金额
--
当前代币价格
--
入场代币价格
--
已获手续费
--
当前代币持仓
--
当前稳定币持仓
--
价格区间
--
当前仓位价值
--
当前盈利
--
当前利率
--
区间上限
--
区间下限
--
持仓建议
价格接近区间上限,建议逐步撤出一部分流动性锁定收益
实时监控中…
`; document.body.appendChild(panel); // 拖拽逻辑 (function makeDraggable(el) { let isDown = false; let startX = 0; let startY = 0; let startLeft = 0; let startTop = 0; function ensureUsingLeftTop() { const rect = el.getBoundingClientRect(); el.style.left = rect.left + 'px'; el.style.top = rect.top + 'px'; el.style.right = 'auto'; el.style.bottom = 'auto'; el.style.cursor = 'move'; } el.addEventListener('mousedown', (e) => { // 如果用户在输入框/按钮上按下,就不要触发拖拽 const tag = e.target.tagName.toLowerCase(); if (tag === 'input' || tag === 'button' || tag === 'textarea' || e.target.isContentEditable) { return; } isDown = true; ensureUsingLeftTop(); startX = e.clientX; startY = e.clientY; startLeft = parseFloat(el.style.left); startTop = parseFloat(el.style.top); e.preventDefault(); }); document.addEventListener('mousemove', (e) => { if (!isDown) return; const dx = e.clientX - startX; const dy = e.clientY - startY; let newLeft = startLeft + dx; let newTop = startTop + dy; const maxLeft = window.innerWidth - el.offsetWidth; const maxTop = window.innerHeight - el.offsetHeight; if (newLeft < 0) newLeft = 0; if (newTop < 0) newTop = 0; if (newLeft > maxLeft) newLeft = maxLeft; if (newTop > maxTop) newTop = maxTop; el.style.left = newLeft + 'px'; el.style.top = newTop + 'px'; }); document.addEventListener('mouseup', () => { isDown = false; }); })(panel); panel.querySelector('#applyInitialUsdBtn').addEventListener('click', function () { const tokenId = $s['tokenId']; if (!tokenId) { return; } let initialUsdValue = panel.querySelector('#initialUsdInput').value; if (initialUsdValue <= 0) { return; } GM_setValue(tokenId, initialUsdValue); render(); }) const nodeMap = { 区间内: { s: '.sc-3fcdcbc5-1.sc-9cde33ed-0.gbBSci.bhTcKs>.sc-989df720-0.kWBErU', i: 0 }, 当前代币持仓: { s: '.sc-3fcdcbc5-1.sc-9cde33ed-0.gbBSci.gFUdWE>.sc-1e14ff52-0.jZKhjC', i: 0 }, 当前稳定币持仓: { s: '.sc-3fcdcbc5-1.sc-9cde33ed-0.gbBSci.gFUdWE>.sc-1e14ff52-0.jZKhjC', i: 1 }, 当前代币奖励: { s: '.sc-3fcdcbc5-1.sc-9cde33ed-0.gbBSci.gFUdWE>.sc-1e14ff52-0.eGVPaE', i: 0 }, 当前稳定币奖励: { s: '.sc-3fcdcbc5-1.sc-9cde33ed-0.gbBSci.gFUdWE>.sc-1e14ff52-0.eGVPaE', i: 1 }, 最低代币价格: { s: '.sc-3fcdcbc5-1.sc-3fb999a5-0.sc-3fb999a5-2.lpuOsy.eUNTUw.diFng>.sc-1e14ff52-0.sc-d3773c3c-0.eFuWTw.dCGsLH', i: 0 }, 最高代币价格: { s: '.sc-3fcdcbc5-1.sc-3fb999a5-0.sc-3fb999a5-2.hKMEfs.eUNTUw.diFng>.sc-1e14ff52-0.sc-d3773c3c-0.eFuWTw.dCGsLH', i: 0 }, 当前代币价格: { s: '.sc-3fcdcbc5-1.sc-3fb999a5-0.sc-3fb999a5-2.gbBSci.eUNTUw.diFng>.dCGsLH', i: 0 }, 汇率分母: { s: '.sc-fd486af3-0.fjJGMT.sc-bb7aac7a-0.jJcYUn', i: 0 } } function $(node) { let nodeE = document.querySelectorAll(node) if (!nodeE) { return false } return nodeE } const green = '#4ade80' const red = '#F54927' const orange = 'orange' function showInfo(info, color = '#4ade80') { const el = document.querySelector('#adviceValue') el.innerText = info; el.style.color = color; } function setValue(name, value, color = false) { const item = panel.querySelector('#' + name) item.innerText = value item.style.color = color ? color : 'white' } function render() { const tokenId = $s['tokenId']; if (!tokenId) { showInfo('获取交易对信息失败,请检查', red) return; } let initialUsdValue = GM_getValue(tokenId, 0)//初始投资金额 if (initialUsdValue == 0) { showInfo('请先设置初始资金', red) return; } showInfo('正在获取数据,如果时间过久,请检查页面是否完全加载或者脚本是否出错', orange) const datas = {} try { for (const e in nodeMap) { const el = $(nodeMap[e].s)[nodeMap[e].i].innerHTML if (!el || el == '') { throw "获取" + e + "失败"; } datas[e] = el } datas['入场代币价格'] = (datas.最高代币价格 * 1 + datas.最低代币价格 * 1) / 2 datas['反向代币实时价格'] = 1 / datas.当前代币价格 //一个代币=多少稳定币 datas['当前代币奖励换算为U'] = datas.当前代币奖励 * datas['反向代币实时价格'] datas['当前手续费总计奖励'] = datas.当前代币奖励换算为U * 1 + datas.当前稳定币奖励 * 1 datas['当前仓位价值'] = datas.当前代币持仓 * datas['反向代币实时价格'] + datas.当前稳定币持仓 * 1 datas['当前盈利'] = datas.当前仓位价值 - initialUsdValue + datas['当前手续费总计奖励'] datas['当前利率'] = datas.当前盈利 / datas.当前仓位价值 * 100 } catch (e) { console.log(e) showInfo('获取数据失败,请检查页面是否完全加载(是否缺数据、是否崩盘)', red) return } if (!datas.汇率分母.includes('USDT') && !datas.汇率分母.includes('USDC')) { showInfo('汇率分母仅支持USDT和USDC,请调整', red) return } setValue('initialUsdValue', '$' + initialUsdValue) setValue('currentPriceValue', datas.当前代币价格) setValue('entryPriceValue', datas.入场代币价格) setValue('feeEarnedValue', datas['当前手续费总计奖励']) setValue('tokenAmountValue', datas.当前代币持仓) setValue('stableAmountValue', '$' + datas.当前稳定币持仓) setValue('rangeValue', datas.最高代币价格 + '~' + datas.最低代币价格) setValue('positionNowValue', '$' + datas['当前仓位价值']) setValue('profitValue', '$' + datas.当前盈利, datas.当前盈利 > 0 ? green : red) setValue('apyValue', (datas['当前利率'] > 0 ? '+' : '-') + datas['当前利率'].toFixed(3) + '%', datas['当前利率'] > 0 ? green : red) setValue('rangeHighValue', datas.最低代币价格) setValue('rangeLowValue', datas.最高代币价格) setValue('isIN','是',green) if (!datas.区间内.includes('区间内')) { setValue('isIN','否',red) if (datas.当前代币价格 < datas.最低代币价格) { showInfo('你的池子已经赚够了钱,请撤出,继续持有也不会再有奖励', green) } else if (datas.当前代币价格 > datas.最高代币价格) { showInfo('代币价值下跌,你的池子全是廉价代币,请评估币价是否会回升或立即撤出止损', red) } } else if (datas.当前盈利 <= 0) { showInfo('你已经出现了事实亏损,请考虑撤出', orange) return } else if (datas.当前盈利 > 0) { showInfo('你正在盈利,无须担心', green) return } } setInterval(render, 500) })();