forked from bokub/vanity-eth
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbot.py
More file actions
133 lines (100 loc) Β· 4.13 KB
/
Copy pathbot.py
File metadata and controls
133 lines (100 loc) Β· 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import os
import re
import asyncio
import logging
from concurrent.futures import ThreadPoolExecutor
from dotenv import load_dotenv
from eth_account import Account
from telegram import Update
from telegram.ext import (
ApplicationBuilder,
CommandHandler,
ContextTypes,
MessageHandler,
filters,
)
# Load environment variables from a .env file (if present)
load_dotenv()
BOT_TOKEN = os.getenv("BOT_TOKEN")
if not BOT_TOKEN:
raise RuntimeError("Please set the BOT_TOKEN environment variable in a .env file or system environment.")
# Configure logging
logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
)
logger = logging.getLogger(__name__)
# ThreadPoolExecutor for CPU-bound vanity generation tasks
executor = ThreadPoolExecutor(max_workers=os.cpu_count() or 4)
HEX_PATTERN = re.compile(r"^[0-9a-fA-F]+$")
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Send a welcome message and brief instruction."""
await update.message.reply_text(
"π Halo! Kirim /generate <prefiks_heksadesimal> untuk membuat dompet Ethereum vanity.\n\n"
"Contoh: /generate abc\n"
"Catatan: Prefiks tidak termasuk '0x' dan sebaiknya maksimal 6 karakter untuk proses cepat."
)
def generate_wallet(prefix: str) -> tuple[str, str]:
"""Brute force search for an Ethereum address that starts with the given hex prefix.
Returns tuple (address, private_key_hex).
"""
prefix = prefix.lower()
target = "0x" + prefix
attempts = 0
while True:
acct = Account.create()
address = acct.address.lower()
attempts += 1
if address.startswith(target):
return address, acct.key.hex()
# Optionally log progress every million attempts.
if attempts % 1_000_000 == 0:
logger.info("Tried %d keys for prefix %s", attempts, prefix)
async def _async_generate(prefix: str) -> tuple[str, str]:
"""Run the CPU bound generate_wallet in a thread pool."""
loop = asyncio.get_running_loop()
return await loop.run_in_executor(executor, generate_wallet, prefix)
async def generate_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Handle the /generate command."""
if not context.args:
await update.message.reply_text("Silakan sertakan prefiks hex. Contoh: /generate abc")
return
prefix = context.args[0]
# Validate prefix
if not HEX_PATTERN.fullmatch(prefix):
await update.message.reply_text("Prefiks harus berupa karakter heksadesimal (0-9, a-f).")
return
if len(prefix) > 6:
await update.message.reply_text("Prefiks terlalu panjang (maks 6 karakter disarankan).")
return
await update.message.reply_text(
f"β³ Sedang mencari alamat yang dimulai dengan 0x{prefix} ... Mohon tunggu."
)
try:
address, priv_key = await _async_generate(prefix)
except Exception as exc:
logger.exception("Error generating wallet: %s", exc)
await update.message.reply_text("Terjadi kesalahan saat membuat dompet. Coba lagi nanti.")
return
# Send result (beware of privacy)
await update.message.reply_text(
f"β
Ditemukan!\n\n"
f"Address: `{address}`\n"
f"Private Key: `{priv_key}`\n\n"
"SIMPAN private key ini dengan aman. Siapapun yang memiliki kunci ini dapat mengakses dana Anda.",
parse_mode="Markdown",
)
async def unknown_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Respond to unknown commands."""
await update.message.reply_text("Perintah tidak dikenali. Gunakan /generate untuk membuat dompet baru.")
def main() -> None:
"""Run the Telegram bot."""
application = ApplicationBuilder().token(BOT_TOKEN).build()
application.add_handler(CommandHandler("start", start))
application.add_handler(CommandHandler("generate", generate_handler))
# Unknown commands
application.add_handler(MessageHandler(filters.COMMAND, unknown_handler))
# Start the bot
logger.info("Bot started...")
application.run_polling()
if __name__ == "__main__":
main()