Spaces:
Sleeping
Sleeping
Commit
·
43c0549
1
Parent(s):
2d89504
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,196 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# EthPen.com
|
2 |
+
|
3 |
+
# 导入运行代码所需要的库
|
4 |
+
import streamlit as st # streamlit app
|
5 |
+
from web3 import Web3 # 与以太坊交互的库
|
6 |
+
import hashlib # 用于数据哈希
|
7 |
+
import re # 用于正则表达式
|
8 |
+
import time # 用于时间相关
|
9 |
+
|
10 |
+
|
11 |
+
# 许可使用开关
|
12 |
+
approved_use = False
|
13 |
+
|
14 |
+
|
15 |
+
# 检查 ETH 地址是否有效
|
16 |
+
def is_valid_eth_address(address):
|
17 |
+
if re.match("^0x[0-9a-fA-F]{40}$", address):
|
18 |
+
return True
|
19 |
+
return False
|
20 |
+
|
21 |
+
|
22 |
+
# 检查 Ethereum 私钥是否有效
|
23 |
+
def is_valid_eth_private_key(private_key):
|
24 |
+
if re.match("^[0-9a-fA-F]{64}$", private_key):
|
25 |
+
return True
|
26 |
+
return False
|
27 |
+
|
28 |
+
|
29 |
+
# 验证输入的铭文文本是否含有空格和换行符,而且字母全部为小写
|
30 |
+
def validate_input(data_str):
|
31 |
+
if re.search(r'[A-Z\s\n]', data_str): # 查找大写字母、空格或换行符
|
32 |
+
return False
|
33 |
+
return True
|
34 |
+
|
35 |
+
|
36 |
+
# 把文字转换成 16 进制
|
37 |
+
def text_to_hex(text):
|
38 |
+
return ''.join(format(byte, '02x') for byte in text.encode('utf-8'))
|
39 |
+
|
40 |
+
|
41 |
+
# 使用sha256算法计算哈希
|
42 |
+
def sha256(input_string):
|
43 |
+
sha256 = hashlib.sha256()
|
44 |
+
sha256.update(input_string.encode('utf-8'))
|
45 |
+
return sha256.hexdigest()
|
46 |
+
|
47 |
+
|
48 |
+
# 发送自己到自己 0ETH 的交易
|
49 |
+
def send_transaction(w3, account_address, private_key, chain_id, gas_price, input_data, current_nonce):
|
50 |
+
|
51 |
+
# 设置交易的相关信息
|
52 |
+
tx = {
|
53 |
+
'chainId': chain_id, # 网络 ID
|
54 |
+
'gas': 25000, # 如果交易 gas 过低,可适当调高
|
55 |
+
'gasPrice': gas_price, # gas 的价格
|
56 |
+
'nonce': current_nonce,
|
57 |
+
'to': account_address, # 接收地址为自己
|
58 |
+
'value': 0, # 金额为 0ETH
|
59 |
+
'data': text_to_hex(input_data), # 铭文内容
|
60 |
+
}
|
61 |
+
|
62 |
+
# 用私钥签名这个交易
|
63 |
+
signed_tx = w3.eth.account.sign_transaction(tx, private_key)
|
64 |
+
# 发送签名后的交易并获取交易哈希
|
65 |
+
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
|
66 |
+
# 打印结果信息
|
67 |
+
st.toast(f'{input_data}', icon='✅')
|
68 |
+
# 返回铭文还有交易哈希
|
69 |
+
return input_data, tx_hash.hex()
|
70 |
+
|
71 |
+
|
72 |
+
# 网页前端显示
|
73 |
+
st.set_page_config(page_title="EthPen - 批量 Mint $pols", page_icon="🪙", layout='centered', initial_sidebar_state='auto')
|
74 |
+
|
75 |
+
# 网页标题
|
76 |
+
st.subheader(r'🪙 :rainbow[EthPen - 批量 Mint $pols]', anchor=False, divider='rainbow')
|
77 |
+
|
78 |
+
# 提醒
|
79 |
+
st.markdown('### 在开始使用前,请仔细阅读相关说明,并在确认无误后打上 ✅。感谢您的理解与配合。')
|
80 |
+
|
81 |
+
st.markdown('''- 我们已将网站代码完全开源。您可以访问并仔细阅读此页面的源码:[3_🪙_ 批量题写代币铭文.py](https://huggingface.co/spaces/Ethscriptions/POLS/tree/main)
|
82 |
+
|
83 |
+
- 如果你对此代码存有疑虑,建议你利用如 [OpenAI - ChetGPT](https://chat.openai.com/)、[Google - Bard](https://bard.google.com/)、[Anthropic - Claude](https://claude.ai/)、[抖音 - 豆包](https://www.doubao.com/)、[百度 - 文心一言](https://yiyan.baidu.com/)、[阿里 - 通义千问](https://qianwen.aliyun.com/) 等知名 AI 平台进行问询,这可以帮助你判断代码是否含有恶意内容。
|
84 |
+
|
85 |
+
- 复制我们的代码,你同样可以在 [HuggingFace](https://HuggingFace.co) 上搭建专属于你的域名铭文批量题写工具。
|
86 |
+
|
87 |
+
- 请务必确保你正在访问的是 **[EthPen.com](https://ethpen.com)** 网站。我们保证站内代码不包含窃取私钥或其他恶意行为,你可以安心使用。
|
88 |
+
|
89 |
+
- 在使用过程中,请按照提示准确地填写信息,这样可以确保程序的顺畅运行。
|
90 |
+
|
91 |
+
- 为了安全起见,我们建议您使用备用账号(小号)并确保账号中不存放大额资金。
|
92 |
+
|
93 |
+
- 首次使用时,我们建议您先使用小号少量操作。确认一切无误后,再大批量账户使用。
|
94 |
+
|
95 |
+
- 若您在使用过程中遇到问题,请及时向我们反馈。我们明白程序可能存在不完善之处,并且我们的能力也有限。真心希望得到各位程序员大佬的指导和交流。
|
96 |
+
''',)
|
97 |
+
|
98 |
+
approved = st.checkbox('我已经详细阅读上述内容,并且清楚了解本网站无泄漏私钥的风险。',)
|
99 |
+
|
100 |
+
if approved:
|
101 |
+
approved_use = True
|
102 |
+
else:
|
103 |
+
approved_use = False
|
104 |
+
|
105 |
+
if approved_use:
|
106 |
+
|
107 |
+
st.markdown('## 批量题写 $pols 代币')
|
108 |
+
|
109 |
+
# 这里配置 Ethereum PRC URL,如果你没有,请到 infura.io 或者 alchemy.com 申请一个免费的 API
|
110 |
+
token_eth_prc_url = st.text_input(
|
111 |
+
f'**Polygon PRC 链接**:选填,你可以去 [infura.io](https://app.infura.io/) 或者 [alchemy.com](https://alchemy.com/) 免费申请一个',
|
112 |
+
f'https://polygon-mainnet.g.alchemy.com/v2/UNAiPmma0H0vPaeimRGnIYJmJu0iAHkr')
|
113 |
+
w3 = Web3(Web3.HTTPProvider(f'{token_eth_prc_url}'))
|
114 |
+
|
115 |
+
# 初始化当前账户索引为 0
|
116 |
+
current_account_index = 0
|
117 |
+
# 收集和显示所有交易的结果
|
118 |
+
transaction_results = []
|
119 |
+
# 创建账户列表
|
120 |
+
accounts = []
|
121 |
+
# 使用字典来跟踪每个地址的nonce
|
122 |
+
nonces = {}
|
123 |
+
|
124 |
+
# 启用多账户操作
|
125 |
+
multipl_accounts = st.toggle('启用**多账户**操作')
|
126 |
+
if multipl_accounts:
|
127 |
+
# 多账户的文本框
|
128 |
+
account_list = st.text_area(f'输入多个 **ETH 地址及其对应的私钥**,用英文逗号分隔(,),如下:地址,私钥')
|
129 |
+
if account_list: # 如果账户列表有内容
|
130 |
+
for line in account_list.split('\n'): # 根据换行符划分账户
|
131 |
+
if ',' in line: # 检查是否包含逗号
|
132 |
+
address, key = line.split(',') # 分开地址和私钥
|
133 |
+
if is_valid_eth_address(address) and is_valid_eth_private_key(key): # 验证地址和私钥
|
134 |
+
current_nonce = w3.eth.get_transaction_count(address) # 获取地址的 nonce
|
135 |
+
nonces[address] = current_nonce # 记录地址的 nonce
|
136 |
+
accounts.append((address.strip(), key.strip())) # 保存地址和私钥还有 nonce
|
137 |
+
else:
|
138 |
+
st.error(f"地址 {address} 或私钥 {key} 无效,请检查!")
|
139 |
+
st.stop()
|
140 |
+
else:
|
141 |
+
st.error(f"输入格式错误,请确保每行包含一个地址和一个私钥,并使用英文逗号分隔(,)。错误行:**{line}**")
|
142 |
+
st.stop()
|
143 |
+
else:
|
144 |
+
account_address = st.text_input('填写你的 **ETH 地址**:')
|
145 |
+
private_key = st.text_input('填写你的 **ETH 地址对应的私钥**:', type="password")
|
146 |
+
if account_address and private_key: # 如果地址和私钥有内容
|
147 |
+
if is_valid_eth_address(account_address) and is_valid_eth_private_key(private_key): # 验证地址和私钥
|
148 |
+
current_nonce = w3.eth.get_transaction_count(account_address) # 获取地址的 nonce
|
149 |
+
nonces[account_address] = current_nonce # 记录地址的 nonce
|
150 |
+
accounts.append((account_address.strip(), private_key.strip())) # 保存地址和私钥还有 nonce
|
151 |
+
else:
|
152 |
+
st.error("地址或私钥无效,请检查!")
|
153 |
+
st.stop()
|
154 |
+
|
155 |
+
# 配置铭文文本
|
156 |
+
input_data = st.text_input('填写需要题写代币铭文文本', 'data:,{"p":"prc-20","op":"mint","tick":"pols","amt":"100000000"}')
|
157 |
+
token_amount = st.number_input('填写需要题写代币铭文数量(张)', min_value=1, value=100, step=1)
|
158 |
+
# 判断铭文文本里是否包含空格、换行符,而且所有的字母都必须为小写。
|
159 |
+
if not validate_input(f'{input_data}'):
|
160 |
+
st.warning("**请注意**:通常代币铭文文本里不能包含空格、换行符,而且所有的字母都必须为小写。")
|
161 |
+
|
162 |
+
sleep_3s = st.toggle('每次完成交易后暂停 3 秒')
|
163 |
+
# 每次交易成功后暂停 3 秒
|
164 |
+
if sleep_3s:
|
165 |
+
sleep_3s = True
|
166 |
+
else:
|
167 |
+
sleep_3s = False
|
168 |
+
|
169 |
+
# 点击发送交易开始
|
170 |
+
if st.button(f'开始**发送交易**'):
|
171 |
+
st.toast(f'开始任务,需要题写的铭文总量为:{token_amount}', icon='😎')
|
172 |
+
# 对代币铭文 id 进行循环
|
173 |
+
for the_id in range(token_amount):
|
174 |
+
# 使用当前账户发送交易,获取当前账户的 nonce
|
175 |
+
address, key = accounts[current_account_index]
|
176 |
+
# 获取 gas
|
177 |
+
gas_price = w3.eth.gas_price
|
178 |
+
# 这里是未开检查后直接发送交易
|
179 |
+
# 使用 current_nonce 发送交易
|
180 |
+
data, tx_hash = send_transaction(w3, address, key, 137, gas_price, input_data, nonces[address])
|
181 |
+
# 记录最后输出的结果
|
182 |
+
transaction_results.append(f"Transaction Hash: https://polygonscan.com/tx/{tx_hash}")
|
183 |
+
# 交易成功后,手动增加 nonce 值
|
184 |
+
nonces[address] += 1
|
185 |
+
# 更新当前账户索引,确保索引始终在账户列表的范围内
|
186 |
+
current_account_index = (current_account_index + 1) % len(accounts)
|
187 |
+
# 暂停 3 秒
|
188 |
+
if sleep_3s:
|
189 |
+
time.sleep(3) # 暂停三秒
|
190 |
+
st.toast(f'所有任务已经完成。', icon='🎉')
|
191 |
+
# 庆祝动画
|
192 |
+
st.balloons()
|
193 |
+
# 显示所有交易的结果
|
194 |
+
st.code('\n'.join(transaction_results))
|
195 |
+
else:
|
196 |
+
st.error('# 阅读并打勾 ✅ 后方可使用。')
|