// ==UserScript== // @name GMGN-Get-Holders // @namespace http://tampermonkey.net/ // @version 2024-10-19 // @description try to take over the world! // @author You // @match https://gmgn.ai/sol/token/* // @icon https://www.google.com/s2/favicons?sz=64&domain=gmgn.ai // @grant none // ==/UserScript== function funcDownload(content, filename) { console.log('begin download'); // 创建隐藏的可下载链接 let eleLink = document.createElement('a'); eleLink.download = filename; eleLink.style.display = 'none'; // 字符内容转变成blob地址 let blob = new Blob([content]); eleLink.href = URL.createObjectURL(blob); // 触发点击 document.body.appendChild(eleLink); eleLink.click(); // 然后移除 document.body.removeChild(eleLink); } function sleep(sleepdelay) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(sleepdelay); }, sleepdelay); }) } var number_chars_obj = { "k": 3, "m": 6, "b": 9, "t": 12, "p": 15 }; var number_chars_arr = ["k", "m", "b", "t", "p"]; function get_float_number(str_number) { let float_number = parseFloat(str_number); for (let number_char of number_chars_arr) { if (str_number.indexOf(number_char) != -1) { float_number = parseFloat(str_number) * 10 ** number_chars_obj[number_char]; } } return float_number; } function getCurrentTime() { const zeroFill = (i) => { if (i >= 0 && i <= 9) { return "0" + i; } else { return '' + i; } } let date = new Date();//当前时间 let year = date.getFullYear(); let month = zeroFill(date.getMonth() + 1);//月 let day = zeroFill(date.getDate());//日 let hour = zeroFill(date.getHours());//时 let minute = zeroFill(date.getMinutes());//分 let second = zeroFill(date.getSeconds());//秒 //当前时间 var curTime = month + day + '_' + hour + minute ; return curTime; } function get_thead_arr_holders() { // let titlearr = _thead.innerText.trim().split(/\r?\n/); let titlearr = ['Maker', 'Owned_per', 'SOL','inflow_usd', 'Owned_amount', // 'avg_buy','avg_sell', 'Buy_counts', 'Sell_counts']; return titlearr; } async function get_tbody_data_holders() { let div_has_tran_table = document.querySelector("div.chakra-tabs__tab-panels.css-2zi8qu"); let tbody = div_has_tran_table.querySelector("div.ag-body.ag-layout-normal div.ag-center-cols-viewport div.ag-center-cols-container"); let arr_tbody_trs; arr_tbody_trs = Array.from(tbody.children); let last_tr = arr_tbody_trs[arr_tbody_trs.length - 1]; let last_row_id = parseInt(last_tr.getAttribute('row-id')); if (arr_res_data_toptrader.length - 1 >= last_row_id + 1) { // 这批已经全部获取了 return false; } for (let i = 0; i < arr_tbody_trs.length; i++) { let cur_row_id = parseInt(arr_tbody_trs[i].getAttribute('row-id')); if (arr_res_data_toptrader.length - 1 >= cur_row_id + 1) { continue; } let arr_tds; arr_tds = Array.from(arr_tbody_trs[i].children); let tdtexts = []; for (let i = 0; i < arr_tds.length; i++) { if (i == 0) { // trader let a_element = arr_tds[i].querySelector("a"); let str_trader = a_element.href.split('/').pop(); tdtexts.push( str_trader); } else if (i == 1) { // Owned% let str_owned = "0"; let float_sol = 0; let arr_owned_sol = arr_tds[i].children[0].children; str_owned = arr_owned_sol[0].innerText.trim().toLowerCase(); str_owned = str_owned.replace(/[%]/g, "").trim(); float_sol = parseFloat(str_owned); tdtexts.push(float_sol); } else if (i == 2) { //sol balance let str_balance = arr_tds[i].children[0].innerText.trim().replace(/[,]/g, "").trim(); str_balance = str_balance.replace(/\s+/g, ""); console.log("str_balance=",str_balance); str_balance = str_balance.toLowerCase(); let float_balance = get_float_number(str_balance); tdtexts.push(float_balance) ; } else if (i == 3) { // source/tf time } else if (i == 4) { // inflow/Amount let str_token_amount = "0"; let arr_sol_amount = arr_tds[i].children[0].children; let str_inflow_amount = arr_sol_amount[0].innerText.trim().toLowerCase(); str_inflow_amount = str_inflow_amount.replace(/[sol$,%\+><]/g, "").trim(); str_token_amount = arr_sol_amount[1].innerText.trim().toLowerCase(); // if (str_token_amount == "--") { // str_token_amount = "0"; // } console.log("str_token_amount=",str_token_amount); let float_token_amount = get_float_number(str_token_amount); tdtexts.push(str_inflow_amount); tdtexts.push(float_token_amount/1e6); } else if (i == 5) { // pnl continue; } else if (i == 6) { // holding duration continue; }else if (i == 7) { // Avg Cost/Sold continue; } else if (i == 8) { // Buy/Sell let str_buysell_counts = arr_tds[i].innerText.trim().toLowerCase(); str_buysell_counts = str_buysell_counts.replace(/[\s+]/g, "").trim(); let arr_buysell_counts = str_buysell_counts.split("/"); let str_buy_counts = arr_buysell_counts[0]; let str_sell_counts = arr_buysell_counts[1]; console.log("str_buy_counts=",str_buy_counts); console.log("str_sell_counts=",str_sell_counts); let float_buy_counts = get_float_number(str_buy_counts) ; let float_sell_counts = get_float_number(str_sell_counts) ; tdtexts.push( float_buy_counts); tdtexts.push(float_sell_counts); continue } else if (i == 9) { // Last Active continue } } arr_res_data_toptrader.push(tdtexts); } return true } function save_resdata_holders() { console.log("enter save_resdata_holders"); arr_res_data_toptrader.forEach((val, index, arr) => { arr[index] = val.join() + "\n" }); let urlpathname = window.location.pathname.slice(1).split('/'); urlpathname = urlpathname.pop() funcDownload(arr_res_data_toptrader.join(""), urlpathname + "_holder_gmgn_sol" + "_" + getCurrentTime() + ".csv"); arr_res_data_toptrader = []; } function autoScroll_holders() { console.log("enter autoScroll_holders"); let interval; let scroll_times = 15; let div_has_tran_table = document.querySelector("div.chakra-tabs__tab-panels.css-2zi8qu"); let tbody = div_has_tran_table.querySelector("div.ag-body.ag-layout-normal div.ag-center-cols-viewport div.ag-center-cols-container"); async function down() { interval = setInterval(async () => { let tbodytrs; console.log("scroll_times=", scroll_times); if (scroll_times > 0) { await sleep(150); tbodytrs = tbody.children; tbodytrs[tbodytrs.length - 1].scrollIntoView({ behavior: "smooth", block: "center" }); let bool_get_tbody = await get_tbody_data_holders(); if (bool_get_tbody == false) { scroll_times = 0; } } else { clearInterval(interval); await get_tbody_data_holders(); save_resdata_holders(); return; } scroll_times--; // tbodytrs = tbody.children; if (arr_res_data_toptrader.length == 101) { clearInterval(interval); await get_tbody_data_holders(); save_resdata_holders(); return; } await sleep(300); }, 1200) } down() } var arr_res_data_toptrader = []; var res_data_toptrader = []; // window.addEventListener('load', async () => { (async function () { console.log("enter load"); await sleep(6000); console.log("create button"); var mydivbox = document.createElement("div"); var button_holders = document.createElement("button");//创建 获取 holders 一个按钮 button_holders.className = "tam-mybutton-gettran" button_holders.textContent = "holder"; //按钮内容 button_holders.style.width = "90px"; //按钮宽度 button_holders.style.height = "20px"; //按钮高度 button_holders.style.align = "center"; //文本居中 button_holders.style.color = "blue"; //按钮文字颜色 button_holders.style.background = "#045710"; //按钮底色 button_holders.style.border = "1px solid #045710"; //边框属性 mydivbox.appendChild(button_holders); mydivbox.style.position = "fixed"; mydivbox.style.top = "200px"; mydivbox.style.right = "40px"; document.body.appendChild(mydivbox); button_holders.addEventListener("click", clickButton_get_holders); //监听按钮点击事件 })(); async function clickButton_get_holders() { arr_res_data_toptrader = []; console.log("enter clickButton_get_holders arr_res_data_toptrader=", arr_res_data_toptrader); let div_chakra_tabs = document.querySelector('[role="tablist"]'); let arr_buttons_chakra = Array.from(div_chakra_tabs.querySelectorAll("button")); let tab_holders_click = undefined; for (let button of arr_buttons_chakra) { if (button.innerText.includes("Holders")) { tab_holders_click = button; break; } } if (tab_holders_click == undefined) { console.log("no tab_holders_click"); return; } await tab_holders_click.click(); await sleep(7000); let div_has_tran_table = document.querySelector("div.chakra-tabs__tab-panels.css-2zi8qu"); let _thead = div_has_tran_table.querySelector("div.css-c6kdal div.ag-header-row.ag-header-row-column"); let arr_th = _thead.children; let tab_click_USD_holder = arr_th[5].querySelector("div.css-1szs8yo"); if (tab_click_USD_holder.innerText.includes("USD")) { await tab_click_USD_holder.click(); await sleep(4000); } let titlearr = get_thead_arr_holders(); arr_res_data_toptrader.push(titlearr); autoScroll_holders(); }