getsourcecode 2.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- getsourcecode/__init__.py +74 -0
- getsourcecode/check.py +22 -0
- getsourcecode/common.py +69 -0
- getsourcecode/config.py +175 -0
- getsourcecode/filter.py +169 -0
- getsourcecode/handle.py +427 -0
- getsourcecode/keys.py +28 -0
- getsourcecode/menu.py +43 -0
- getsourcecode-2.1.0.dist-info/LICENSE +201 -0
- getsourcecode-2.1.0.dist-info/METADATA +234 -0
- getsourcecode-2.1.0.dist-info/RECORD +14 -0
- getsourcecode-2.1.0.dist-info/WHEEL +5 -0
- getsourcecode-2.1.0.dist-info/entry_points.txt +2 -0
- getsourcecode-2.1.0.dist-info/top_level.txt +1 -0
getsourcecode/handle.py
ADDED
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
from audioop import add
|
|
2
|
+
import json
|
|
3
|
+
import base64
|
|
4
|
+
import requests
|
|
5
|
+
from getsourcecode.common import *
|
|
6
|
+
from getsourcecode.config import *
|
|
7
|
+
from getsourcecode.keys import get_key
|
|
8
|
+
from retrying import retry
|
|
9
|
+
import certifi
|
|
10
|
+
|
|
11
|
+
def check_is_duplicate_file(file_path, contract_code):
|
|
12
|
+
if hash_file(file_path) == hash_string(contract_code):
|
|
13
|
+
return True
|
|
14
|
+
return False
|
|
15
|
+
|
|
16
|
+
def save_info(address, contract_name):
|
|
17
|
+
try:
|
|
18
|
+
if address not in contract_info.keys():
|
|
19
|
+
contract_info[address] = contract_name
|
|
20
|
+
except Exception as e:
|
|
21
|
+
handle_exception(e)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@retry(stop_max_attempt_number=5, wait_fixed=2000)
|
|
25
|
+
def tron_requests(address, api_url):
|
|
26
|
+
data = {
|
|
27
|
+
"contractAddress": address
|
|
28
|
+
}
|
|
29
|
+
tron_req = requests.post(api_url, data=data, verify=False)
|
|
30
|
+
return tron_req
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def send_tron(addresses, output_folder):
|
|
34
|
+
global contract_index
|
|
35
|
+
global temp_contract_name
|
|
36
|
+
try:
|
|
37
|
+
api_url = "https://apiasia.tronscan.io:5566/api/solidity/contract/info"
|
|
38
|
+
for address in addresses:
|
|
39
|
+
req = tron_requests(address, api_url)
|
|
40
|
+
if json.loads(req.text)["code"] == 200:
|
|
41
|
+
contract_code = json.loads(req.text)["data"]["contract_code"]
|
|
42
|
+
contract_folder = json.loads(req.text)["data"][
|
|
43
|
+
"contract_name"] if output_folder == "" else output_folder
|
|
44
|
+
make_dir(contract_folder)
|
|
45
|
+
sub_index = 0
|
|
46
|
+
save_info(address, json.loads(req.text)["data"]["contract_name"])
|
|
47
|
+
for code in contract_code:
|
|
48
|
+
index = 0
|
|
49
|
+
contract_name = code['name']
|
|
50
|
+
temp_contract_name = contract_name
|
|
51
|
+
code_temp = str(base64.b64decode(code['code']), 'utf-8').replace('\r\n', '\n')
|
|
52
|
+
exist_file =False
|
|
53
|
+
while os.path.exists(contract_folder + "//" + contract_name):
|
|
54
|
+
exist_file = True
|
|
55
|
+
if contract_name.find("_")!= -1:
|
|
56
|
+
contract_name = code['name'].split('_')[0] + "_{}".format(index) + ".sol"
|
|
57
|
+
else:
|
|
58
|
+
contract_name = code['name'].split('.')[0] + "_{}".format(index) + ".sol"
|
|
59
|
+
index += 1
|
|
60
|
+
# Do not process files with duplicate content
|
|
61
|
+
if exist_file and check_is_duplicate_file(contract_folder + "//" + temp_contract_name, code_temp):
|
|
62
|
+
continue
|
|
63
|
+
make_dir(os.path.split(contract_folder + "//" + contract_name)[0])
|
|
64
|
+
with open(contract_folder + "//" + contract_name, "w+", encoding='utf-8') as fw:
|
|
65
|
+
fw.write(code_temp)
|
|
66
|
+
|
|
67
|
+
print(f'{contract_index}-{sub_index}: {contract_folder + "/" + contract_name}'.replace(
|
|
68
|
+
'//', '/'))
|
|
69
|
+
sub_index += 1
|
|
70
|
+
contract_index += 1
|
|
71
|
+
except Exception as e:
|
|
72
|
+
handle_exception(e)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@retry(stop_max_attempt_number=5, wait_fixed=2000)
|
|
76
|
+
def okex_requests(api_url, apikey, proxies):
|
|
77
|
+
head = {
|
|
78
|
+
"X-Apikey": apikey
|
|
79
|
+
}
|
|
80
|
+
okex_req = requests.get(api_url, headers=head, proxies=proxies, verify=False)
|
|
81
|
+
return okex_req
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def send_okex(addresses, output_folder, apikey, network):
|
|
85
|
+
okex_network_api = {
|
|
86
|
+
"okt": "okexchain",
|
|
87
|
+
"okb": "okbc_test",
|
|
88
|
+
"okt-testnet": "okexchain_test"
|
|
89
|
+
}
|
|
90
|
+
global contract_index
|
|
91
|
+
global proxy_contract
|
|
92
|
+
global temp_contract_name
|
|
93
|
+
proxies = get_proxies()
|
|
94
|
+
try:
|
|
95
|
+
for address in addresses:
|
|
96
|
+
api_url = f"https://www.oklink.com/api/explorer/v1/{okex_network_api[network]}/addresses/{address}/contract"
|
|
97
|
+
req = okex_requests(api_url, apikey, proxies)
|
|
98
|
+
if json.loads(req.text)["code"] == 0:
|
|
99
|
+
contractSourceList = json.loads(req.text)["data"]["contractSourceList"]
|
|
100
|
+
contract_main_name = json.loads(req.text)["data"]["name"] if "name" in json.loads(req.text)[
|
|
101
|
+
"data"].keys() else "not_open_source"
|
|
102
|
+
if contractSourceList != []:
|
|
103
|
+
contract_code_list = json.loads(req.text)["data"]["contractSourceList"]
|
|
104
|
+
else:
|
|
105
|
+
contract_code_list = [{
|
|
106
|
+
"name": contract_main_name,
|
|
107
|
+
"source_code": json.loads(req.text)["data"]["contractSource"],
|
|
108
|
+
}]
|
|
109
|
+
contract_folder = contract_main_name if output_folder == "" else output_folder
|
|
110
|
+
make_dir(contract_folder)
|
|
111
|
+
save_info(address, contract_main_name)
|
|
112
|
+
sub_index = 0
|
|
113
|
+
for code in contract_code_list:
|
|
114
|
+
index = 0
|
|
115
|
+
contract_name = code['name'] + ".sol"
|
|
116
|
+
temp_contract_name = contract_name
|
|
117
|
+
code_temp = code['source_code'].replace('\r\n', '\n')
|
|
118
|
+
exist_file = False
|
|
119
|
+
while os.path.exists(contract_folder + "//" + contract_name):
|
|
120
|
+
exist_file = True
|
|
121
|
+
if contract_name.find("_")!= -1:
|
|
122
|
+
contract_name = code['name'].split('_')[0] + "_{}".format(index) + ".sol"
|
|
123
|
+
else:
|
|
124
|
+
contract_name = code['name'].split('.')[0] + "_{}".format(index) + ".sol"
|
|
125
|
+
index += 1
|
|
126
|
+
# Do not process files with duplicate content
|
|
127
|
+
if exist_file and check_is_duplicate_file(contract_folder + "//" + temp_contract_name, code_temp):
|
|
128
|
+
continue
|
|
129
|
+
make_dir(os.path.split(contract_folder + "//" + contract_name)[0])
|
|
130
|
+
with open(contract_folder + "//" + contract_name, "w+", encoding='utf-8') as fw:
|
|
131
|
+
fw.write(code_temp)
|
|
132
|
+
print(f'{contract_index}-{sub_index}: {contract_folder + "/" + contract_name}'.replace('//', '/'))
|
|
133
|
+
sub_index += 1
|
|
134
|
+
contract_index += 1
|
|
135
|
+
impl = ""
|
|
136
|
+
if "implContractAddress" in json.loads(req.text)["data"].keys():
|
|
137
|
+
impl = json.loads(req.text)["data"]["implContractAddress"]
|
|
138
|
+
if impl != "":
|
|
139
|
+
addresses = [impl]
|
|
140
|
+
proxy_contract[address] = impl
|
|
141
|
+
send_okex(addresses, "impl_contract", apikey, network)
|
|
142
|
+
except Exception as e:
|
|
143
|
+
handle_exception(e)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
@retry(stop_max_attempt_number=5, wait_fixed=2000)
|
|
147
|
+
def klaytn_requests(real_url, proxies):
|
|
148
|
+
klaytn_req = requests.get(real_url, proxies=proxies, verify=False)
|
|
149
|
+
return klaytn_req
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def send_klaytn(addresses, output_folder, network):
|
|
153
|
+
global contract_index
|
|
154
|
+
global temp_contract_name
|
|
155
|
+
try:
|
|
156
|
+
proxies = get_proxies()
|
|
157
|
+
for address in addresses:
|
|
158
|
+
if network == "klaytn":
|
|
159
|
+
klaytn_url = f"https://api-cypress.klaytnscope.com/v2/accounts/{address}"
|
|
160
|
+
else:
|
|
161
|
+
klaytn_url = f"https://api-baobab.klaytnscope.com/v2/accounts/{address}"
|
|
162
|
+
req = klaytn_requests(klaytn_url, proxies)
|
|
163
|
+
code = json.loads(req.text)['result']['matchedContract']
|
|
164
|
+
contract_name = code['contractName'] + ".sol"
|
|
165
|
+
temp_contract_name = contract_name
|
|
166
|
+
code_temp = code["contractSource"].replace('\r\n', '\n')
|
|
167
|
+
exist_file = False
|
|
168
|
+
save_info(address, code['contractName'])
|
|
169
|
+
contract_folder = code['contractName'] if output_folder == "" else output_folder
|
|
170
|
+
index = 0
|
|
171
|
+
while os.path.exists(contract_folder + "//" + contract_name):
|
|
172
|
+
exist_file = True
|
|
173
|
+
if contract_name.find("_")!= -1:
|
|
174
|
+
contract_name = code['contractName'].split('_')[0] + "_{}".format(index) + ".sol"
|
|
175
|
+
else:
|
|
176
|
+
contract_name = code['contractName'].split('.')[0] + "_{}".format(index) + ".sol"
|
|
177
|
+
index += 1
|
|
178
|
+
# Do not process files with duplicate content
|
|
179
|
+
if exist_file and check_is_duplicate_file(contract_folder + "//" + temp_contract_name, code_temp):
|
|
180
|
+
continue
|
|
181
|
+
make_dir(os.path.split(contract_folder + "//" + contract_name)[0])
|
|
182
|
+
with open(contract_folder + "//" + contract_name, "w+", encoding='utf-8') as fw:
|
|
183
|
+
fw.write(code_temp)
|
|
184
|
+
print(f'{contract_index}: {contract_folder + "/" + contract_name}'.replace('//', '/'))
|
|
185
|
+
contract_index += 1
|
|
186
|
+
except Exception as e:
|
|
187
|
+
handle_exception(e)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
@retry(stop_max_attempt_number=5, wait_fixed=2000)
|
|
191
|
+
def check_ronin_is_proxy(address, proxies, network):
|
|
192
|
+
header = {
|
|
193
|
+
"User-Agent": USER_AGENT,
|
|
194
|
+
"Content-Type": "application/json"
|
|
195
|
+
}
|
|
196
|
+
if network == "ronin":
|
|
197
|
+
check_proxy_url = f"https://explorer-kintsugi.roninchain.com/v2/2020/contract/{address}"
|
|
198
|
+
else:
|
|
199
|
+
check_proxy_url = f"https://explorer-kintsugi.roninchain.com/v2/2021/contract/{address}"
|
|
200
|
+
check_proxy_req = requests.get(check_proxy_url, proxies=proxies, headers=header, verify=False)
|
|
201
|
+
return check_proxy_req.json()['result']
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
@retry(stop_max_attempt_number=5, wait_fixed=2000)
|
|
205
|
+
def ronin_request(url, proxies):
|
|
206
|
+
header = {
|
|
207
|
+
"User-Agent": USER_AGENT,
|
|
208
|
+
"Content-Type": "application/json"
|
|
209
|
+
}
|
|
210
|
+
ronin_req = requests.get(url, proxies=proxies, headers=header, verify=False)
|
|
211
|
+
return ronin_req.json()
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def send_ronin(addresses, output_folder, network):
|
|
215
|
+
global contract_index
|
|
216
|
+
global proxy_contract
|
|
217
|
+
global temp_contract_name
|
|
218
|
+
try:
|
|
219
|
+
proxies = get_proxies()
|
|
220
|
+
for address in addresses:
|
|
221
|
+
address_info = check_ronin_is_proxy(address, proxies, network)
|
|
222
|
+
proxy_address = address_info["proxy_to"]
|
|
223
|
+
contract_name = address_info["contract_name"]
|
|
224
|
+
temp_contract_name = contract_name
|
|
225
|
+
if network == "ronin":
|
|
226
|
+
url = f"https://explorer-kintsugi.roninchain.com/v2/2020/contract/{address}/src"
|
|
227
|
+
else:
|
|
228
|
+
url = f"https://explorer-kintsugi.roninchain.com/v2/2021/contract/{address}/src"
|
|
229
|
+
ronin_req = ronin_request(url, proxies)
|
|
230
|
+
save_info(address, contract_name)
|
|
231
|
+
contract_folder = contract_name if output_folder == "" else output_folder
|
|
232
|
+
index = 0
|
|
233
|
+
sub_index = 0
|
|
234
|
+
for code in ronin_req['result']:
|
|
235
|
+
exist_file = False
|
|
236
|
+
code_temp = code['content'].replace('\r\n', '\n')
|
|
237
|
+
while os.path.exists(contract_folder + "//" + contract_name):
|
|
238
|
+
exist_file = True
|
|
239
|
+
if contract_name.find("_")!= -1:
|
|
240
|
+
contract_name = contract_name.split('_')[0] + "_{}".format(index) + ".sol"
|
|
241
|
+
else:
|
|
242
|
+
contract_name = contract_name.split('.')[0] + "_{}".format(index) + ".sol"
|
|
243
|
+
index += 1
|
|
244
|
+
make_dir(os.path.split(contract_folder + "//" + address_info["contract_name"])[0])
|
|
245
|
+
# Do not process files with duplicate content
|
|
246
|
+
if exist_file and check_is_duplicate_file(contract_folder + "//" + temp_contract_name, code_temp):
|
|
247
|
+
continue
|
|
248
|
+
with open(contract_folder + "//" + contract_name, "w+", encoding='utf-8') as fw:
|
|
249
|
+
fw.write(code_temp)
|
|
250
|
+
sub_index += 1
|
|
251
|
+
print(f'{contract_index}-{sub_index}: {contract_folder + "/" + contract_name}'.replace('//', '/'))
|
|
252
|
+
contract_index += 1
|
|
253
|
+
if proxy_address != "":
|
|
254
|
+
addresses = [proxy_address]
|
|
255
|
+
proxy_contract[address] = proxy_address
|
|
256
|
+
send_ronin(addresses, output_folder, network)
|
|
257
|
+
except Exception as e:
|
|
258
|
+
handle_exception(e)
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
@retry(stop_max_attempt_number=5, wait_fixed=2000)
|
|
262
|
+
def zksync_request(url, proxies):
|
|
263
|
+
header = {
|
|
264
|
+
"User-Agent": USER_AGENT,
|
|
265
|
+
"Content-Type": "application/json"
|
|
266
|
+
}
|
|
267
|
+
zksync_req = requests.get(url, proxies=proxies, headers=header, verify=False)
|
|
268
|
+
return zksync_req.json()
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def send_zksync_era(addresses, output_folder, network):
|
|
272
|
+
global contract_index
|
|
273
|
+
global proxy_contract
|
|
274
|
+
global temp_contract_name
|
|
275
|
+
try:
|
|
276
|
+
proxies = get_proxies()
|
|
277
|
+
for address in addresses:
|
|
278
|
+
if network == "zksyncera":
|
|
279
|
+
url = f"https://zksync2-mainnet-explorer.zksync.io/contract_verification/info/{address}"
|
|
280
|
+
else:
|
|
281
|
+
url = f"https://zksync2-testnet-explorer.zksync.dev/contract_verification/info/{address}"
|
|
282
|
+
zksync_req = zksync_request(url, proxies)
|
|
283
|
+
contract_name = zksync_req['request']['contractName'].split(".sol:")[1]
|
|
284
|
+
save_info(address, contract_name)
|
|
285
|
+
contract_folder = contract_name if output_folder == "" else output_folder
|
|
286
|
+
index = 0
|
|
287
|
+
sub_index = 0
|
|
288
|
+
for contract_name in zksync_req['request']['sourceCode']['sources'].keys():
|
|
289
|
+
temp_contract_name = contract_name
|
|
290
|
+
code_temp = zksync_req['request']['sourceCode']['sources'][contract_name]['content'].replace('\r\n', '\n')
|
|
291
|
+
exist_file = False
|
|
292
|
+
while os.path.exists(contract_folder + "//" + contract_name):
|
|
293
|
+
exist_file = True
|
|
294
|
+
if contract_name.find("_")!= -1:
|
|
295
|
+
contract_name = contract_name.split('_')[0] + "_{}".format(index) + ".sol"
|
|
296
|
+
else:
|
|
297
|
+
contract_name = contract_name.split('.')[0] + "_{}".format(index) + ".sol"
|
|
298
|
+
index += 1
|
|
299
|
+
# Do not process files with duplicate content
|
|
300
|
+
if exist_file and check_is_duplicate_file(contract_folder + "//" + temp_contract_name, code_temp):
|
|
301
|
+
continue
|
|
302
|
+
make_dir(os.path.split(contract_folder + "//" + contract_name)[0])
|
|
303
|
+
with open(contract_folder + "//" + contract_name, "w+", encoding='utf-8') as fw:
|
|
304
|
+
fw.write(code_temp)
|
|
305
|
+
sub_index += 1
|
|
306
|
+
print(f'{contract_index}-{sub_index}: {contract_folder + "/" + contract_name}'.replace('//', '/'))
|
|
307
|
+
contract_index += 1
|
|
308
|
+
except Exception as e:
|
|
309
|
+
handle_exception(e)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
@retry(stop_max_attempt_number=5, wait_fixed=2000)
|
|
313
|
+
def common_requests(real_url, proxies, headers):
|
|
314
|
+
common_req = requests.get(real_url, proxies=proxies, headers=headers, verify=False)
|
|
315
|
+
return common_req
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def send_request(addresses, output_folder, network, api_key):
|
|
319
|
+
try:
|
|
320
|
+
proxies = get_proxies()
|
|
321
|
+
headers = {
|
|
322
|
+
'user-agent': USER_AGENT
|
|
323
|
+
}
|
|
324
|
+
for address in addresses:
|
|
325
|
+
if address in deal_addresses:
|
|
326
|
+
continue
|
|
327
|
+
deal_addresses.append(address)
|
|
328
|
+
output_data = ""
|
|
329
|
+
api_key = get_key() if api_key == "" else api_key
|
|
330
|
+
real_url = req_url + address + "&apikey=" + api_key + f"&chainid={chain_to_id.get(network)}"
|
|
331
|
+
req = common_requests(real_url, proxies, headers)
|
|
332
|
+
results = json.loads(req.text)['result']
|
|
333
|
+
if isinstance(results, dict):
|
|
334
|
+
output_data = results
|
|
335
|
+
elif isinstance(results, list):
|
|
336
|
+
output_data = results[0]
|
|
337
|
+
export_result(output_data, output_folder, network, address, api_key)
|
|
338
|
+
except Exception as e:
|
|
339
|
+
handle_exception(e)
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def export_result(result, output_folder, network, address, api_key):
|
|
343
|
+
global contract_index
|
|
344
|
+
global proxy_contract
|
|
345
|
+
global temp_contract_name
|
|
346
|
+
if "ContractName" not in result.keys():
|
|
347
|
+
return
|
|
348
|
+
try:
|
|
349
|
+
contract_suffix = ".sol"
|
|
350
|
+
if result['CompilerVersion'].find("vyper") != -1:
|
|
351
|
+
contract_suffix = ".vy"
|
|
352
|
+
index = 0
|
|
353
|
+
sub_index = 0
|
|
354
|
+
is_multi_file = False
|
|
355
|
+
contract_name = result['ContractName']
|
|
356
|
+
save_info(address, contract_name)
|
|
357
|
+
source_code = result['SourceCode'].replace("\r\n", "\n")
|
|
358
|
+
if source_code.find(contract_suffix + '":{"content":') != -1:
|
|
359
|
+
is_multi_file = True
|
|
360
|
+
if "\"language\":" in source_code or is_multi_file:
|
|
361
|
+
contract_folder = contract_name if output_folder == "" else output_folder
|
|
362
|
+
make_dir(contract_folder)
|
|
363
|
+
if not is_multi_file:
|
|
364
|
+
source_code = json.loads(source_code[1:-1])['sources']
|
|
365
|
+
else:
|
|
366
|
+
source_code = json.loads(source_code)
|
|
367
|
+
for key in source_code.keys():
|
|
368
|
+
contract_name = key + contract_suffix if key.find(contract_suffix) == -1 else key
|
|
369
|
+
temp_contract_name = contract_name
|
|
370
|
+
code_temp = source_code[key]["content"].replace('\r\n', '\n')
|
|
371
|
+
exist_file = False
|
|
372
|
+
while os.path.exists(contract_folder + "//" + contract_name):
|
|
373
|
+
exist_file = True
|
|
374
|
+
if contract_name.find("_")!= -1:
|
|
375
|
+
contract_name = contract_name.split('_')[0] + "_{}".format(index) + ".sol"
|
|
376
|
+
else:
|
|
377
|
+
contract_name = contract_name.split('.')[0] + "_{}".format(index) + ".sol"
|
|
378
|
+
index += 1
|
|
379
|
+
index = 0
|
|
380
|
+
# Do not process files with duplicate content
|
|
381
|
+
if exist_file and check_is_duplicate_file(contract_folder + "//" + temp_contract_name, code_temp):
|
|
382
|
+
continue
|
|
383
|
+
make_dir(os.path.split(contract_folder + "//" + contract_name)[0])
|
|
384
|
+
with open(contract_folder + "//" + contract_name, "w+", encoding='utf-8') as fw:
|
|
385
|
+
fw.write(code_temp)
|
|
386
|
+
print(f'{contract_index}-{sub_index}: {contract_folder + "/" + contract_name}'.replace('//', '/'))
|
|
387
|
+
sub_index += 1
|
|
388
|
+
contract_index += 1
|
|
389
|
+
else:
|
|
390
|
+
if contract_name == "":
|
|
391
|
+
return
|
|
392
|
+
contract_folder = contract_name if output_folder == "" else output_folder
|
|
393
|
+
contract_name = contract_name + contract_suffix if contract_name.find(contract_suffix) == -1 else contract_name
|
|
394
|
+
temp_contract_name = contract_name
|
|
395
|
+
code_temp = source_code.replace('\r\n', '\n')
|
|
396
|
+
exist_file = False
|
|
397
|
+
while os.path.exists(contract_folder + "//" + contract_name):
|
|
398
|
+
exist_file = True
|
|
399
|
+
if contract_name.find("_")!= -1:
|
|
400
|
+
contract_name = contract_name.split('_')[0] + "_{}".format(index) + ".sol"
|
|
401
|
+
else:
|
|
402
|
+
contract_name = contract_name.split('.')[0] + "_{}".format(index) + ".sol"
|
|
403
|
+
index += 1
|
|
404
|
+
# Do not process files with duplicate content
|
|
405
|
+
if exist_file and check_is_duplicate_file(contract_folder + "//" + temp_contract_name, code_temp):
|
|
406
|
+
return
|
|
407
|
+
make_dir(os.path.split(contract_folder + "//" + contract_name)[0])
|
|
408
|
+
with open(contract_folder + "//" + contract_name, "w+", encoding='utf-8') as fw:
|
|
409
|
+
fw.write(code_temp)
|
|
410
|
+
print(f'{contract_index}-{sub_index}: {contract_folder + "/" + contract_name}'.replace('//', '/'))
|
|
411
|
+
contract_index += 1
|
|
412
|
+
addresses = []
|
|
413
|
+
if network == "cronos":
|
|
414
|
+
if "ImplementationAddress" in result.keys():
|
|
415
|
+
if result['ImplementationAddress'] != "":
|
|
416
|
+
proxy_contract[address] = result['ImplementationAddress']
|
|
417
|
+
addresses.append(result['ImplementationAddress'])
|
|
418
|
+
send_request(addresses, "Implementation", network, api_key)
|
|
419
|
+
elif result['Implementation'] != "":
|
|
420
|
+
# Handle block explorer API exception returns to avoid infinite loops
|
|
421
|
+
if result['Implementation'].lower() == address.lower():
|
|
422
|
+
return
|
|
423
|
+
proxy_contract[address] = result['Implementation']
|
|
424
|
+
addresses.append(result['Implementation'])
|
|
425
|
+
send_request(addresses, "Implementation", network, api_key)
|
|
426
|
+
except Exception as e:
|
|
427
|
+
handle_exception(e)
|
getsourcecode/keys.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from random import randint
|
|
2
|
+
from getsourcecode.common import handle_exception
|
|
3
|
+
from getsourcecode.config import api_keys
|
|
4
|
+
|
|
5
|
+
def get_keys():
|
|
6
|
+
try:
|
|
7
|
+
return api_keys
|
|
8
|
+
except KeyError as e:
|
|
9
|
+
handle_exception(e)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_key():
|
|
13
|
+
try:
|
|
14
|
+
keys = get_keys()
|
|
15
|
+
random_num = randint(0, len(keys) - 1)
|
|
16
|
+
return keys[random_num]
|
|
17
|
+
except IndexError as e:
|
|
18
|
+
handle_exception(e)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def print_key():
|
|
22
|
+
try:
|
|
23
|
+
keys = get_keys()
|
|
24
|
+
if keys:
|
|
25
|
+
output_keys = "\n".join(keys)
|
|
26
|
+
print(output_keys)
|
|
27
|
+
except Exception as e:
|
|
28
|
+
handle_exception(e)
|
getsourcecode/menu.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from argparse import RawTextHelpFormatter
|
|
3
|
+
from getsourcecode.common import current_version
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def argparse_menu():
|
|
7
|
+
parser = argparse.ArgumentParser(
|
|
8
|
+
description="To get contract source code verified on blockchain explorer.\n\n"
|
|
9
|
+
"Supported Chain Platforms:\n"
|
|
10
|
+
" Ethereum Mainnet | Sepolia Testnet | Hoodi Testnet\n"
|
|
11
|
+
" BNB Smart Chain Mainnet | BNB Smart Chain Testnet\n"
|
|
12
|
+
" Polygon Mainnet | Polygon Amoy Testnet\n"
|
|
13
|
+
" Base Mainnet | Base Sepolia Testnet\n"
|
|
14
|
+
" Arbitrum One Mainnet | Arbitrum Sepolia Testnet\n"
|
|
15
|
+
" Linea Mainnet | Linea Sepolia Testnet\n"
|
|
16
|
+
" Blast Mainnet | Blast Sepolia Testnet\n"
|
|
17
|
+
" OP Mainnet | OP Sepolia Testnet\n"
|
|
18
|
+
" Avalanche C-Chain | Avalanche Fuji Testnet\n"
|
|
19
|
+
" BitTorrent Chain Mainnet | BitTorrent Chain Testnet\n"
|
|
20
|
+
" Celo Mainnet | Celo Sepolia Testnet\n"
|
|
21
|
+
" Fraxtal Mainnet | Fraxtal Hoodi Testnet\n"
|
|
22
|
+
" Gnosis\n"
|
|
23
|
+
" * Chain names are case-insensitive.\n"
|
|
24
|
+
" * Some chains (e.g. BNB Smart Chain, Base, OP, Avalanche) require a paid API plan.\n"
|
|
25
|
+
" * For the full list, visit: https://docs.etherscan.io/supported-chains\n\n"
|
|
26
|
+
"Some of the above networks may not be fully tested.\n"
|
|
27
|
+
"If you encounter any problems, please contact support@hxzy.me\n\n"
|
|
28
|
+
"PS: Files with exactly the same code will not be saved repeatedly.",
|
|
29
|
+
formatter_class=RawTextHelpFormatter)
|
|
30
|
+
|
|
31
|
+
parser.add_argument('-i', default='', dest='inputFile', help='Input file path including contract addresses.')
|
|
32
|
+
parser.add_argument('-o', default='', dest='outputFolder', help='Choose a folder to export.')
|
|
33
|
+
parser.add_argument('-a', default='', dest='address', help='A string including contract addresses.')
|
|
34
|
+
parser.add_argument('-n', default='', dest='network', help='Which network to get source code.')
|
|
35
|
+
parser.add_argument('-k', default='', dest='key', help='Provide paid api key to download paid-only network code.')
|
|
36
|
+
parser.add_argument('-p', default='', dest='proxy', help='Use a proxy.')
|
|
37
|
+
parser.add_argument('-t', default='', dest='txhash', help='Get the relevant contract source code in the specified transaction.')
|
|
38
|
+
parser.add_argument('-u', action="store_true", dest='update', help='Check to see if a new version is available to update.')
|
|
39
|
+
parser.add_argument('-v', action='version', version=current_version, help='Show current version.')
|
|
40
|
+
parser.add_argument('--hash', action="store_true", dest='contractHash', help='Show contract hash data.')
|
|
41
|
+
parser.add_argument('--apikey', default='', dest='apikey', help='The apikey required by the okex related chain.')
|
|
42
|
+
|
|
43
|
+
return parser.parse_args()
|