Import wallet, Send money
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
.idea/
|
||||
venv/
|
||||
wallets/
|
||||
92
wallet.py
92
wallet.py
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
import json
|
||||
import getpass
|
||||
from pathlib import Path
|
||||
from web3 import Web3
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Protocol.KDF import PBKDF2
|
||||
@@ -8,7 +9,6 @@ from Crypto.Random import get_random_bytes
|
||||
from rich import print
|
||||
from rich.prompt import Prompt
|
||||
from eth_account import Account
|
||||
import requests
|
||||
|
||||
WALLETS_DIR = "wallets"
|
||||
|
||||
@@ -25,6 +25,7 @@ def encrypt_wallet(private_key, password):
|
||||
key = PBKDF2(password, salt, dkLen=32)
|
||||
cipher = AES.new(key, AES.MODE_GCM)
|
||||
ciphertext, tag = cipher.encrypt_and_digest(private_key.encode())
|
||||
|
||||
return {
|
||||
'ciphertext': ciphertext.hex(),
|
||||
'salt': salt.hex(),
|
||||
@@ -42,7 +43,7 @@ def decrypt_wallet(data, password):
|
||||
|
||||
def connect_to_network():
|
||||
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))
|
||||
if web3.is_connected():
|
||||
print("[green]Успешное подключение к сети Ethereum[/]")
|
||||
@@ -54,12 +55,27 @@ def connect_to_network():
|
||||
def create_wallet():
|
||||
Account.enable_unaudited_hdwallet_features()
|
||||
acct = Account.create()
|
||||
password = getpass.getpass("Введите пароль для шифрования кошелька: ")
|
||||
encrypted = encrypt_wallet(acct.key.hex(), password)
|
||||
filename = os.path.join(WALLETS_DIR, f"{acct.address}.json")
|
||||
save_wallet(acct)
|
||||
|
||||
|
||||
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:
|
||||
json.dump({"address": acct.address, "data": encrypted}, f)
|
||||
print(f"[green]Кошелек создан и сохранен: {acct.address}[/]")
|
||||
json.dump({"address": account.address, "data": encrypted}, f)
|
||||
print(f"[green]Кошелек сохранен: {account.address}[/]")
|
||||
|
||||
|
||||
def select_wallet():
|
||||
@@ -68,9 +84,16 @@ def select_wallet():
|
||||
if not files:
|
||||
print("[red]Нет доступных кошельков.[/]")
|
||||
return
|
||||
|
||||
for i, fname in enumerate(files):
|
||||
print(f"[{i}] {fname}")
|
||||
choice = int(Prompt.ask("Выберите номер кошелька"))
|
||||
print(f"[{i}] {Path(fname).stem}")
|
||||
|
||||
try:
|
||||
choice = int(Prompt.ask("Выберите номер кошелька"))
|
||||
except:
|
||||
print("[red]Неверный номер.[/]")
|
||||
return
|
||||
|
||||
with open(os.path.join(WALLETS_DIR, files[choice])) as f:
|
||||
wallet_data = json.load(f)
|
||||
selected_wallet = wallet_data['address']
|
||||
@@ -85,45 +108,47 @@ def get_balance():
|
||||
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():
|
||||
if not selected_wallet:
|
||||
print("[red]Кошелек не выбран.[/]")
|
||||
return
|
||||
password = getpass.getpass("Введите пароль от кошелька: ")
|
||||
|
||||
print("[bold cyan]Введите пароль от кошелька: [/]", end='')
|
||||
password = getpass.getpass(prompt="")
|
||||
|
||||
try:
|
||||
private_key = decrypt_wallet(wallet_data['data'], password)
|
||||
except:
|
||||
print("[red]Неверный пароль![/]")
|
||||
return
|
||||
|
||||
to = Prompt.ask("Введите адрес получателя")
|
||||
value = float(Prompt.ask("Введите сумму в ETH"))
|
||||
_, gas_price, _ = fetch_gas_data()
|
||||
print(f"[yellow]Текущая цена за газ: {gas_price}")
|
||||
to = Prompt.ask("[bold cyan]Введите адрес получателя[/]")
|
||||
value = float(Prompt.ask("[bold cyan]Введите сумму в ETH[/]"))
|
||||
|
||||
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 = {
|
||||
'chainId': web3.eth.chain_id,
|
||||
'nonce': web3.eth.get_transaction_count(selected_wallet),
|
||||
'to': to,
|
||||
'value': web3.to_wei(value, 'ether'),
|
||||
'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)
|
||||
print(f"[green]Транзакция отправлена! TX Hash: {tx_hash.hex()}[/]")
|
||||
|
||||
try:
|
||||
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():
|
||||
@@ -134,6 +159,7 @@ def main():
|
||||
w. Выбор кошелька
|
||||
b. Просмотр баланса
|
||||
s. Отправка средств
|
||||
i. Импорт существующего кошелька
|
||||
q. Выход
|
||||
""")
|
||||
|
||||
@@ -154,7 +180,9 @@ def main():
|
||||
if web3 and selected_wallet:
|
||||
send_transaction()
|
||||
else:
|
||||
print("[red]Необходимо подключение и выбор кошелька[/]")
|
||||
print("[red]Необходимо подключиться к сети и выбрать кошелек[/]")
|
||||
elif choice == 'i':
|
||||
import_wallet()
|
||||
elif choice == 'q':
|
||||
break
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user