├── 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 | 
3 | 
4 | 
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 |
--------------------------------------------------------------------------------