Import wallet, Send money

This commit is contained in:
2025-07-14 11:58:27 +03:00
parent 02ed2416d0
commit cd50a3b92a
2 changed files with 62 additions and 33 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
.idea/ .idea/
venv/ venv/
wallets/

View File

@@ -1,6 +1,7 @@
import os import os
import json import json
import getpass import getpass
from pathlib import Path
from web3 import Web3 from web3 import Web3
from Crypto.Cipher import AES from Crypto.Cipher import AES
from Crypto.Protocol.KDF import PBKDF2 from Crypto.Protocol.KDF import PBKDF2
@@ -8,7 +9,6 @@ from Crypto.Random import get_random_bytes
from rich import print from rich import print
from rich.prompt import Prompt from rich.prompt import Prompt
from eth_account import Account from eth_account import Account
import requests
WALLETS_DIR = "wallets" WALLETS_DIR = "wallets"
@@ -25,6 +25,7 @@ def encrypt_wallet(private_key, password):
key = PBKDF2(password, salt, dkLen=32) key = PBKDF2(password, salt, dkLen=32)
cipher = AES.new(key, AES.MODE_GCM) cipher = AES.new(key, AES.MODE_GCM)
ciphertext, tag = cipher.encrypt_and_digest(private_key.encode()) ciphertext, tag = cipher.encrypt_and_digest(private_key.encode())
return { return {
'ciphertext': ciphertext.hex(), 'ciphertext': ciphertext.hex(),
'salt': salt.hex(), 'salt': salt.hex(),
@@ -42,7 +43,7 @@ def decrypt_wallet(data, password):
def connect_to_network(): def connect_to_network():
global web3 global web3
rpc_url = Prompt.ask("[bold cyan]Введите RPC URL[/]") rpc_url = Prompt.ask("[bold cyan]Введите RPC URL[/]", default="https://ethereum-rpc.publicnode.com")
web3 = Web3(Web3.HTTPProvider(rpc_url)) web3 = Web3(Web3.HTTPProvider(rpc_url))
if web3.is_connected(): if web3.is_connected():
print("[green]Успешное подключение к сети Ethereum[/]") print("[green]Успешное подключение к сети Ethereum[/]")
@@ -54,12 +55,27 @@ def connect_to_network():
def create_wallet(): def create_wallet():
Account.enable_unaudited_hdwallet_features() Account.enable_unaudited_hdwallet_features()
acct = Account.create() acct = Account.create()
password = getpass.getpass("Введите пароль для шифрования кошелька: ") save_wallet(acct)
encrypted = encrypt_wallet(acct.key.hex(), password)
filename = os.path.join(WALLETS_DIR, f"{acct.address}.json")
def import_wallet():
print("[bold cyan]Введите приватный ключ: [/]", end='')
private_key = getpass.getpass(prompt="")
account = Account.from_key(private_key)
save_wallet(account)
def save_wallet(account):
print("[bold cyan]Введите пароль для шифрования кошелька: [/]", end='')
password = getpass.getpass(prompt="")
encrypted = encrypt_wallet(account.key.hex(), password)
filename = os.path.join(WALLETS_DIR, f"{account.address}.json")
with open(filename, 'w') as f: with open(filename, 'w') as f:
json.dump({"address": acct.address, "data": encrypted}, f) json.dump({"address": account.address, "data": encrypted}, f)
print(f"[green]Кошелек создан и сохранен: {acct.address}[/]") print(f"[green]Кошелек сохранен: {account.address}[/]")
def select_wallet(): def select_wallet():
@@ -68,9 +84,16 @@ def select_wallet():
if not files: if not files:
print("[red]Нет доступных кошельков.[/]") print("[red]Нет доступных кошельков.[/]")
return return
for i, fname in enumerate(files): for i, fname in enumerate(files):
print(f"[{i}] {fname}") print(f"[{i}] {Path(fname).stem}")
choice = int(Prompt.ask("Выберите номер кошелька"))
try:
choice = int(Prompt.ask("Выберите номер кошелька"))
except:
print("[red]Неверный номер.[/]")
return
with open(os.path.join(WALLETS_DIR, files[choice])) as f: with open(os.path.join(WALLETS_DIR, files[choice])) as f:
wallet_data = json.load(f) wallet_data = json.load(f)
selected_wallet = wallet_data['address'] selected_wallet = wallet_data['address']
@@ -85,45 +108,47 @@ def get_balance():
print(f"Баланс: {web3.from_wei(balance, 'ether')} ETH") print(f"Баланс: {web3.from_wei(balance, 'ether')} ETH")
def fetch_gas_data():
try:
res = requests.get("https://ethgas.watch/api/gas")
data = res.json()
fast = data['fast'] / 10
gas_price_wei = web3.to_wei(fast, 'gwei')
eth_price = requests.get("https://api.coinbase.com/v2/prices/ETH-USD/spot").json()['data']['amount']
gas_usd = web3.from_wei(gas_price_wei * 21000, 'ether') * float(eth_price)
return fast, gas_price_wei, round(gas_usd, 2)
except:
return None, None, None
def send_transaction(): def send_transaction():
if not selected_wallet: if not selected_wallet:
print("[red]Кошелек не выбран.[/]") print("[red]Кошелек не выбран.[/]")
return return
password = getpass.getpass("Введите пароль от кошелька: ")
print("[bold cyan]Введите пароль от кошелька: [/]", end='')
password = getpass.getpass(prompt="")
try: try:
private_key = decrypt_wallet(wallet_data['data'], password) private_key = decrypt_wallet(wallet_data['data'], password)
except: except:
print("[red]Неверный пароль![/]") print("[red]Неверный пароль![/]")
return return
to = Prompt.ask("Введите адрес получателя") to = Prompt.ask("[bold cyan]Введите адрес получателя[/]")
value = float(Prompt.ask("Введите сумму в ETH")) value = float(Prompt.ask("[bold cyan]Введите сумму в ETH[/]"))
_, gas_price, _ = fetch_gas_data()
print(f"[yellow]Текущая цена за газ: {gas_price}") base_fee = web3.eth.fee_history(1, 'latest')['baseFeePerGas'][-1]
priority_fee_gwei = float(Prompt.ask("[bold cyan]Введите приоритетную комиссию в GWEI[/]", default="2"))
max_priority_fee = web3.to_wei(priority_fee_gwei, 'gwei')
max_fee = base_fee + max_priority_fee * 2
print(f"[yellow]Максимальная комиссия за транзакцию: {float(max_fee) / 10**9} gwei[/]")
tx = { tx = {
'chainId': web3.eth.chain_id,
'nonce': web3.eth.get_transaction_count(selected_wallet), 'nonce': web3.eth.get_transaction_count(selected_wallet),
'to': to, 'to': to,
'value': web3.to_wei(value, 'ether'), 'value': web3.to_wei(value, 'ether'),
'gas': 21000, 'gas': 21000,
'gasPrice': gas_price 'maxFeePerGas': max_fee,
'maxPriorityFeePerGas': max_priority_fee
} }
signed = web3.eth.account.sign_transaction(tx, private_key)
tx_hash = web3.eth.send_raw_transaction(signed.rawTransaction) try:
print(f"[green]Транзакция отправлена! TX Hash: {tx_hash.hex()}[/]") signed = web3.eth.account.sign_transaction(tx, private_key)
tx_hash = web3.eth.send_raw_transaction(signed.raw_transaction)
print(f"[green]Транзакция отправлена! TX Hash: {tx_hash.hex()}[/]")
except Exception as error:
print(f"[red]{error.message}[/]")
def main(): def main():
@@ -134,6 +159,7 @@ def main():
w. Выбор кошелька w. Выбор кошелька
b. Просмотр баланса b. Просмотр баланса
s. Отправка средств s. Отправка средств
i. Импорт существующего кошелька
q. Выход q. Выход
""") """)
@@ -154,7 +180,9 @@ def main():
if web3 and selected_wallet: if web3 and selected_wallet:
send_transaction() send_transaction()
else: else:
print("[red]Необходимо подключение и выбор кошелька[/]") print("[red]Необходимо подключиться к сети и выбрать кошелек[/]")
elif choice == 'i':
import_wallet()
elif choice == 'q': elif choice == 'q':
break break
else: else: