├── id_users.txt ├── seeds.txt ├── requirements.txt ├── LavaMoatExtFix.py ├── README.md ├── LavaMoatProfileCacheFix.py └── main.py /id_users.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /seeds.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/desti-w/adspower-import-metamask-rework/HEAD/requirements.txt -------------------------------------------------------------------------------- /LavaMoatExtFix.py: -------------------------------------------------------------------------------- 1 | import time 2 | from termcolor import cprint 3 | import traceback 4 | import os 5 | import string 6 | import platform 7 | import getpass 8 | 9 | 10 | def path_to_ads_folder(): 11 | # Определение ОС пользователя 12 | if platform.system() == 'Darwin': 13 | # Mac operating system 14 | folder_name = "adspower_global/cwd_global/source" 15 | username = getpass.getuser() 16 | path = os.path.join("/Users/", username + "/Library/Application Support/", folder_name) 17 | if os.path.exists(path): 18 | return path 19 | 20 | else: 21 | # Other operating systems (Windows) 22 | drives = [drive for drive in string.ascii_uppercase if os.path.exists(drive + ":")] 23 | folder_name = ".ADSPOWER_GLOBAL" 24 | for drive in drives: 25 | path = drive + ":" + "\\" + folder_name 26 | if os.path.exists(os.path.join(path)): 27 | return path 28 | 29 | 30 | def runtime_lavamoat_editor(path): 31 | with open(path, 'r', encoding="utf-8") as read: 32 | lines = read.readlines() 33 | 34 | # Изменяет переменную scuttleGlobalThis на значение false 35 | with open(path, 'w', encoding="utf-8") as read: 36 | for line in lines: 37 | if line.startswith(' } = {"scuttleGlobalThis":true,"scuttleGlobalThisExceptions":["toString","getComputedStyle","addEventListener","removeEventListener","ShadowRoot","HTMLElement","Element","pageXOffset","pageYOffset","visualViewport","Reflect","Set","Object","navigator","harden","console","location","/cdc_[a-zA-Z0-9]+_[a-zA-Z]+/iu","performance","parseFloat","innerWidth","innerHeight","Symbol","Math","DOMRect","Number","Array","crypto","Function","Uint8Array","String","Promise","__SENTRY__","appState","extra","stateHooks","sentryHooks","sentry"]}'): 38 | line = ' } = {"scuttleGlobalThis":false,"scuttleGlobalThisExceptions":["toString","getComputedStyle","addEventListener","removeEventListener","ShadowRoot","HTMLElement","Element","pageXOffset","pageYOffset","visualViewport","Reflect","Set","Object","navigator","harden","console","location","/cdc_[a-zA-Z0-9]+_[a-zA-Z]+/iu","performance","parseFloat","innerWidth","innerHeight","Symbol","Math","DOMRect","Number","Array","crypto","Function","Uint8Array","String","Promise","__SENTRY__","appState","extra","stateHooks","sentryHooks","sentry"]}' 39 | read.write(line) 40 | 41 | 42 | if __name__ == '__main__': 43 | 44 | try: 45 | path_from_ads_settings = path_to_ads_folder() 46 | if path_from_ads_settings is None: 47 | raise FileNotFoundError 48 | 49 | path_to_js = fr'{path_from_ads_settings}/extension/19657/3f78540a9170bc1d87c525f061d1dd0f/10.26.2_0/runtime-lavamoat.js' 50 | runtime_lavamoat_editor(path_to_js) 51 | cprint(f'Фикс применен/fix applied', 'green') 52 | 53 | except FileNotFoundError: 54 | cprint(f'Файл не найден. Проверьте путь/наличие файла или обратитесь к разработчику.', 'red') 55 | 56 | except Exception as ex: 57 | traceback.print_exc() 58 | time.sleep(.3) 59 | cprint(f'Unexpected error. Обратитесь к разработчику.', 'red') 60 | 61 | # ====================================================================================================================== 62 | # Created by Desti 63 | # ====================================================================================================================== 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # adspower-import-metamask-rework 2 | ![Python](https://img.shields.io/badge/Python-3.7%20%7C%203.8%20%7C%203.9%20%7C%203.10-blue?style=flat-square) 3 | ![Supports](https://img.shields.io/badge/Python-Windows%20%7C%20MacOS-brightgreen?style=flat-square) 4 | ![Metamask](https://img.shields.io/badge/Metamask-10.26.2-orange?style=flat-square) 5 | ___ 6 | #### Изменения 03.05 commit: 7 | 8 | * Изменена функция отображения тестовых сетей 9 | * Добавлены небольшие улучшения 10 | 11 | #### Изменения 27.04 commit: 12 | 13 | * Добавлена функция отображения тестовых сетей 14 | * Исправлен баг с незакрывающейся панелью после добавления сети 15 | ___ 16 | 17 | 18 | 19 | #### Описание режимов работы: 20 | 1. Скрипт импортирует созданные метамаски в готовые профили в Adspower.
21 | После импорта он добавляет сети Optimism, BSC, Polygon, Arbitrum, Zksync Era, Arbitrum Nova, Avalanche, Gnosis Chain, Fantom и Aurora в кошелек. 22 | Заменяет уже добавленые метамаски на новые. Сети сохраняются. 23 | 2. Режим подготовки профилей к работе. Открывает профили и разблокирует метамаски. 24 | 25 | ___ 26 | #### Для установки необходимых библиотек пропиши в терминал: 27 | ``` 28 | pip install -r requirements.txt 29 | ``` 30 | ___ 31 | ### LavaMoat Fixed :white_check_mark: 32 | 33 | Этот фикс отключает LavaMoat путем изменения переменной **scuttleGlobalThis** в файле run-time.js 34 | 35 | 36 | В фиксе присутствуют 2 основных файла: 37 | * LavaMoatExtFix.py 38 | * LavaMoatProfileCacheFix.py 39 | 40 | 41 | 42 | **LavaMoatExtFix.py** - предназначен для изменения файла run-time.js в условном "корневом" каталоге расширения Metamask, скаченным Adspower. Позваляет создавать профили с **отключенным** LavaMoat. 43 | 44 | 45 | **LavaMoatProfileCacheFix.py** - предназначен для изменения файла run-time.js в уже созданном профиле. 46 | 47 | 48 | **Запуск LavaMoatExtFix.py** 49 | 1. Запустите скрипт. 50 | * При успешном применении вы увидите: 51 | 52 | ``` 53 | Фикс применен/fix applied. 54 | ``` 55 | 56 | 57 | **Запуск LavaMoatProfileCacheFix.py** 58 | 1. Добавьте id профилей в файл id_users.txt (каждый с новой строки) 59 | 2. Запустите скрипт. 60 | 61 | * При успешном применении вы увидите: 62 | 63 | ``` 64 | 1. < {ads_id} > fixed # Изменения применены 65 | 66 | 2. < {ads_id} > already fixed # Изменения уже были применены 67 | ``` 68 | * Возможный исход: 69 | ``` 70 | 3. < {ads_id} > cache not found or wrong id 71 | ``` 72 | Отсутвие кэша профиля или неверный ID профиля. Данный сценарий присущ новосозданным профилям, которые ниразу не запускались. 73 | В этом нет ничего страшного, если ID профиля верен. Можете запускать main.py . 74 | 75 | ___ 76 | 77 | 78 | 79 | ### Исктрукция для скрипта импорта :man_technologist: :rocket: 80 | 1. Экспортируй ids из adspower со своих профилей 81 | 2. Добавь эти ids в файл id_users.txt (каждый с новой строки) 82 | 3. Добавь сид-фразы от заранее созданных кошельков в файл seeds.txt (каждый с новой строки) 83 | 4. По желанию в файле main.py измени переменную password (по умолчанию=password123) 84 | 5. По желанию вы можете закомментировать ненужные для добавления сети 85 | 6. Запусти Adspower 86 | 7. Запусти файл main.py 87 | 88 | 89 | 90 | **Возможные режимы работы:** 91 | 92 | | Переменная | Значение | Режим работы | 93 | |:-------------:|:----------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 94 | | unlock_mode | 0 | Импортирует сид-фразы в созданные профиля, если в профиле уже имеется авторизованный метамаск, он будет заменен на новый через fargot password. | 95 | | unlock_mode | 1 | Режим предназначен для подготовки профилей к работе.
Запускает профиль и входит в метамаск, при этом окно профиля закрываться не будет.
Не требует заполнения файла seeds.txt | 96 | 97 | ### FAQ 98 | 1. Если у вас не прогружается Metamask, попробуйте отключить/изменить прокси. 99 | 2. Если у вас не прогружаются сети, попробуйте изменить rpc проблемной сети или отключить/изменить прокси. 100 | 101 | Если у вас что-то не получается или возникают ошибки, обратитесь к разработчику. Буду рад помочь :alien: 102 | 103 | ### Поддержка :heart: 104 | Btc : bc1qwjv6rlkwhj3ft0ejzq8ntdcw455gfmzupstgte
105 | Eth : 0xbF7534d0e8A048a6b621c7DA1db65b4b866718E4
106 | Arb : 0xbF7534d0e8A048a6b621c7DA1db65b4b866718E4
107 | USDT  trc20   :   TFyu4aPm8jHU68pZwJjSwN4r72X8hEvnV3
108 | BUSD  bep20 :   0xbF7534d0e8A048a6b621c7DA1db65b4b866718E4
109 | 110 | ### Rework by *[Desti](https://t.me/ddest1)* 111 | #### Автор оригинального скрипта ***[Zaivanza](https://t.me/zaivanza)*** 112 | #### При поддержке канала *[hodlmod.eth](https://t.me/hodlmodeth)* 113 | -------------------------------------------------------------------------------- /LavaMoatProfileCacheFix.py: -------------------------------------------------------------------------------- 1 | import time, os, sys 2 | from termcolor import cprint 3 | import glob 4 | import traceback 5 | import os 6 | import string 7 | import platform 8 | import getpass 9 | 10 | 11 | def line_control(file_txt): 12 | # Удаление пустых строк 13 | with open(file_txt) as f1: 14 | lines = f1.readlines() 15 | non_empty_lines = (line for line in lines if not line.isspace()) 16 | with open(file_txt, "w") as n_f1: 17 | n_f1.writelines(non_empty_lines) 18 | 19 | 20 | def path_to_ads_folder(): 21 | # Определение ОС пользователя 22 | if platform.system() == 'Darwin': 23 | # Mac operating system 24 | folder_name = "adspower_global/cwd_global/source" 25 | username = getpass.getuser() 26 | path = os.path.join("/Users/", username + "/Library/Application Support/", folder_name) 27 | if os.path.exists(path): 28 | return path 29 | 30 | else: 31 | # Other operating systems (Windows) 32 | drives = [drive for drive in string.ascii_uppercase if os.path.exists(drive + ":")] 33 | folder_name = ".ADSPOWER_GLOBAL" 34 | for drive in drives: 35 | path = drive + ":" + "\\" + folder_name 36 | if os.path.exists(os.path.join(path)): 37 | return path 38 | 39 | 40 | def cache_folder_exist(): 41 | path_to_cache = path_from_ads_settings + r"/cache" 42 | if os.path.exists(path_to_cache): 43 | return 44 | else: 45 | return 0 46 | 47 | 48 | def get_profile_cache_path(ads_id, path_from_ads_settings): 49 | folder_path = glob.glob(fr"{path_from_ads_settings}/cache/{ads_id}*") 50 | 51 | if folder_path: 52 | path_to_profile = folder_path[0].replace("\\", "/") 53 | path = fr'{path_to_profile}/extensionCenter/3f78540a9170bc1d87c525f061d1dd0f/10.26.2_0/runtime-lavamoat.js' 54 | else: 55 | return 0 56 | return path 57 | 58 | 59 | def runtime_lavamoat_cache_editor(path): 60 | 61 | with open(path, 'r', encoding="utf-8") as read: 62 | lines = read.readlines() 63 | 64 | key_edt = False 65 | # Изменяет переменную scuttleGlobalThis на значение false 66 | with open(path, 'w', encoding="utf-8") as read: 67 | for line in lines: 68 | if line.startswith(' } = {"scuttleGlobalThis":true,"scuttleGlobalThisExceptions":["toString","getComputedStyle","addEventListener","removeEventListener","ShadowRoot","HTMLElement","Element","pageXOffset","pageYOffset","visualViewport","Reflect","Set","Object","navigator","harden","console","location","/cdc_[a-zA-Z0-9]+_[a-zA-Z]+/iu","performance","parseFloat","innerWidth","innerHeight","Symbol","Math","DOMRect","Number","Array","crypto","Function","Uint8Array","String","Promise","__SENTRY__","appState","extra","stateHooks","sentryHooks","sentry"]}'): 69 | line = ' } = {"scuttleGlobalThis":false,"scuttleGlobalThisExceptions":["toString","getComputedStyle","addEventListener","removeEventListener","ShadowRoot","HTMLElement","Element","pageXOffset","pageYOffset","visualViewport","Reflect","Set","Object","navigator","harden","console","location","/cdc_[a-zA-Z0-9]+_[a-zA-Z]+/iu","performance","parseFloat","innerWidth","innerHeight","Symbol","Math","DOMRect","Number","Array","crypto","Function","Uint8Array","String","Promise","__SENTRY__","appState","extra","stateHooks","sentryHooks","sentry"]}' 70 | key_edt = True 71 | read.write(line) 72 | 73 | return key_edt 74 | 75 | 76 | if __name__ == '__main__': 77 | 78 | path_from_ads_settings = path_to_ads_folder() 79 | if path_from_ads_settings is None: 80 | cprint(f'Adspower не установлен/Не найден путь. Обратитесь к разрабочику', 'red') 81 | sys.exit(0) 82 | if cache_folder_exist() == 0: 83 | cprint(f'Папка /Cache/ не была обнаружена. Обратитесь к разрабочику', 'red') 84 | sys.exit(0) 85 | 86 | line_control("id_users.txt") 87 | with open("id_users.txt", "r") as f: 88 | id_users = [row.strip() for row in f] 89 | 90 | i = 0 91 | for ads_id in id_users: 92 | i += 1 93 | 94 | try: 95 | path = get_profile_cache_path(ads_id, path_from_ads_settings) 96 | if path == 0: 97 | cprint(f'{i}. < {ads_id} > cache not found or wrong id', 'yellow') 98 | continue 99 | key_edt = runtime_lavamoat_cache_editor(path) 100 | if key_edt is True: 101 | cprint(f'{i}. < {ads_id} > fixed', 'green') 102 | elif key_edt is False: 103 | cprint(f'{i}. < {ads_id} > already fixed', 'green') 104 | 105 | except FileNotFoundError: 106 | # traceback.print_exc() 107 | # time.sleep(.3) 108 | cprint(f'{i}. < {ads_id} > runtime-lavamoat.js not found', 'red') 109 | 110 | except Exception as ex: 111 | traceback.print_exc() 112 | time.sleep(.3) 113 | cprint(f'{i}. < {ads_id} > Unexpected error. Обратитесь к разработчику.', 'red') 114 | 115 | # ====================================================================================================================== 116 | # Created by Desti 117 | # ====================================================================================================================== 118 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import requests, time, sys 2 | from selenium import webdriver 3 | from selenium.webdriver.chrome.options import Options 4 | from selenium.webdriver.common.by import By 5 | from selenium.webdriver.common.action_chains import ActionChains 6 | from selenium.webdriver.support import expected_conditions as EC 7 | from selenium.webdriver.support.ui import WebDriverWait 8 | from selenium.webdriver.common.keys import Keys 9 | from selenium.webdriver.chrome.service import Service 10 | from selenium.common.exceptions import WebDriverException 11 | from selenium.common.exceptions import TimeoutException 12 | from termcolor import cprint 13 | import pyperclip 14 | import platform 15 | import traceback 16 | 17 | def clickOnXpath(driver, wait_time, str_path): 18 | WebDriverWait(driver, wait_time).until(EC.element_to_be_clickable((By.XPATH, str_path))).click() 19 | 20 | def clickOnClassName(driver, wait_time, str_path): 21 | WebDriverWait(driver, wait_time).until(EC.element_to_be_clickable((By.CLASS_NAME, str_path))).click() 22 | 23 | def clickOnID(driver, wait_time, str_path): 24 | WebDriverWait(driver, wait_time).until(EC.element_to_be_clickable((By.ID, str_path))).click() 25 | 26 | def inputTextXpath(driver, wait_time, send_data, str_path): 27 | WebDriverWait(driver, wait_time).until(EC.element_to_be_clickable((By.XPATH, str_path))).send_keys(send_data) 28 | 29 | def inputTextName(driver, wait_time, send_data, str_path): 30 | WebDriverWait(driver, wait_time).until(EC.element_to_be_clickable((By.NAME, str_path))).send_keys(send_data) 31 | 32 | def inputTextClassName(driver, wait_time, send_data, str_path): 33 | WebDriverWait(driver, wait_time).until(EC.element_to_be_clickable((By.CLASS_NAME, str_path))).send_keys(send_data) 34 | 35 | def inputTextByID(driver, wait_time, send_data, str_path): 36 | WebDriverWait(driver, wait_time).until(EC.element_to_be_clickable((By.ID, str_path))).send_keys(send_data) 37 | 38 | def waitElementXpath(driver, wait_time, str_path): 39 | WebDriverWait(driver, wait_time).until(EC.presence_of_element_located((By.XPATH, str_path))) 40 | 41 | def waitElementID(driver, wait_time, str_path): 42 | WebDriverWait(driver, wait_time).until(EC.presence_of_element_located((By.ID, str_path))) 43 | 44 | 45 | # Onboard Page 46 | XPATH_ONBOARDING_IMPORT_WALLET = '//*[@data-testid="onboarding-import-wallet"]' 47 | XPATH_ONBOARDING_NO_METRIC = '//*[@data-testid="metametrics-no-thanks"]' 48 | XPATH_CONFIRM_MNEMONIC = '//*[@data-testid="import-srp-confirm"]' 49 | XPATH_INPUT_PASS = '//*[@data-testid="create-password-new"]' 50 | XPATH_INPUT_PASS_CNFRM = '//*[@data-testid="create-password-confirm"]' 51 | XPATH_INPUT_TERMS = '//*[@data-testid="create-password-terms"]' 52 | XPATH_CREATE_NEW_WALLET = '//*[@data-testid="create-password-import"]' 53 | XPATH_ONBOARDING_DONE = '//*[@data-testid="onboarding-complete-done"]' 54 | XPATH_PIN_EXT_NEXT = '//*[@data-testid="pin-extension-next"]' 55 | XPATH_PIN_EXT_DONE = '//*[@data-testid="pin-extension-done"]' 56 | XPATH_ETH_DISPLAYED = '//*[@data-testid="eth-overview__primary-currency"]' 57 | XPATH_SECONDARY_BTN = '//*[@class="button btn--rounded btn-secondary"]' 58 | 59 | # Forgot Pass Page 60 | XPATH_FORGOT_PASS = '//*[@class="button btn-link unlock-page__link"]' 61 | XPATH_SUBMIT_BTN = '//*[@class="button btn--rounded btn-primary create-new-vault__submit-button"]' 62 | XPATH_PONYATNO_BTN = '//*[@class="button btn--rounded btn-primary"]' 63 | 64 | # Unlock 65 | XPATH_INPUT_UNLOCK_PASS = '//*[@data-testid="unlock-password"]' 66 | XPATH_UNLOCK = '//*[@data-testid="unlock-submit"]' 67 | 68 | XPATH_INPUTS_MNEMONIC = '//*[@class="MuiInputBase-input MuiInput-input"]' 69 | XPATH_POPOVER_CLOSE = '//*[@data-testid="popover-close"]' 70 | XPATH_SHOW_TEST_NETWORKS = '//*[@data-testid="advanced-setting-show-testnet-conversion"]' 71 | 72 | 73 | networks = { 74 | 'Optimism': { 75 | 'net_name': 'Optimism', 76 | 'rpc': 'https://mainnet.optimism.io', 77 | 'chain_id': 10, 78 | 'symbol': 'ETH', 79 | 'explorer': 'https://optimistic.etherscan.io/', 80 | }, 81 | 82 | 'Arbitrum': { 83 | 'net_name': 'Arbitrum One', 84 | 'rpc': 'https://arb1.arbitrum.io/rpc', 85 | 'chain_id': 42161, 86 | 'symbol': 'ETH', 87 | 'explorer': 'https://arbiscan.io/', 88 | }, 89 | 90 | 'BSC': { 91 | 'net_name': 'Smart Chain', 92 | 'rpc': 'https://bsc-dataseed.binance.org/', 93 | 'chain_id': 56, 94 | 'symbol': 'BNB', 95 | 'explorer': 'https://bscscan.com', 96 | }, 97 | 98 | 'Polygon': { 99 | 'net_name': 'Polygon', 100 | 'rpc': 'https://polygon-rpc.com', 101 | 'chain_id': 137, 102 | 'symbol': 'MATIC', 103 | 'explorer': 'https://polygonscan.com/', 104 | }, 105 | 106 | 'Zksync Era': { 107 | 'net_name': 'zkSync Era Mainnet', 108 | 'rpc': 'https://mainnet.era.zksync.io', 109 | 'chain_id': 324, 110 | 'symbol': 'ETH', 111 | 'explorer': 'https://explorer.zksync.io/', 112 | }, 113 | 114 | 'Arbitrum Nova': { 115 | 'net_name': 'Arbitrum Nova', 116 | 'rpc': 'https://nova.arbitrum.io/rpc', 117 | 'chain_id': 42170, 118 | 'symbol': 'ETH', 119 | 'explorer': 'https://nova-explorer.arbitrum.io', 120 | }, 121 | 122 | 'Avalanche': { 123 | 'net_name': 'Avalanche Network C-Chain', 124 | 'rpc': 'https://api.avax.network/ext/bc/C/rpc', 125 | # 'rpc': 'https://avalanche-mainnet.infura.io', 126 | 'chain_id': 43114, 127 | 'symbol': 'AVAX', 128 | 'explorer': 'https://snowtrace.io/', 129 | }, 130 | 131 | 'Gnosis Chain': { 132 | 'net_name': 'Gnosis Chain', 133 | 'rpc': 'https://rpc.gnosischain.com', 134 | 'chain_id': 100, 135 | 'symbol': 'xDai', 136 | 'explorer': 'https://blockscout.com/xdai/mainnet/', 137 | }, 138 | 139 | 'Fantom': { 140 | 'net_name': 'Fantom', 141 | 'rpc': 'https://rpc.ftm.tools/', 142 | 'chain_id': 250, 143 | 'symbol': 'FTM', 144 | 'explorer': 'https://ftmscan.com/', 145 | }, 146 | 147 | 'Aurora': { 148 | 'net_name': 'Aurora Mainnet', 149 | 'rpc': 'https://mainnet.aurora.dev', 150 | # 'rpc': 'https://aurora-mainnet.infura.io', 151 | 'chain_id': 1313161554, 152 | 'symbol': 'ETH', 153 | 'explorer': 'https://explorer.aurora.dev/', 154 | } 155 | } 156 | 157 | 158 | def line_control(file_txt): 159 | # Удаление пустых строк 160 | with open(file_txt) as f1: 161 | lines = f1.readlines() 162 | non_empty_lines = (line for line in lines if not line.isspace()) 163 | with open(file_txt, "w") as n_f1: 164 | n_f1.writelines(non_empty_lines) 165 | 166 | 167 | def show_test_networks(driver): 168 | try: 169 | driver.get('chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/home.html#settings/advanced') 170 | waitElementXpath(driver, 1.5, XPATH_SHOW_TEST_NETWORKS) 171 | el_1 = driver.find_elements(By.XPATH, XPATH_SHOW_TEST_NETWORKS) 172 | ActionChains(driver).move_to_element(el_1[0]).perform() 173 | el_toggle = el_1[1].find_elements(By.XPATH, "*") 174 | el_toggle[1].click() 175 | except Exception: 176 | cprint(f'< {ads_id} > test networks not added', 'white') 177 | 178 | 179 | def add_network(driver, name_network): 180 | 181 | def info_panel_closer(await_time): 182 | # Закрытие панели после добавления сети 183 | try: 184 | time.sleep(.5) 185 | WebDriverWait(driver, await_time).until(EC.element_to_be_clickable((By.XPATH, XPATH_POPOVER_CLOSE))) # krestik btn 186 | time.sleep(.5) 187 | driver.find_element(By.XPATH, XPATH_POPOVER_CLOSE).click() 188 | time.sleep(.5) 189 | except Exception: 190 | pass 191 | 192 | try: 193 | xpatch = '/html/body/div[1]/div/div[3]/div/div[2]/div[2]/div/div[2]/div/div[2]/div' 194 | 195 | driver.get('chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/home.html#settings/networks/add-network') 196 | info_panel_closer(.7) 197 | inputTextXpath(driver, 5, networks[name_network]['net_name'], f'{xpatch}[1]/label/input') # name 198 | inputTextXpath(driver, 5, networks[name_network]['rpc'], f'{xpatch}[2]/label/input') # new_rpc 199 | inputTextXpath(driver, 5, networks[name_network]['chain_id'], f'{xpatch}[3]/label/input') # chain 200 | inputTextXpath(driver, 5, networks[name_network]['symbol'], f'{xpatch}[4]/label/input') # currency_symbol 201 | inputTextXpath(driver, 5, networks[name_network]['explorer'], f'{xpatch}[5]/label/input') # explorer_url 202 | # save 203 | q = 0 204 | while True: 205 | try: 206 | time.sleep(.5) 207 | clickOnXpath(driver, 3, XPATH_PONYATNO_BTN) # Save button 208 | break 209 | except: 210 | time.sleep(.5) 211 | driver.find_element(By.XPATH, f'{xpatch}[5]/label/input').clear() 212 | time.sleep(.5) 213 | inputTextXpath(driver, 5, networks[name_network]['explorer'], f'{xpatch}[5]/label/input') 214 | time.sleep(.5) 215 | q += 1 216 | if q >= 6: 217 | raise 218 | info_panel_closer(2) 219 | except Exception: 220 | cprint(f'network < {name_network} > network not added', 'white') 221 | 222 | 223 | def fill_seed(driver, seed): 224 | # Filling in text phrase fields 225 | waitElementID(driver, 8, 'import-srp__srp-word-0') 226 | driver.find_element(By.XPATH, XPATH_INPUTS_MNEMONIC).click() 227 | 228 | # Определение ОС пользователя 229 | if platform.system() == 'Darwin': 230 | # Mac operating system 231 | pyperclip.copy(seed) 232 | ActionChains(driver).key_down(u'\ue03d').send_keys('v').key_up(u'\ue03d').perform() 233 | else: 234 | # Other operating systems 235 | pyperclip.copy(seed) 236 | ActionChains(driver).key_down(Keys.CONTROL).send_keys('v').key_up(Keys.CONTROL).perform() 237 | 238 | 239 | def onboard_page(driver, seed, password): 240 | # ##################################Login MetaMask version 10.26.2################################################## 241 | clickOnXpath(driver, 12, XPATH_ONBOARDING_IMPORT_WALLET) # Import exist wallet 242 | clickOnXpath(driver, 5, XPATH_ONBOARDING_NO_METRIC) # No metric button 243 | fill_seed(driver, seed) # Input seed phrase 244 | clickOnXpath(driver, 5, XPATH_CONFIRM_MNEMONIC) # Confirm a seed phrase 245 | inputTextXpath(driver, 5, password, XPATH_INPUT_PASS) 246 | inputTextXpath(driver, 5, password, XPATH_INPUT_PASS_CNFRM) 247 | clickOnXpath(driver, 5, XPATH_INPUT_TERMS) # Terms checkbox 248 | clickOnXpath(driver, 5, XPATH_CREATE_NEW_WALLET) # Import wallet btn 249 | 250 | svg_spinner = WebDriverWait(driver, 10).until( 251 | EC.presence_of_element_located((By.CLASS_NAME, "lds-spinner"))) 252 | WebDriverWait(driver, 30).until( 253 | EC.invisibility_of_element_located(svg_spinner)) # Waiting for svg_spinner to disappear 254 | 255 | clickOnXpath(driver, 30, XPATH_ONBOARDING_DONE) # Got it button 256 | clickOnXpath(driver, 30, XPATH_PIN_EXT_NEXT) # Next button 257 | clickOnXpath(driver, 7, XPATH_PIN_EXT_DONE) # Done button 258 | 259 | # =================================== if you don't need to add a networks, comment everything below ================ 260 | waitElementXpath(driver, 7, XPATH_ETH_DISPLAYED) # wait_elem ETH display 261 | show_test_networks(driver) # Enables display of test networks 262 | add_network(driver, 'BSC') 263 | add_network(driver, 'Polygon') 264 | add_network(driver, 'Optimism') 265 | add_network(driver, 'Arbitrum') 266 | add_network(driver, 'Zksync Era') 267 | add_network(driver, 'Arbitrum Nova') 268 | add_network(driver, 'Avalanche') 269 | add_network(driver, 'Gnosis Chain') 270 | add_network(driver, 'Fantom') 271 | add_network(driver, 'Aurora') 272 | # ================================================================================================================== 273 | 274 | # For Metamask 10.29.0 275 | try: 276 | clickOnXpath(driver, 0.7, XPATH_SECONDARY_BTN) # Dismiss button 277 | except Exception: 278 | pass 279 | # ################################################################################################################## 280 | 281 | 282 | def forgot_password_page(driver, seed, password): 283 | # ##################################Forgot Pass MetaMask version 10.26.2############################################ 284 | clickOnXpath(driver, 7, XPATH_FORGOT_PASS) # Forgot Pass Btn 285 | fill_seed(driver, seed) # Fills in the seed phrase and password fields 286 | inputTextByID(driver, 5, password, 'password') 287 | inputTextByID(driver, 5, password, 'confirm-password') 288 | clickOnXpath(driver, 7, XPATH_SUBMIT_BTN) # Recover button 289 | try: 290 | clickOnXpath(driver, 2.5, XPATH_PONYATNO_BTN) # Got it button 291 | time.sleep(.5) 292 | except Exception: 293 | pass 294 | 295 | # ################################################################################################################## 296 | 297 | 298 | def mode_selector(driver): 299 | try: 300 | waitElementXpath(driver, 3, XPATH_ONBOARDING_IMPORT_WALLET) 301 | return True 302 | except Exception: 303 | return False 304 | 305 | 306 | def main(zero, ads_id, seed, password, unlock_mode): 307 | try: 308 | args1 = ["--disable-popup-blocking", "--window-position=700,0"] 309 | args1 = str(args1).replace("'", '"') 310 | 311 | open_url = f"http://local.adspower.net:50325/api/v1/browser/start?user_id=" + ads_id + f"&launch_args={str(args1)}" 312 | close_url = "http://local.adspower.net:50325/api/v1/browser/stop?user_id=" + ads_id 313 | 314 | try: 315 | # Отправка запроса на открытие профиля 316 | resp = requests.get(open_url).json() 317 | time.sleep(.5) 318 | except requests.exceptions.ConnectionError: 319 | cprint(f'Adspower is not running.', 'red') 320 | sys.exit(0) 321 | except requests.exceptions.JSONDecodeError: 322 | cprint(f'Проверьте ваше подключение. Отключите VPN/Proxy используемые напрямую.', 'red') 323 | sys.exit(0) 324 | 325 | while True: 326 | try: 327 | chrome_driver = resp["data"]["webdriver"] 328 | chrome_options = Options() 329 | chrome_options.add_experimental_option("debuggerAddress", resp["data"]["ws"]["selenium"]) 330 | driver = webdriver.Chrome(service=Service(chrome_driver), options=chrome_options) 331 | break 332 | except KeyError: 333 | # Перезапуск профиля для попытки устраниения ошибки открытия 334 | try: 335 | requests.get(open_url).json() 336 | time.sleep(3) 337 | requests.get(close_url).json() 338 | except Exception: 339 | cprint(f'{ads_id} - profile opening error', 'red') 340 | break 341 | except Exception: 342 | cprint(f'{ads_id} - profile opening error', 'red') 343 | driver.quit() 344 | requests.get(close_url) 345 | break 346 | 347 | url = 'chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/home.html' 348 | 349 | time.sleep(2.3) 350 | driver.switch_to.new_window() 351 | time.sleep(.5) 352 | driver.get(url) 353 | time.sleep(.5) 354 | driver.refresh() 355 | time.sleep(.9) 356 | 357 | # ============================================================================================================== 358 | # Выбор режима 359 | mode_bool = mode_selector(driver) 360 | if mode_bool is True: 361 | onboard_page(driver, seed, password) 362 | elif mode_bool is False: 363 | if unlock_mode == 0: 364 | forgot_password_page(driver, seed, password) 365 | elif unlock_mode == 1: 366 | inputTextXpath(driver, 5, password, XPATH_INPUT_UNLOCK_PASS) 367 | clickOnXpath(driver, 5, XPATH_UNLOCK) 368 | 369 | try: 370 | for q in range(3): 371 | clickOnXpath(driver, 2, XPATH_POPOVER_CLOSE) # Close popover windows 372 | except Exception: 373 | pass 374 | # ============================================================================================================== 375 | 376 | if unlock_mode == 0: 377 | driver.quit() 378 | requests.get(close_url) 379 | 380 | cprint(f'{zero + 1}. {ads_id} - done', 'green') 381 | 382 | except TimeoutException as ex1: 383 | # traceback.print_exc() 384 | time.sleep(.3) 385 | cprint(f'Profile < {ads_id} > has TimeOut Error. Please contact the developer.', 'red') 386 | driver.quit() 387 | requests.get(close_url) 388 | 389 | except WebDriverException as ex: 390 | if 'LavaMoat' in str(ex): 391 | cprint(f'Profile < {ads_id} > has LavaMoat Error. Please use fix scripts.', 'red') 392 | else: 393 | traceback.print_exc() 394 | time.sleep(.3) 395 | cprint(f'WebDriverException Error. Please contact the developer.', 'red') 396 | driver.quit() 397 | requests.get(close_url) 398 | 399 | except Exception as ex: 400 | traceback.print_exc() 401 | time.sleep(.3) 402 | cprint(f'{zero + 1}. {ads_id} = already done', 'yellow') 403 | driver.quit() 404 | requests.get(close_url) 405 | 406 | 407 | if __name__ == '__main__': 408 | 409 | line_control("id_users.txt") 410 | line_control("seeds.txt") 411 | 412 | with open("id_users.txt", "r") as f: 413 | id_users = [row.strip() for row in f] 414 | 415 | with open("seeds.txt", "r") as f: 416 | seeds = [row.strip() for row in f] 417 | 418 | # ===========================================Settings=============================================================== 419 | # Change the metamask password here 420 | password = 'password123' 421 | 422 | # 0 - The unlock mode is disabled. If you need to replace some metamask wallets in your profiles. 423 | # 1 - Enters the metamask wallet, using the password from the password variable. 424 | # The variable in unlock mode - 1 is designed to prepare profiles for operation, in this value the profiles 425 | # will NOT be closed automatically! 426 | unlock_mode = 0 427 | # ================================================================================================================== 428 | 429 | for i, ads_id in enumerate(id_users): 430 | try: 431 | if unlock_mode == 1: 432 | seeds.append('blank') 433 | main(i, ads_id, seeds[i], password, unlock_mode) 434 | except IndexError as ex: 435 | cprint(f'\nCheck the correspondence of the number of seed phrases with ' 436 | f'the number of profiles in the files id_users.txt and seeds.txt', 'red') 437 | sys.exit(0) 438 | except Exception as ex: 439 | cprint(str(ex), 'red') 440 | 441 | 442 | # ====================================================================================================================== 443 | # Reworked by Desti 444 | # ====================================================================================================================== 445 | --------------------------------------------------------------------------------