web3ChangeChain.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. // ==UserScript==
  2. // @name Web3网络快速切换器
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.1
  5. // @description 在页面上添加下拉框快速切换Web3钱包网络
  6. // @author You
  7. // @match *://*/*
  8. // @grant GM_notification
  9. // ==/UserScript==
  10. (function() {
  11. 'use strict';
  12. // 配置:预设的网络列表(目前只有Monad测试网,您可以自行添加)
  13. const networks = [
  14. { name: "Monad Testnet", chainId: "0x4a", rpcUrls: ["https://testnet.monad.xyz"] }
  15. // 您可以在这里添加其他网络,格式如下:
  16. // { name: "网络名称", chainId: "网络ID", rpcUrls: ["RPC URL"] },
  17. ];
  18. // 创建样式
  19. const style = document.createElement('style');
  20. style.textContent = `
  21. .web3-network-switcher {
  22. position: fixed;
  23. top: 20px;
  24. right: 20px;
  25. z-index: 9999;
  26. padding: 10px;
  27. background-color: rgba(255, 255, 255, 0.95);
  28. border: 1px solid #ccc;
  29. border-radius: 8px;
  30. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  31. font-family: Arial, sans-serif;
  32. min-width: 200px;
  33. }
  34. .web3-network-switcher label {
  35. display: block;
  36. margin-bottom: 8px;
  37. font-weight: bold;
  38. color: #333;
  39. }
  40. .web3-network-switcher select {
  41. width: 100%;
  42. padding: 8px;
  43. border-radius: 4px;
  44. border: 1px solid #ddd;
  45. background-color: white;
  46. font-size: 14px;
  47. }
  48. .web3-network-switcher select:focus {
  49. outline: none;
  50. border-color: #4a90e2;
  51. box-shadow: 0 0 0 2px rgba(74, 144, 226, 0.2);
  52. }
  53. .web3-network-switcher .status {
  54. margin-top: 8px;
  55. font-size: 12px;
  56. color: #666;
  57. }
  58. .web3-network-switcher .toggle {
  59. position: absolute;
  60. top: 5px;
  61. right: 5px;
  62. cursor: pointer;
  63. font-weight: bold;
  64. color: #999;
  65. }
  66. .web3-network-switcher.collapsed {
  67. width: auto;
  68. min-width: auto;
  69. padding: 5px;
  70. }
  71. .web3-network-switcher.collapsed select,
  72. .web3-network-switcher.collapsed label,
  73. .web3-network-switcher.collapsed .status {
  74. display: none;
  75. }
  76. `;
  77. document.head.appendChild(style);
  78. // 等待页面加载完成后执行
  79. setTimeout(init, 2000);
  80. function init() {
  81. // 如果页面已存在切换器,先移除
  82. const existing = document.getElementById('web3-network-switcher');
  83. if (existing) existing.remove();
  84. // 重新初始化
  85. if (typeof window.ethereum !== 'undefined') {
  86. // 这里需要执行createNetworkSelector函数
  87. // 可能需要将函数改为全局可访问
  88. console.log('Web3钱包已检测到');
  89. } else {
  90. console.log('未检测到Web3钱包');
  91. }
  92. // 创建网络选择器
  93. createNetworkSelector();
  94. }
  95. function createNetworkSelector() {
  96. // 如果已存在,先移除
  97. const existing = document.getElementById('web3-network-switcher');
  98. if (existing) existing.remove();
  99. // 创建容器
  100. const container = document.createElement('div');
  101. container.className = 'web3-network-switcher';
  102. container.id = 'web3-network-switcher';
  103. // 创建折叠按钮
  104. const toggleBtn = document.createElement('div');
  105. toggleBtn.className = 'toggle';
  106. toggleBtn.textContent = '−';
  107. toggleBtn.title = '折叠/展开';
  108. toggleBtn.onclick = function() {
  109. container.classList.toggle('collapsed');
  110. toggleBtn.textContent = container.classList.contains('collapsed') ? '+' : '−';
  111. };
  112. // 创建标签
  113. const label = document.createElement('label');
  114. label.textContent = '切换到Monad:';
  115. label.htmlFor = 'web3-network-select';
  116. // 创建下拉选择框
  117. const select = document.createElement('select');
  118. select.id = 'web3-network-select';
  119. // 添加网络选项
  120. networks.forEach(network => {
  121. const option = document.createElement('option');
  122. option.value = network.chainId;
  123. option.textContent = network.name;
  124. select.appendChild(option);
  125. });
  126. // 添加状态显示
  127. const status = document.createElement('div');
  128. status.className = 'status';
  129. status.textContent = '就绪';
  130. status.id = 'web3-network-status';
  131. // 添加事件监听器
  132. select.addEventListener('change', function() {
  133. const selectedChainId = this.value;
  134. const selectedNetwork = networks.find(net => net.chainId === selectedChainId);
  135. if (selectedNetwork) {
  136. status.textContent = `切换中: ${selectedNetwork.name}...`;
  137. status.style.color = '#4a90e2';
  138. switchNetwork(selectedNetwork);
  139. }
  140. });
  141. // 添加到容器
  142. container.appendChild(toggleBtn);
  143. container.appendChild(label);
  144. container.appendChild(select);
  145. container.appendChild(status);
  146. // 添加到页面
  147. document.body.appendChild(container);
  148. // 添加拖动功能
  149. makeDraggable(container);
  150. }
  151. async function switchNetwork(network) {
  152. const status = document.getElementById('web3-network-status');
  153. try {
  154. // 尝试切换到指定网络
  155. await window.ethereum.request({
  156. method: 'wallet_switchEthereumChain',
  157. params: [{ chainId: network.chainId }],
  158. });
  159. status.textContent = `已切换到 ${network.name}`;
  160. status.style.color = 'green';
  161. } catch (switchError) {
  162. // 如果网络未添加,尝试添加它
  163. if (switchError.code === 4902) {
  164. status.textContent = '添加新网络中...';
  165. status.style.color = '#4a90e2';
  166. try {
  167. await window.ethereum.request({
  168. method: 'wallet_addEthereumChain',
  169. params: [{
  170. chainId: network.chainId,
  171. chainName: network.name,
  172. rpcUrls: network.rpcUrls,
  173. nativeCurrency: {
  174. name: 'MON',
  175. symbol: 'MON',
  176. decimals: 18
  177. },
  178. blockExplorerUrls: ['https://explorer.monad.xyz']
  179. }],
  180. });
  181. status.textContent = `已添加并切换到 ${network.name}`;
  182. status.style.color = 'green';
  183. } catch (addError) {
  184. status.textContent = `添加失败: ${addError.message}`;
  185. status.style.color = 'red';
  186. }
  187. } else {
  188. status.textContent = `切换失败: ${switchError.message}`;
  189. status.style.color = 'red';
  190. }
  191. }
  192. }
  193. function makeDraggable(element) {
  194. let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  195. element.onmousedown = dragMouseDown;
  196. function dragMouseDown(e) {
  197. if (e.target.tagName === 'SELECT' || e.target.tagName === 'OPTION') return;
  198. e = e || window.event;
  199. e.preventDefault();
  200. pos3 = e.clientX;
  201. pos4 = e.clientY;
  202. document.onmouseup = closeDragElement;
  203. document.onmousemove = elementDrag;
  204. }
  205. function elementDrag(e) {
  206. e = e || window.event;
  207. e.preventDefault();
  208. pos1 = pos3 - e.clientX;
  209. pos2 = pos4 - e.clientY;
  210. pos3 = e.clientX;
  211. pos4 = e.clientY;
  212. element.style.top = (element.offsetTop - pos2) + "px";
  213. element.style.right = "unset";
  214. element.style.left = (element.offsetLeft - pos1) + "px";
  215. }
  216. function closeDragElement() {
  217. document.onmouseup = null;
  218. document.onmousemove = null;
  219. }
  220. }
  221. })();