您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
錢包地址管理助手
// ==UserScript== // @name MSU 緞帶肥肥小錢包 // @namespace http://tampermonkey.net/ // @version 0.13 // @author Alex from MyGOTW // @description 錢包地址管理助手 // @match https://msu.io/* // @grant none // @run-at document-end // @license MIT // ==/UserScript== (function() { 'use strict'; const waitForElement = (selector) => { return new Promise(resolve => { // 如果元素已存在,直接返回 if (document.querySelector(selector)) { return resolve(document.querySelector(selector)); } // 建立 observer 監聽 DOM 變化 const observer = new MutationObserver(mutations => { if (document.querySelector(selector)) { observer.disconnect(); resolve(document.querySelector(selector)); } }); observer.observe(document.body, { childList: true, subtree: true }); }); } const createWalletHelper = () => { // 檢查是否已存在錢包小幫手 if (document.querySelector('#msu-wallet-helper')) { console.log('錢包小幫手已存在,跳過創建'); return; } console.log('開始創建錢包小幫手...'); try { // 從 localStorage 獲取保存的錢包資料 let savedWallets = []; try { const storedData = localStorage.getItem('walletAddresses'); if (storedData) { const parsedData = JSON.parse(storedData); // 檢查是否為舊格式(純地址陣列) if (Array.isArray(parsedData) && typeof parsedData[0] === 'string') { // 轉換舊格式到新格式 savedWallets = parsedData.map((address, index) => ({ name: `錢包 ${index + 1}`, address: address })); // 保存新格式 localStorage.setItem('walletAddresses', JSON.stringify(savedWallets)); } else { savedWallets = parsedData; } } } catch (e) { console.error('解析儲存的錢包資料時發生錯誤:', e); } // 如果沒有資料,使用預設值 if (savedWallets.length === 0) { savedWallets = [{ name: '贊助AA🙏', address: '0xfc64f99069FFb79b4B6C1BF9C3579B7fA9cb9B08' }]; localStorage.setItem('walletAddresses', JSON.stringify(savedWallets)); } // 創建主容器 const container = document.createElement('div'); container.id = 'msu-wallet-helper'; // 添加 ID 以便檢查 container.style.cssText = ` position: fixed; right: -300px; top: 10vw; background: #ffffff; padding: 20px; border-radius: 12px 0 0 12px; box-shadow: -2px 0 15px rgba(0,0,0,0.1); z-index: 9999; width: 300px; transition: right 0.3s ease; font-family: Arial, sans-serif; `; // 創建切換按鈕 const toggleButton = document.createElement('div'); toggleButton.style.cssText = ` width: 40px; position: absolute; left: -40px; top: 15%; transform: translateY(-50%); background: linear-gradient(180deg, #acc631, #769700); color: white; padding: 12px; cursor: pointer; border-radius: 6px 0 0 6px; box-shadow: -2px 0 8px rgba(0,0,0,0.2); font-size: 20px; transition: all 0.3s ease; `; toggleButton.textContent = '👛'; toggleButton.onmouseover = () => toggleButton.style.transform = 'translateY(-50%) scale(1.1)'; toggleButton.onmouseout = () => toggleButton.style.transform = 'translateY(-50%)'; // 標題 const title = document.createElement('h3'); title.textContent = '錢包地址管理'; title.style.cssText = ` margin: 0 0 15px 0; color: #333; font-size: 18px; border-bottom: 2px solid #4CAF50; padding-bottom: 10px; `; const hint = document.createElement('div'); hint.textContent = '💡 點擊錢包地址即可複製'; hint.style.cssText = ` color: #666; font-size: 13px; margin-bottom: 15px; padding: 8px; background: #f0f0f0; border-radius: 4px; `; // 地址列表容器 const addressList = document.createElement('div'); addressList.style.cssText = ` max-height: 300px; overflow-y: auto; margin-top: 15px; `; // 新增地址輸入區 const inputContainer = document.createElement('div'); inputContainer.style.cssText = ` display: none; gap: 8px; margin-bottom: 15px; flex-wrap: wrap; `; const nameInput = document.createElement('input'); nameInput.style.cssText = ` width: 120px; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; color: #000000; `; nameInput.placeholder = '錢包名稱...'; const addressInput = document.createElement('input'); addressInput.style.cssText = ` flex: 1; min-width: 200px; padding: 6px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; color: #000000; cursor: pointer; transition: background-color 0.3s ease; `; addressInput.placeholder = '輸入錢包地址...'; // 添加點擊複製功能 addressInput.onclick = () => { navigator.clipboard.writeText(wallet.address); // 創建提示容器 const copyTip = document.createElement('div'); copyTip.style.cssText = ` position: absolute; background: #4CAF50; color: white; padding: 4px 8px; border-radius: 4px; font-size: 12px; white-space: nowrap; left: 50%; transform: translateX(-50%); top: 50%; z-index: 1000; `; copyTip.textContent = '已複製✓'; // 將提示加入到輸入框的父元素中 addressInput.parentElement.appendChild(copyTip); // 添加綠色漸變背景動畫 addressInput.style.background = 'linear-gradient(to right, #4CAF50, #45a049)'; // 1秒後移除提示和背景效果 setTimeout(() => { copyTip.remove(); addressInput.style.background = 'white'; }, 1000); }; const addButton = document.createElement('button'); addButton.textContent = '新增錢包'; addButton.style.cssText = ` background: #4CAF50; color: white; border: none; padding: 8px 15px; border-radius: 4px; cursor: pointer; transition: background 0.3s; margin-bottom: 15px; `; addButton.onmouseover = () => addButton.style.background = '#45a049'; addButton.onmouseout = () => addButton.style.background = '#4CAF50'; const confirmButton = document.createElement('button'); confirmButton.textContent = '確認'; confirmButton.style.cssText = ` background: #cccccc; color: white; border: none; padding: 8px 15px; border-radius: 4px; cursor: not-allowed; transition: all 0.3s; `; // 監聽輸入框的變化 const updateConfirmButton = () => { const hasAddress = addressInput.value.trim() !== ''; if (hasAddress) { confirmButton.style.background = '#4CAF50'; confirmButton.style.cursor = 'pointer'; } else { confirmButton.style.background = '#cccccc'; confirmButton.style.cursor = 'not-allowed'; } }; // 添加輸入事件監聽 addressInput.addEventListener('input', updateConfirmButton); // 渲染地址列表 const renderWallets = () => { addressList.innerHTML = ''; savedWallets.forEach((wallet, index) => { const walletItem = document.createElement('div'); walletItem.style.cssText = ` display: flex; align-items: center; gap: 8px; padding: 8px; background: #f5f5f5; border-radius: 4px; margin-bottom: 8px; flex-wrap: wrap; position: relative; `; const nameContainer = document.createElement('div'); nameContainer.style.cssText = ` display: flex; align-items: center; gap: 4px; position: relative; `; const nameInput = document.createElement('input'); nameInput.value = wallet.name; nameInput.readOnly = true; nameInput.style.cssText = ` width: 100px; padding: 6px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; color: #000000; `; // 新增包包連結 const bagLink = document.createElement('a'); bagLink.href = `https://msu.io/marketplace/inventory/${wallet.address}`; bagLink.target = "_blank"; bagLink.innerHTML = "🔍"; bagLink.style.cssText = ` text-decoration: none; cursor: pointer; font-size: 16px; padding: 4px; transition: transform 0.2s ease; `; // 添加懸停效果 bagLink.onmouseover = () => bagLink.style.transform = 'scale(1.2)'; bagLink.onmouseout = () => bagLink.style.transform = 'scale(1)'; // 將元素添加到 nameContainer nameContainer.append(nameInput, bagLink); const addressInput = document.createElement('input'); addressInput.value = wallet.address; addressInput.readOnly = true; addressInput.style.cssText = ` flex: 1; min-width: 200px; padding: 6px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; color: #000000; cursor: pointer; transition: background-color 0.3s ease; `; // 添加點擊複製功能 addressInput.onclick = () => { navigator.clipboard.writeText(wallet.address); // 創建提示容器 const copyTip = document.createElement('div'); copyTip.style.cssText = ` position: absolute; background: black; color: white; padding: 4px 8px; border-radius: 4px; font-size: 12px; white-space: nowrap; left: 50%; transform: translateX(-50%); top: 50%; z-index: 1000; `; copyTip.textContent = '已複製✓'; // 將提示加入到輸入框的父元素中 addressInput.parentElement.appendChild(copyTip); // 添加綠色漸變背景動畫 addressInput.style.background = 'rgb(186 224 188)'; // 1秒後移除提示和背景效果 setTimeout(() => { copyTip.remove(); addressInput.style.background = 'white'; }, 1000); }; // 防止輸入框被編輯 addressInput.readOnly = true; const deleteButton = document.createElement('div'); deleteButton.innerHTML = '✕'; deleteButton.style.cssText = ` background: #666666; color: white; cursor: pointer; width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; border-radius: 4px; font-size: 14px; font-weight: bold; transition: all 0.2s ease; line-height: 1; z-index: 1; margin-left: auto; `; // hover 效果 deleteButton.onmouseover = () => { deleteButton.style.background = '#ff4444'; deleteButton.style.transform = 'scale(1.1)'; }; deleteButton.onmouseout = () => { deleteButton.style.background = '#666666'; deleteButton.style.transform = 'scale(1)'; }; // 刪除功能 deleteButton.onclick = () => { savedWallets.splice(index, 1); localStorage.setItem('walletAddresses', JSON.stringify(savedWallets)); renderWallets(); }; // 編輯功能 nameInput.onchange = () => { savedWallets[index].name = nameInput.value; localStorage.setItem('walletAddresses', JSON.stringify(savedWallets)); }; addressInput.onchange = () => { savedWallets[index].address = addressInput.value; localStorage.setItem('walletAddresses', JSON.stringify(savedWallets)); }; walletItem.append(nameContainer, addressInput, deleteButton); addressList.appendChild(walletItem); }); }; // 新增錢包功能 addButton.onclick = () => { inputContainer.style.display = 'flex'; addButton.style.display = 'none'; }; confirmButton.onclick = () => { const newName = nameInput.value.trim(); const newAddress = addressInput.value.trim(); if (newAddress) { savedWallets.push({ name: newName || `錢包 ${savedWallets.length + 1}`, address: newAddress }); localStorage.setItem('walletAddresses', JSON.stringify(savedWallets)); nameInput.value = ''; addressInput.value = ''; renderWallets(); // 重置顯示狀態 inputContainer.style.display = 'none'; addButton.style.display = 'block'; // 重置確認按鈕狀態 updateConfirmButton(); } }; // 切換顯示/隱藏的功能 let isVisible = false; toggleButton.onclick = () => { isVisible = !isVisible; container.style.right = isVisible ? '0' : '-300px'; }; // 組裝 DOM container.appendChild(toggleButton); container.appendChild(title); container.appendChild(hint); container.appendChild(addButton); inputContainer.append(nameInput, addressInput, confirmButton); container.append(inputContainer, addressList); document.body.appendChild(container); // 初始渲染錢包列表 renderWallets(); console.log('錢包小幫手已成功插入 DOM'); } catch (error) { console.error('創建錢包小幫手時發生錯誤:', error); } }; const initialize = async () => { console.log('Initialize being called with URL:', window.location.href); // 新增 URL 檢查的除錯訊息 if (!window.location.href.includes('/marketplace/inventory/')) { console.log('URL 不符合條件,退出初始化'); return; } try { console.log('開始等待目標元素...'); // 等待目標元素出現 const targetNode = await waitForElement('div[class*="item-list"]'); console.log('目標元素已找到:', targetNode); // 直接創建 helper createWalletHelper(); // 設置 observer 監聽後續變化 const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.addedNodes.length) { console.log('DOM 變化偵測到,但 helper 應該已經創建'); } }); }); observer.observe(targetNode, { childList: true, subtree: true }); } catch (error) { console.error('Error initializing:', error); } } const handleUrlChange = (method) => { console.log(`小精靈通知: [${method}] URL 已變化: ${window.location.href}`); initialize(); }; const originalPushState = history.pushState; const originalReplaceState = history.replaceState; history.pushState = function(...args) { originalPushState.apply(history, args); handleUrlChange('pushState'); }; history.replaceState = function(...args) { originalReplaceState.apply(history, args); handleUrlChange('replaceState'); }; window.addEventListener('popstate', () => { handleUrlChange('popstate'); }); })();