SAUSERLA commited on
Commit
180e626
Β·
verified Β·
1 Parent(s): 981b1f0

Upload 16 files

Browse files
check/.gitignore ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ *.egg-info/
24
+ .installed.cfg
25
+ *.egg
26
+ MANIFEST
27
+
28
+ # PyInstaller
29
+ *.manifest
30
+ *.spec
31
+
32
+ # Installer logs
33
+ pip-log.txt
34
+ pip-delete-this-directory.txt
35
+
36
+ # Unit test / coverage reports
37
+ htmlcov/
38
+ .tox/
39
+ .nox/
40
+ .coverage
41
+ .coverage.*
42
+ .cache
43
+ nosetests.xml
44
+ coverage.xml
45
+ *.cover
46
+ .hypothesis/
47
+ .pytest_cache/
48
+
49
+ # Translations
50
+ *.mo
51
+ *.pot
52
+
53
+ # Django stuff:
54
+ *.log
55
+ local_settings.py
56
+ db.sqlite3
57
+
58
+ # Flask stuff:
59
+ instance/
60
+ .webassets-cache
61
+
62
+ # Scrapy stuff:
63
+ .scrapy
64
+
65
+ # Sphinx documentation
66
+ docs/_build/
67
+
68
+ # PyBuilder
69
+ target/
70
+
71
+ # Jupyter Notebook
72
+ .ipynb_checkpoints
73
+
74
+ # IPython
75
+ profile_default/
76
+ ipython_config.py
77
+
78
+ # pyenv
79
+ .python-version
80
+
81
+ # celery beat schedule file
82
+ celerybeat-schedule
83
+
84
+ # SageMath parsed files
85
+ *.sage.py
86
+
87
+ # Environments
88
+ .env
89
+ .venv
90
+ env/
91
+ venv/
92
+ ENV/
93
+ env.bak/
94
+ venv.bak/
95
+
96
+ # Spyder project settings
97
+ .spyderproject
98
+ .spyproject
99
+
100
+ # Rope project settings
101
+ .ropeproject
102
+
103
+ # mkdocs documentation
104
+ /site
105
+
106
+ # mypy
107
+ .mypy_cache/
108
+ .dmypy.json
109
+ dmypy.json
110
+
111
+ # Pyre type checker
112
+ .pyre/
check/.local/state/replit/agent/.agent_state_3f44dea3ced50eea70ed33f619266e6106de2f11.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:348dc2a73d8391d49ef77ec716b2f92e2e9024fa39cc984cebac680c8ce7763c
3
+ size 70772
check/.local/state/replit/agent/.agent_state_463c51dcb980c6a1c74871fdded99cee48599e9f.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5e385906b8811e52a23cb2e70c96e9dc0f3e17fdae5693a8117a2cebbaed9610
3
+ size 15354
check/.local/state/replit/agent/.agent_state_4a9c459c1a931955b949bf88f4b0e0baa9962553.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1117e7acff36469b266910d8ddc0c9706f8199b05c142914aa83266beed87f74
3
+ size 61030
check/.local/state/replit/agent/.agent_state_64e054bde1467c40837361c152fc18d8c61c7222.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e0043f982a8790ee22f682f758e4c3ae332c9e9ef5e4224a332d8a74d427c784
3
+ size 43283
check/.local/state/replit/agent/.agent_state_8e004c6c49565a75b7faeecd2d322a680a4f0544.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1224d68482e0e6252197eadc9bfea4a199ec50bb010a27df78001d58a5c0aad3
3
+ size 53225
check/.local/state/replit/agent/.agent_state_a142ae0b26554e72877f8744d1805d558482e490.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c42c1cc3765aeaf52cfe3c4e2dda77a0d55dd1bc552a8fa1a2be89783ea81633
3
+ size 15324
check/.local/state/replit/agent/.agent_state_main.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9eef0a119374324445ed18e6bc52dad353071ac2e61cacaa8eb774ed8595c8b3
3
+ size 70743
check/.local/state/replit/agent/.latest.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"latest": "main"}
check/.local/state/replit/agent/filesystem/filesystem_state.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"file_contents":{"README.md":{"content":"title: Solana Key-Miner\nemoji: πŸͺ™\ncolorFrom: green\ncolorTo: gray\nsdk: gradio\nsdk_version: 4.44.0\napp_file: app.py\npinned: false\nπŸ” Solana Key Generator & Live Miner\nGenerate Ed25519 Base-58 keys and mine Solana addresses in real time with Discord notifications.\n\nFeatures\nπŸ”„ 30-minute mining cycles (30 min active, 30 min break)\nNon-stop background miner (100 wallets per RPC call)\nLive Discord status embed (updates every 60 seconds)\n@everyone ping when a funded wallet is found\nReal-time feed inside the interface\nBulk key generation (up to 1000 keys)\nMultiple RPC endpoint fallback for reliability\n🌐 Multi-platform compatibility (Hugging Face Spaces & Replit)\nπŸš€ Complete Setup Guide for ALL Platforms\nπŸ€— Hugging Face Spaces (Recommended - FREE)\nStep 1: Create Your Space\nGo to huggingface.co/new-space\nChoose a name for your space (e.g., my-solana-miner)\nSelect Gradio as the SDK\nSet visibility to Public or Private (your choice)\nClick Create Space\nStep 2: Upload Files\nClick Files tab in your new space\nUpload these files from this repository:\napp.py (main application)\nrequirements.txt (dependencies)\nREADME.md (this file)\nStep 3: Set Up Discord (Optional but Recommended)\nGo to your Discord server\nRight-click on the channel where you want notifications\nSelect Edit Channel β†’ Integrations β†’ Webhooks\nClick New Webhook\nCopy the webhook URL\nIn your Hugging Face Space, go to Settings tab\nScroll to Repository secrets\nAdd new secret: DISCORD_WEBHOOK = your_webhook_url_here\nStep 4: Configure Settings (Optional)\nAdd these optional secrets in Hugging Face Settings:\n\nMIN_SOL=0.00001 (minimum SOL to consider \"funded\")\nRPC_BATCH_SIZE=100 (wallets per batch, max 100)\nMINER_SLEEP=1.0 (seconds between mining cycles)\nStep 5: Launch\nYour space will automatically build and deploy\nWait 2-3 minutes for initialization\nClick the app URL to access your miner\nHit Start Mining and watch it work!\nπŸ’» Local Development Setup\nRequirements\nPython 3.8 or higher\nGit\nStep 1: Clone Repository\ngit clone <your-repo-url>\ncd solana-key-miner\nStep 2: Create Virtual Environment\n# Windows\npython -m venv venv\nvenv\\Scripts\\activate\n\n# macOS/Linux\npython3 -m venv venv\nsource venv/bin/activate\nStep 3: Install Dependencies\npip install -r requirements.txt\nStep 4: Set Environment Variables\nCreate a .env file in the project root:\n\n# Required for Discord notifications (optional)\nDISCORD_WEBHOOK=your_discord_webhook_url_here\n\n# Optional settings\nMIN_SOL=0.00001\nRPC_BATCH_SIZE=100\nMINER_SLEEP=1.0\nStep 5: Run the Application\npython app.py\nThe app will be available at http://localhost:7860\n\n🐳 Docker Setup\nStep 1: Create Dockerfile\nCreate Dockerfile in your project root:\n\nFROM python:3.9-slim\n\nWORKDIR /app\nCOPY requirements.txt .\nRUN pip install -r requirements.txt\n\nCOPY . .\n\nEXPOSE 7860\nCMD [\"python\", \"app.py\"]\nStep 2: Build and Run\n# Build the image\ndocker build -t solana-miner .\n\n# Run with environment variables\ndocker run -d \\\n -p 7860:7860 \\\n -e DISCORD_WEBHOOK=your_webhook_url \\\n -e MIN_SOL=0.00001 \\\n --name solana-miner \\\n solana-miner\n☁️ Cloud Deployment Options\nGoogle Cloud Run\nInstall Google Cloud CLI\nBuild and deploy:\ngcloud run deploy solana-miner \\\n --source . \\\n --platform managed \\\n --region us-central1 \\\n --allow-unauthenticated \\\n --set-env-vars DISCORD_WEBHOOK=your_webhook_url\nAWS EC2\nLaunch Ubuntu 20.04 instance\nSSH into instance\nInstall Python and dependencies:\nsudo apt update\nsudo apt install python3 python3-pip git -y\ngit clone <your-repo>\ncd solana-key-miner\npip3 install -r requirements.txt\nSet environment variables and run\nDigitalOcean Droplet\nCreate Ubuntu droplet\nFollow same steps as AWS EC2\nOptional: Set up nginx reverse proxy\nπŸ”§ Configuration Guide\nEnvironment Variables\nVariable Default Description\nDISCORD_WEBHOOK None Discord webhook URL for notifications\nMIN_SOL 0.00001 Minimum SOL to consider wallet \"funded\"\nRPC_BATCH_SIZE 100 Number of wallets to check per RPC call\nMINER_SLEEP 1.0 Seconds to sleep between mining cycles\nPORT 7860 Port for the web interface\nDiscord Setup Details\nServer Permissions: Ensure the bot/webhook has permission to send messages\nChannel Selection: Use a dedicated channel for miner notifications\nWebhook Security: Keep your webhook URL private\nRate Limits: The app automatically manages Discord rate limits\nRPC Endpoints\nThe app uses multiple free Solana RPC endpoints with automatic failover:\n\napi.mainnet-beta.solana.com\nsolana-api.projectserum.com\nrpc.ankr.com/solana\nsolana.public-rpc.com\nπŸ›‘οΈ Security Considerations\nImportant Notes\nThis tool is for educational purposes\nFound private keys are displayed in the interface\nBe cautious when using Discord notifications\nNever share your webhook URLs\nKeep your environment variables secure\nBest Practices\nUse private Hugging Face Spaces for sensitive operations\nRegularly rotate Discord webhooks\nMonitor your RPC usage\nKeep dependencies updated\nπŸ“± Mobile Access\nAccess via Mobile Browser\nDeploy to any cloud platform above\nAccess via mobile browser\nAdd to home screen for app-like experience\nResponsive Design\nThe Gradio interface is mobile-friendly and works on:\n\niPhone (Safari, Chrome)\nAndroid (Chrome, Firefox)\nTablets and iPads\nπŸ” Troubleshooting\nCommon Issues\n\"All RPC endpoints failed\"\n\nCheck internet connection\nRPC endpoints may be rate-limiting\nWait a few minutes and try again\nDiscord notifications not working\n\nVerify webhook URL is correct\nCheck channel permissions\nEnsure webhook hasn't been deleted\nApp won't start on Hugging Face\n\nCheck build logs in the space\nVerify all files are uploaded correctly\nEnsure requirements.txt is valid\nHigh memory usage\n\nReduce RPC_BATCH_SIZE to 50 or lower\nRestart the application periodically\nGetting Help\nCheck the build logs first\nVerify all environment variables\nTest with minimal configuration\nCheck Discord webhook with a simple test message\nπŸ“Š Performance Optimization\nFor High-Volume Mining\nSet RPC_BATCH_SIZE=100 (maximum)\nUse multiple RPC endpoints\nMonitor rate limits\nConsider using paid RPC services for better performance\nFor Low-Resource Environments\nSet RPC_BATCH_SIZE=25\nIncrease MINER_SLEEP=2.0\nReduce FEED_MAX_ITEMS=25\n🎯 Quick Start Summary\nFastest way to get running:\n\nFork this repository to your GitHub\nCreate Hugging Face Space with Gradio SDK\nUpload files: app.py, requirements.txt, README.md\nAdd Discord webhook (optional) in Space settings\nWait for build (2-3 minutes)\nStart mining and enjoy!\nTotal setup time: 5-10 minutes ⚑\n\nCheck the Hugging Face Spaces documentation for more advanced configuration options.\n","size_bytes":6578},"app.py":{"content":"\"\"\"\nHugging Face Space – Solana Key Generator & Miner\nSimple, reliable implementation optimized for cloud deployment\n\"\"\"\nimport os\nimport queue\nimport threading\nimport time\nimport base58\nimport json\nimport requests\nimport collections\nimport hashlib\nimport secrets\nfrom typing import List, Dict, Optional, Tuple\nfrom datetime import datetime\n\nimport gradio as gr\nfrom solana.rpc.api import Client\nfrom solana.rpc.core import RPCException\nfrom solders.keypair import Keypair\nfrom solders.pubkey import Pubkey\n\n# ---------- Safe keypair generator ----------\ndef _safe_keypair() -> Keypair:\n \"\"\"Keep drawing 64-byte seeds until Edwards point is valid.\"\"\"\n while True:\n try:\n return Keypair.from_bytes(os.urandom(64))\n except ValueError:\n continue\n\n# ---------- Enhanced Console Logger ----------\nimport logging\nlogging.basicConfig(level=logging.INFO, format=\"%(asctime)s %(message)s\")\nlog = logging.getLogger(\"solana_miner\")\n\n# ---------- Enhanced Configuration with Multi-Miner Support ----------\nclass Config:\n DISCORD_WEBHOOK = os.getenv(\"DISCORD_WEBHOOK\", \"\")\n MINER_ID = os.getenv(\"MINER_ID\", f\"Miner-{secrets.token_hex(4)}\")\n MINER_NAME = os.getenv(\"MINER_NAME\", f\"SolMiner-{secrets.token_hex(3)}\")\n LOCATION = os.getenv(\"MINER_LOCATION\", \"Unknown\")\n\n RPC_URLS = [\n \"https://api.mainnet-beta.solana.com\",\n \"https://solana-api.projectserum.com\", \n \"https://rpc.ankr.com/solana\",\n \"https://solana.public-rpc.com\"\n ]\n current_rpc_index = 0\n MIN_SOL = float(os.getenv(\"MIN_SOL\", \"0.00001\"))\n RPC_BATCH_SIZE = int(os.getenv(\"RPC_BATCH_SIZE\", \"100\"))\n MINER_SLEEP = float(os.getenv(\"MINER_SLEEP\", \"1.0\"))\n MAX_RETRIES = 2\n FEED_MAX_ITEMS = 50\n\n # Discord isolation settings\n DISCORD_RETRY_LIMIT = 3\n DISCORD_TIMEOUT = 5\n DISCORD_COOLDOWN = 300 # 5 minutes between reconnect attempts\n\n @classmethod\n def get_current_rpc(cls):\n return cls.RPC_URLS[cls.current_rpc_index]\n\n @classmethod\n def rotate_rpc(cls):\n cls.current_rpc_index = (cls.current_rpc_index + 1) % len(cls.RPC_URLS)\n log.info(f\"Switched to RPC: {cls.get_current_rpc()}\")\n\nconfig = Config()\n\n# ---------- Advanced Discord Management ----------\nSTATUS_MESSAGE_ID = None\nSTATUS_EDIT_URL = None\nDISCORD_DISABLED = False\nDISCORD_RETRY_COUNT = 0\nDISCORD_LAST_ERROR = None\nDISCORD_LAST_SUCCESS = time.time()\nMINER_START_TIME = datetime.now()\nDISCORD_QUEUE = queue.Queue(maxsize=1000) # Isolated queue for Discord operations\n\n# ---------- Enhanced Multi-Miner State Management ----------\nclass MinerState:\n def __init__(self):\n self.total_mined = 0\n self.funded_found = 0\n self.errors_count = 0\n self.last_funded_time = None\n self.run_flag = threading.Event()\n self.upload_queue = queue.Queue()\n self.lock = threading.Lock()\n\n # Enhanced tracking\n self.start_time = datetime.now()\n self.last_batch_time = None\n self.current_rpc = None\n self.rpc_switches = 0\n self.total_batches = 0\n self.average_batch_time = 0.0\n self.best_streak = 0\n self.current_streak = 0\n self.wallets_per_second = 0.0\n self.connection_status = \"Initializing\"\n self.last_activity = time.time()\n\n # Performance metrics\n self.batch_times = collections.deque(maxlen=100) # Last 100 batch times\n self.rpc_performance = {} # Track RPC response times\n \n # 30-minute cycle tracking\n self.cycle_start_time = time.time()\n self.cycle_active = True\n self.cycle_break_start = None\n self.total_cycles = 0\n self.in_break_mode = False\n\n def increment_mined(self):\n with self.lock: \n self.total_mined += 1\n\n def increment_errors(self):\n with self.lock: \n self.errors_count += 1\n\n def update_batch_stats(self, batch_size: int, batch_time: float, rpc_url: str):\n with self.lock:\n self.last_batch_time = datetime.now()\n self.total_batches += 1\n self.batch_times.append(batch_time)\n self.current_rpc = rpc_url\n self.last_activity = time.time()\n\n # Calculate averages\n if self.batch_times:\n self.average_batch_time = sum(self.batch_times) / len(self.batch_times)\n total_time = (datetime.now() - self.start_time).total_seconds()\n if total_time > 0:\n self.wallets_per_second = self.total_mined / total_time\n\n # Track RPC performance\n if rpc_url not in self.rpc_performance:\n self.rpc_performance[rpc_url] = []\n self.rpc_performance[rpc_url].append(batch_time)\n if len(self.rpc_performance[rpc_url]) > 50:\n self.rpc_performance[rpc_url].pop(0)\n\n def increment_funded(self):\n with self.lock:\n self.funded_found += 1\n self.last_funded_time = datetime.now()\n self.current_streak += 1\n if self.current_streak > self.best_streak:\n self.best_streak = self.current_streak\n\n def reset_streak(self):\n with self.lock:\n self.current_streak = 0\n\n def get_comprehensive_stats(self) -> Dict:\n with self.lock:\n uptime = datetime.now() - self.start_time\n return {\n # Basic stats\n 'total_mined': self.total_mined,\n 'funded_found': self.funded_found,\n 'errors_count': self.errors_count,\n 'last_funded': self.last_funded_time,\n 'queue_size': self.upload_queue.qsize(),\n 'is_running': self.run_flag.is_set(),\n\n # Enhanced stats\n 'miner_id': config.MINER_ID,\n 'miner_name': config.MINER_NAME,\n 'location': config.LOCATION,\n 'start_time': self.start_time,\n 'uptime_seconds': uptime.total_seconds(),\n 'uptime_str': str(uptime).split('.')[0],\n 'current_rpc': self.current_rpc or \"None\",\n 'rpc_switches': self.rpc_switches,\n 'total_batches': self.total_batches,\n 'average_batch_time': round(self.average_batch_time, 2),\n 'wallets_per_second': round(self.wallets_per_second, 2),\n 'best_streak': self.best_streak,\n 'current_streak': self.current_streak,\n 'connection_status': self.connection_status,\n 'last_activity': self.last_activity,\n\n # 30-minute cycle info\n 'cycle_active': self.cycle_active,\n 'in_break_mode': self.in_break_mode,\n 'total_cycles': self.total_cycles,\n 'cycle_time_remaining': self.get_cycle_time_remaining(),\n\n # Performance metrics\n 'batch_times_count': len(self.batch_times),\n 'rpc_performance': {rpc: round(sum(times)/len(times), 2) \n for rpc, times in self.rpc_performance.items() if times}\n }\n\n def get_cycle_time_remaining(self) -> Dict:\n \"\"\"Calculate remaining time in current cycle (30 min active / 30 min break)\"\"\"\n current_time = time.time()\n cycle_duration = 30 * 60 # 30 minutes in seconds\n \n if self.in_break_mode:\n # In break mode\n if self.cycle_break_start:\n elapsed_break = current_time - self.cycle_break_start\n remaining_break = max(0, cycle_duration - elapsed_break)\n return {\n 'mode': 'break',\n 'remaining_seconds': int(remaining_break),\n 'remaining_minutes': int(remaining_break / 60),\n 'progress_percent': min(100, (elapsed_break / cycle_duration) * 100)\n }\n else:\n # In mining mode\n elapsed_mining = current_time - self.cycle_start_time\n remaining_mining = max(0, cycle_duration - elapsed_mining)\n return {\n 'mode': 'mining',\n 'remaining_seconds': int(remaining_mining),\n 'remaining_minutes': int(remaining_mining / 60),\n 'progress_percent': min(100, (elapsed_mining / cycle_duration) * 100)\n }\n \n return {'mode': 'unknown', 'remaining_seconds': 0, 'remaining_minutes': 0, 'progress_percent': 0}\n\n def check_cycle_status(self) -> bool:\n \"\"\"Check if we should switch between mining and break mode. Returns True if should continue mining.\"\"\"\n current_time = time.time()\n cycle_duration = 30 * 60 # 30 minutes\n \n if self.in_break_mode:\n # Currently in break, check if break time is over\n if self.cycle_break_start and (current_time - self.cycle_break_start) >= cycle_duration:\n # Break is over, switch to mining\n self.in_break_mode = False\n self.cycle_active = True\n self.cycle_start_time = current_time\n self.cycle_break_start = None\n log.info(\"🟒 30-minute break completed, resuming mining...\")\n return True\n return False # Still in break\n else:\n # Currently mining, check if mining time is over\n if (current_time - self.cycle_start_time) >= cycle_duration:\n # Mining period is over, switch to break\n self.in_break_mode = True\n self.cycle_active = False\n self.cycle_break_start = current_time\n self.total_cycles += 1\n log.info(f\"πŸ”΄ 30-minute mining cycle #{self.total_cycles} completed, starting 30-minute break...\")\n return False\n return True # Continue mining\n\n def get_stats(self) -> Dict:\n # Maintain backward compatibility\n return self.get_comprehensive_stats()\n\nminer_state = MinerState()\n\n# ---------- Live Feed ----------\nclass LiveFeed:\n def __init__(self, max_items: int = 100):\n self.feed = collections.deque(maxlen=max_items)\n self.lock = threading.Lock()\n\n def add_entry(self, secret: str, sol: float, address: str = \"\"):\n with self.lock:\n timestamp = datetime.now().strftime('%H:%M:%S')\n if sol >= config.MIN_SOL:\n entry = f\"🟒 **FUNDED** {sol:.6f} SOL | `{secret[:20]}...` | {address[:20]}... | {timestamp}\"\n log.info(f\"πŸ’° FUNDED WALLET: {sol:.6f} SOL\")\n else:\n entry = f\"πŸ”΄ Empty | `{secret[:20]}...` | {timestamp}\"\n self.feed.append(entry)\n\n def get_feed(self) -> str:\n with self.lock: \n return \"\\n\".join(self.feed)\n\n def clear_feed(self):\n with self.lock: \n self.feed.clear()\n\nlive_feed = LiveFeed(config.FEED_MAX_ITEMS)\n\n# ---------- Key Generation ----------\nBASE58_ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\"\n\ndef generate_secure_keypair() -> Tuple[str, str, Keypair]:\n \"\"\"Generate a secure keypair with Base58 encoding\"\"\"\n for attempt in range(1000):\n try:\n keypair = _safe_keypair()\n seed = bytes(keypair)[:32]\n private_key_b58 = base58.b58encode(seed).decode('utf-8')\n public_key = str(keypair.pubkey())\n\n if len(private_key_b58) >= 32 and all(c in BASE58_ALPHABET for c in private_key_b58):\n return private_key_b58, public_key, keypair\n except Exception as e:\n log.warning(f\"Keypair attempt {attempt + 1} failed: {e}\")\n continue\n raise Exception(\"Failed to generate valid keypair after 1000 attempts\")\n\ndef get_key_info(private_key: str) -> Dict:\n try:\n decoded = base58.b58decode(private_key)\n keypair = _safe_keypair()\n return {\n \"private_key\": private_key,\n \"public_key\": str(keypair.pubkey()),\n \"key_length\": len(private_key),\n \"is_valid\": True,\n \"private_key_hex\": decoded.hex(),\n \"public_key_hex\": bytes(keypair.pubkey()).hex(),\n }\n except Exception as e:\n return {\"private_key\": private_key, \"error\": str(e), \"is_valid\": False}\n\n# ---------- Simple Solana Client ----------\ndef create_solana_client() -> Client:\n \"\"\"Create client with simple RPC rotation\"\"\"\n for attempt in range(len(config.RPC_URLS)):\n rpc_url = config.get_current_rpc()\n try:\n client = Client(rpc_url.strip())\n client.get_slot() # Test connection\n log.info(f\"βœ… Connected to Solana RPC: {rpc_url}\")\n return client\n except Exception as e:\n log.warning(f\"❌ RPC {rpc_url} failed: {e}\")\n config.rotate_rpc()\n time.sleep(2)\n\n raise Exception(\"All RPC endpoints failed\")\n\ndef get_balances_with_retry(client: Client, addresses: List[str]) -> List[float]:\n \"\"\"Simple balance checking with retry logic\"\"\"\n chunk_size = min(50, len(addresses))\n\n for attempt in range(config.MAX_RETRIES):\n try:\n all_balances = []\n\n for i in range(0, len(addresses), chunk_size):\n chunk = addresses[i:i + chunk_size]\n pubkeys = [Pubkey.from_string(addr) for addr in chunk]\n\n time.sleep(0.5) # Rate limiting\n resp = client.get_multiple_accounts(pubkeys)\n\n chunk_balances = []\n for acc in resp.value:\n chunk_balances.append((acc.lamports / 1e9) if acc else 0.0)\n all_balances.extend(chunk_balances)\n\n # Small delay between chunks\n if i + chunk_size < len(addresses):\n time.sleep(0.2)\n\n return all_balances\n\n except Exception as e:\n log.warning(f\"Balance check attempt {attempt + 1} failed: {e}\")\n miner_state.increment_errors()\n config.rotate_rpc()\n time.sleep(2)\n\n return [0.0] * len(addresses)\n\n# ---------- Isolated Discord Operations ----------\ndef queue_discord_message(message_type: str, data: dict):\n \"\"\"Queue Discord message for isolated processing\"\"\"\n if not config.DISCORD_WEBHOOK:\n return\n\n try:\n DISCORD_QUEUE.put_nowait({\n 'type': message_type,\n 'data': data,\n 'timestamp': time.time()\n })\n except queue.Full:\n # If queue is full, remove oldest message and add new one\n try:\n DISCORD_QUEUE.get_nowait()\n DISCORD_QUEUE.put_nowait({\n 'type': message_type,\n 'data': data,\n 'timestamp': time.time()\n })\n except:\n pass # Silently fail to avoid impacting mining\n\ndef send_funded_ping(private_key: str, public_key: str, balance: float):\n \"\"\"Queue funded wallet notification - never blocks mining\"\"\"\n stats = miner_state.get_comprehensive_stats()\n queue_discord_message('funded_wallet', {\n 'private_key': private_key,\n 'public_key': public_key,\n 'balance': balance,\n 'miner_stats': stats,\n 'discovery_time': datetime.now().isoformat()\n })\n\ndef process_funded_wallet_message(data: dict):\n \"\"\"Process funded wallet Discord message\"\"\"\n stats = data['miner_stats']\n payload = {\n \"content\": f\"@everyone 🚨 **{stats['miner_name']}** found FUNDED wallet!\",\n \"embeds\": [{\n \"title\": f\"πŸ’° FUNDED WALLET DISCOVERED - {stats['miner_name']}\",\n \"color\": 0x00ff00,\n \"thumbnail\": {\"url\": \"https://cryptologos.cc/logos/solana-sol-logo.png\"},\n \"fields\": [\n {\"name\": \"πŸ’Ό Wallet Details\", \"value\": \n f\"**Balance:** {data['balance']:.8f} SOL\\n\"\n f\"**Public Key:** `{data['public_key']}`\\n\"\n f\"**Private Key:** ||{data['private_key']}||\", \"inline\": False},\n\n {\"name\": \"πŸ† Miner Performance\", \"value\": \n f\"**Total Mined:** {stats['total_mined']:,} wallets\\n\"\n f\"**Total Funded:** {stats['funded_found']} wallets\\n\"\n f\"**Success Rate:** {(stats['funded_found']/max(stats['total_mined'],1)*100):.6f}%\", \"inline\": True},\n\n {\"name\": \"⚑ Current Stats\", \"value\": \n f\"**Speed:** {stats['wallets_per_second']:.1f} wallets/sec\\n\"\n f\"**Uptime:** {stats['uptime_str']}\\n\"\n f\"**Current Streak:** {stats['current_streak']}\", \"inline\": True},\n\n {\"name\": \"🌐 Miner Info\", \"value\": \n f\"**ID:** {stats['miner_id']}\\n\"\n f\"**Location:** {stats['location']}\\n\"\n f\"**RPC:** {stats['current_rpc'].split('//')[-1][:25]}\", \"inline\": True},\n\n {\"name\": \"πŸ“ˆ Network Stats\", \"value\": \n f\"**Batches Processed:** {stats['total_batches']}\\n\"\n f\"**Avg Batch Time:** {stats['average_batch_time']}s\\n\"\n f\"**RPC Switches:** {stats['rpc_switches']}\", \"inline\": True},\n\n {\"name\": \"πŸ•’ Discovery Time\", \"value\": f\"<t:{int(time.time())}:F>\", \"inline\": False}\n ],\n \"footer\": {\"text\": f\"Miner: {stats['miner_name']} | Best Streak: {stats['best_streak']}\"}\n }]\n }\n\n return requests.post(config.DISCORD_WEBHOOK, data=json.dumps(payload),\n headers={\"Content-Type\": \"application/json\"}, \n timeout=config.DISCORD_TIMEOUT)\n\ndef queue_status_update():\n \"\"\"Queue status update - never blocks mining\"\"\"\n stats = miner_state.get_comprehensive_stats()\n queue_discord_message('status_update', {\n 'stats': stats,\n 'timestamp': time.time()\n })\n\ndef process_status_update(data: dict):\n \"\"\"Process comprehensive status update\"\"\"\n global STATUS_MESSAGE_ID, STATUS_EDIT_URL\n stats = data['stats']\n\n # Enhanced status embed with comprehensive information\n embed = {\n \"title\": f\"πŸͺ™ {stats['miner_name']} - Live Mining Status\",\n \"color\": 0x0099ff if stats['is_running'] else 0xff4444,\n \"thumbnail\": {\"url\": \"https://cryptologos.cc/logos/solana-sol-logo.png\"},\n \"fields\": [\n {\"name\": \"πŸ“ˆ Core Statistics\", \"value\": \n f\"**Status:** {'🟒 MINING' if stats['is_running'] else 'πŸ”΄ STOPPED'}\\n\"\n f\"**Total Mined:** {stats['total_mined']:,} wallets\\n\"\n f\"**Funded Found:** {stats['funded_found']} wallets\\n\"\n f\"**Success Rate:** {(stats['funded_found']/max(stats['total_mined'],1)*100):.6f}%\", \"inline\": True},\n\n {\"name\": \"⚑ Performance Metrics\", \"value\": \n f\"**Speed:** {stats['wallets_per_second']:.2f} wallets/sec\\n\"\n f\"**Uptime:** {stats['uptime_str']}\\n\"\n f\"**Batches:** {stats['total_batches']}\\n\"\n f\"**Avg Batch Time:** {stats['average_batch_time']}s\", \"inline\": True},\n\n {\"name\": \"πŸŽ† Streak & Records\", \"value\": \n f\"**Current Streak:** {stats['current_streak']}\\n\"\n f\"**Best Streak:** {stats['best_streak']}\\n\"\n f\"**Errors:** {stats['errors_count']}\\n\"\n f\"**Queue Size:** {stats['queue_size']}\", \"inline\": True},\n\n {\"name\": \"🌐 Network & Infrastructure\", \"value\": \n f\"**Current RPC:** {stats['current_rpc'].split('//')[-1][:30] if stats['current_rpc'] else 'None'}\\n\"\n f\"**RPC Switches:** {stats['rpc_switches']}\\n\"\n f\"**Connection:** {stats['connection_status']}\\n\"\n f\"**Location:** {stats['location']}\", \"inline\": False},\n\n {\"name\": \"πŸ•°οΈ Timing Information\", \"value\": \n f\"**Started:** <t:{int(stats['start_time'].timestamp())}:R>\\n\"\n f\"**Last Activity:** <t:{int(stats['last_activity'])}:R>\\n\"\n f\"**Last Funded:** {'<t:' + str(int(stats['last_funded'].timestamp())) + ':R>' if stats['last_funded'] else 'Never'}\\n\"\n f\"**Update:** <t:{int(time.time())}:f>\", \"inline\": False}\n ],\n \"footer\": {\n \"text\": f\"Miner ID: {stats['miner_id']} | Batch #{stats['total_batches']}\",\n \"icon_url\": \"https://cryptologos.cc/logos/solana-sol-logo.png\"\n },\n \"timestamp\": datetime.utcnow().isoformat()\n }\n\n # Add RPC performance if available\n if stats['rpc_performance']:\n rpc_perf = \"\\n\".join([f\"**{rpc.split('//')[-1][:20]}:** {avg_time}s\" \n for rpc, avg_time in stats['rpc_performance'].items()])\n embed[\"fields\"].append({\n \"name\": \"πŸš€ RPC Performance\", \n \"value\": rpc_perf[:1000], \n \"inline\": False\n })\n\n # First message or edit existing\n if STATUS_MESSAGE_ID is None:\n payload = {\"embeds\": [embed]}\n r = requests.post(config.DISCORD_WEBHOOK + \"?wait=true\",\n data=json.dumps(payload),\n headers={\"Content-Type\": \"application/json\"}, \n timeout=config.DISCORD_TIMEOUT)\n if r.status_code == 200:\n data = r.json()\n STATUS_MESSAGE_ID = data['id']\n STATUS_EDIT_URL = f\"{config.DISCORD_WEBHOOK}/messages/{STATUS_MESSAGE_ID}\"\n return r\n\n if STATUS_EDIT_URL:\n return requests.patch(STATUS_EDIT_URL, data=json.dumps({\"embeds\": [embed]}),\n headers={\"Content-Type\": \"application/json\"}, \n timeout=config.DISCORD_TIMEOUT)\n return None\n\ndef isolated_discord_worker():\n \"\"\"Completely isolated Discord worker - never affects mining\"\"\"\n global DISCORD_DISABLED, DISCORD_RETRY_COUNT, DISCORD_LAST_ERROR, DISCORD_LAST_SUCCESS\n\n log.info(f\"πŸ’Œ Discord worker started for miner: {config.MINER_NAME}\")\n\n while True:\n try:\n # Process Discord queue without blocking\n try:\n message = DISCORD_QUEUE.get(timeout=1)\n\n # Skip old messages (older than 5 minutes)\n if time.time() - message['timestamp'] > 300:\n continue\n\n # Process message based on type\n response = None\n if message['type'] == 'funded_wallet':\n response = process_funded_wallet_message(message['data'])\n elif message['type'] == 'status_update':\n response = process_status_update(message['data'])\n elif message['type'] == 'miner_startup':\n response = process_miner_startup(message['data'])\n\n # Handle response\n if response and response.status_code in [200, 204]:\n DISCORD_RETRY_COUNT = 0\n DISCORD_LAST_SUCCESS = time.time()\n DISCORD_DISABLED = False\n log.info(f\"πŸ’¬ Discord message sent: {message['type']}\")\n elif response:\n raise Exception(f\"Discord API returned {response.status_code}: {response.text[:100]}\")\n\n except queue.Empty:\n # No messages to process, continue\n pass\n except requests.exceptions.RequestException as e:\n # Network-related errors\n DISCORD_RETRY_COUNT += 1\n DISCORD_LAST_ERROR = f\"Network error: {str(e)[:100]}\"\n\n if DISCORD_RETRY_COUNT >= config.DISCORD_RETRY_LIMIT:\n if not DISCORD_DISABLED:\n log.info(f\"πŸ”‡ Discord temporarily disabled after {DISCORD_RETRY_COUNT} failures. Will retry in {config.DISCORD_COOLDOWN}s\")\n DISCORD_DISABLED = True\n time.sleep(config.DISCORD_COOLDOWN) # Long cooldown\n DISCORD_RETRY_COUNT = 0 # Reset after cooldown\n else:\n time.sleep(min(10, DISCORD_RETRY_COUNT * 2)) # Exponential backoff\n\n except Exception as e:\n # Other errors\n DISCORD_LAST_ERROR = f\"Processing error: {str(e)[:100]}\"\n log.warning(f\"⚠️ Discord processing error: {e}\")\n time.sleep(5)\n\n # Auto-queue status updates every 2 minutes when not disabled\n if not DISCORD_DISABLED and time.time() - DISCORD_LAST_SUCCESS > 120:\n queue_status_update()\n\n except Exception as e:\n # Critical error handler - never crash the Discord worker\n log.error(f\"🚨 Critical Discord worker error: {e}\")\n time.sleep(30) # Long sleep after critical errors\n\n time.sleep(0.1) # Small sleep to prevent tight loop\n\ndef process_miner_startup(data: dict):\n \"\"\"Process miner startup notification\"\"\"\n stats = data['stats']\n payload = {\n \"content\": f\"πŸš€ **{stats['miner_name']}** has started mining!\",\n \"embeds\": [{\n \"title\": f\"πŸš€ New Miner Online - {stats['miner_name']}\",\n \"color\": 0x00ff88,\n \"fields\": [\n {\"name\": \"πŸŽ† Miner Information\", \"value\": \n f\"**Name:** {stats['miner_name']}\\n\"\n f\"**ID:** {stats['miner_id']}\\n\"\n f\"**Location:** {stats['location']}\\n\"\n f\"**Started:** <t:{int(time.time())}:F>\", \"inline\": True},\n\n {\"name\": \"βš™οΈ Configuration\", \"value\": \n f\"**Min SOL:** {config.MIN_SOL}\\n\"\n f\"**Batch Size:** {config.RPC_BATCH_SIZE}\\n\"\n f\"**Sleep Time:** {config.MINER_SLEEP}s\\n\"\n f\"**RPC Endpoints:** {len(config.RPC_URLS)}\", \"inline\": True}\n ],\n \"footer\": {\"text\": f\"Miner ready to start discovering funded wallets!\"}\n }]\n }\n\n return requests.post(config.DISCORD_WEBHOOK, data=json.dumps(payload),\n headers={\"Content-Type\": \"application/json\"}, \n timeout=config.DISCORD_TIMEOUT)\n\n# Start isolated Discord worker\nthreading.Thread(target=isolated_discord_worker, daemon=True).start()\n\n# Queue startup notification\nif config.DISCORD_WEBHOOK:\n queue_discord_message('miner_startup', {\n 'stats': {\n 'miner_name': config.MINER_NAME,\n 'miner_id': config.MINER_ID,\n 'location': config.LOCATION\n }\n })\n\n# Auto-start mining code will be placed after mining_loop function is defined\n\ndef upload_daemon():\n \"\"\"Background uploader for funded wallets - integrated with new Discord system\"\"\"\n while True:\n try:\n private_key, public_key, balance = miner_state.upload_queue.get(timeout=1)\n # Use the new isolated Discord system\n send_funded_ping(private_key, public_key, balance)\n miner_state.upload_queue.task_done()\n except queue.Empty:\n continue\n except Exception as e:\n log.error(f\"Upload daemon error: {e}\")\n\nthreading.Thread(target=upload_daemon, daemon=True).start()\n\n# ---------- Simple Mining Loop ----------\ndef mining_loop():\n \"\"\"Main mining loop with 30-minute cycle management\"\"\"\n log.info(\"πŸš€ Mining loop started with 30-minute cycles\")\n log.info(f\"🏁 Run flag status: {miner_state.run_flag.is_set()}\")\n client = None\n consecutive_errors = 0\n\n batch_private_keys, batch_addresses = [], []\n\n while miner_state.run_flag.is_set():\n try:\n # Check 30-minute cycle status\n should_mine = miner_state.check_cycle_status()\n if not should_mine:\n # In break mode, sleep and continue\n miner_state.connection_status = \"On Break (30 min cycle)\"\n log.info(f\"πŸ’€ In break mode, sleeping for 60 seconds...\")\n time.sleep(60) # Check every minute during break\n continue\n \n miner_state.connection_status = \"Mining Active\"\n log.info(f\"⛏️ Starting mining batch of {config.RPC_BATCH_SIZE} wallets...\")\n # Ensure client connection\n if client is None:\n try:\n client = create_solana_client()\n consecutive_errors = 0\n except Exception as e:\n log.error(f\"Cannot connect to RPC: {e}\")\n time.sleep(10)\n continue\n\n # Generate keypair batch\n log.info(f\"πŸ”‘ Generating batch of {config.RPC_BATCH_SIZE} keypairs...\")\n while len(batch_addresses) < config.RPC_BATCH_SIZE and miner_state.run_flag.is_set():\n try:\n private_key, public_key, _ = generate_secure_keypair()\n batch_private_keys.append(private_key)\n batch_addresses.append(public_key)\n miner_state.increment_mined()\n\n if len(batch_addresses) % 20 == 0:\n log.info(f\"Generated {len(batch_addresses)} keypairs so far...\")\n time.sleep(0.01) # Prevent CPU hogging\n\n except Exception as e:\n log.error(f\"Keypair generation error: {e}\")\n continue\n \n log.info(f\"βœ… Generated {len(batch_addresses)} keypairs, checking balances...\")\n\n # Check balances\n if batch_addresses:\n batch_start_time = time.time()\n log.info(f\"πŸ” Checking {len(batch_addresses)} addresses...\")\n balances = get_balances_with_retry(client, batch_addresses)\n\n if not balances or len(balances) != len(batch_addresses):\n log.warning(\"RPC response mismatch, reconnecting...\")\n client = None\n continue\n\n funded_in_batch = 0\n for i, balance in enumerate(balances):\n if balance >= config.MIN_SOL:\n priv, addr = batch_private_keys[i], batch_addresses[i]\n funded_in_batch += 1\n miner_state.increment_funded()\n miner_state.upload_queue.put((priv, addr, balance))\n log.info(f\"πŸ’° FUNDED: {balance:.8f} SOL | {addr}\")\n live_feed.add_entry(priv, balance, addr)\n elif i % 50 == 0: # Sample empty wallets\n live_feed.add_entry(batch_private_keys[i], balance, batch_addresses[i])\n\n log.info(f\"βœ… Batch complete: {funded_in_batch} funded, {len(batch_addresses)} total\")\n\n # Update comprehensive stats\n batch_time = time.time() - batch_start_time\n miner_state.update_batch_stats(len(batch_addresses), batch_time, config.get_current_rpc())\n miner_state.connection_status = \"Active Mining\"\n\n # Reset batch\n batch_private_keys, batch_addresses = [], []\n consecutive_errors = 0\n\n # Queue status update every 50 batches or when funded wallet found\n if funded_in_batch > 0 or miner_state.total_batches % 50 == 0:\n queue_status_update()\n\n # Sleep between batches\n time.sleep(config.MINER_SLEEP)\n\n except Exception as e:\n consecutive_errors += 1\n log.error(f\"Mining loop error: {e}\")\n miner_state.increment_errors()\n\n if consecutive_errors >= 3:\n client = None\n miner_state.connection_status = \"Reconnecting\"\n miner_state.rpc_switches += 1\n log.info(\"Resetting RPC connection due to errors\")\n time.sleep(5)\n\n log.info(\"πŸ›‘ Mining loop stopped\")\n\n# Auto-start mining when app loads\nlog.info(\"πŸš€ Auto-starting mining on app launch...\")\nminer_state.run_flag.set()\nthreading.Thread(target=mining_loop, daemon=True).start()\n\n# ---------- Gradio Controls ----------\ndef start_mining() -> str:\n if miner_state.run_flag.is_set():\n return \"⚠️ Already running\"\n log.info(\"πŸš€ Starting mining manually via button...\")\n miner_state.run_flag.set()\n threading.Thread(target=mining_loop, daemon=True).start()\n return \"🟒 Mining started (background)\"\n\ndef stop_mining() -> str:\n if not miner_state.run_flag.is_set():\n return \"⚠️ Not running\"\n miner_state.run_flag.clear()\n return \"πŸ”΄ Mining stopped!\"\n\ndef get_mining_stats() -> str:\n stats = miner_state.get_comprehensive_stats()\n running = \"🟒 Running\" if stats['is_running'] else \"πŸ”΄ Stopped\"\n last = \"\"\n if stats['last_funded']:\n ago = (datetime.now() - stats['last_funded']).seconds\n last = f\" | Last funded: {ago//3600}h {(ago//60)%60}m ago\"\n \n # Add cycle information\n cycle_info = stats['cycle_time_remaining']\n if cycle_info['mode'] == 'break':\n cycle_status = f\"πŸ”΄ Break Mode ({cycle_info['remaining_minutes']}m left)\"\n elif cycle_info['mode'] == 'mining':\n cycle_status = f\"🟒 Mining ({cycle_info['remaining_minutes']}m left)\"\n else:\n cycle_status = \"πŸ”„ Cycle Starting\"\n \n return (f\"{running} | {cycle_status} | Cycles: {stats['total_cycles']} | \"\n f\"Mined: {stats['total_mined']:,} | Funded: {stats['funded_found']} | \"\n f\"Speed: {stats['wallets_per_second']:.1f}/s | Errors: {stats['errors_count']} | \"\n f\"Uptime: {stats['uptime_str']}{last}\")\n\ndef clear_feed() -> str:\n live_feed.clear_feed()\n return \"\"\n\ndef generate_single_key() -> tuple:\n try:\n private_key, public_key, _ = generate_secure_keypair()\n info = get_key_info(private_key)\n return private_key, public_key, info.get('private_key_hex', ''), str(info.get('key_length', 0))\n except Exception as e:\n log.error(f\"Key generation error: {e}\")\n err = f\"Error: {e}\"\n return err, err, err, err\n\ndef generate_bulk_keys(count: int) -> str:\n if count <= 0 or count > 1000:\n return \"❌ Enter 1-1000\"\n keys = []\n errors = 0\n for i in range(count):\n try:\n private_key, _, _ = generate_secure_keypair()\n keys.append(private_key)\n if count > 100 and (i + 1) % 50 == 0:\n log.info(f\"Generated {i + 1}/{count} keys...\")\n except Exception as e:\n errors += 1\n log.error(f\"Failed to generate key {i + 1}: {e}\")\n if errors > 10:\n return f\"❌ Too many errors. Generated {len(keys)} keys successfully.\"\n\n result = \"\\n\".join(keys)\n if errors > 0:\n result += f\"\\n\\n⚠️ Note: {errors} keys failed to generate\"\n return result\n\n# ---------- Gradio Interface ----------\ncss = \"\"\"\n#live_feed {\n font-family: monospace;\n font-size: 12px;\n max-height: 500px;\n overflow-y: auto;\n}\n\"\"\"\n\nwith gr.Blocks(title=\"Solana Key Generator & Miner\", css=css, theme=gr.themes.Soft()) as demo:\n\n gr.Markdown(f\"# πŸ” Enhanced Solana Key Generator & Miner\")\n gr.Markdown(f\"**{config.MINER_NAME}** ({config.MINER_ID}) - Multi-miner Discord integration enabled!\")\n gr.Markdown(\"Optimized for Hugging Face Spaces - runs forever even if you close the browser.\")\n\n with gr.Tab(\"🎲 Single Key Generator\"):\n with gr.Row():\n gen_btn = gr.Button(\"🎯 Generate New Keypair\", variant=\"primary\")\n with gr.Row():\n private_key_out = gr.Textbox(label=\"πŸ” Private Key (Base58)\", show_copy_button=True)\n public_key_out = gr.Textbox(label=\"πŸ“ Public Address\", show_copy_button=True)\n with gr.Row():\n private_hex_out = gr.Textbox(label=\"πŸ”’ Private Key (Hex)\", show_copy_button=True)\n key_info_out = gr.Textbox(label=\"ℹ️ Key Information\", interactive=False)\n gen_btn.click(generate_single_key, outputs=[private_key_out, public_key_out, private_hex_out, key_info_out])\n\n with gr.Tab(\"πŸ“¦ Bulk Key Generator\"):\n count = gr.Slider(1, 1000, value=10, step=1, label=\"Number of Keys\")\n btn = gr.Button(\"πŸš€ Generate Bulk Keys\", variant=\"primary\")\n keys = gr.Textbox(label=\"Generated Private Keys\", lines=20, show_copy_button=True)\n btn.click(generate_bulk_keys, inputs=count, outputs=keys)\n\n with gr.Tab(\"πŸͺ™ Wallet Miner\"):\n with gr.Row():\n start_btn = gr.Button(\"🟒 Start Mining\", variant=\"primary\", size=\"lg\")\n stop_btn = gr.Button(\"πŸ”΄ Stop Mining\", variant=\"stop\", size=\"lg\")\n clear_btn = gr.Button(\"🧹 Clear Feed\", variant=\"secondary\")\n status = gr.Textbox(label=\"🎯 Mining Status\", value=\"Ready to start mining...\", interactive=False)\n stats_display = gr.Textbox(label=\"πŸ“Š Real-time Statistics\", interactive=False)\n live_feed_display = gr.Textbox(label=\"πŸ“‘ Live Mining Feed\", lines=25, max_lines=30, interactive=False, elem_id=\"live_feed\")\n\n start_btn.click(start_mining, outputs=status)\n stop_btn.click(stop_mining, outputs=status)\n clear_btn.click(clear_feed, outputs=live_feed_display)\n\n # Auto-refresh for real-time updates\n def _refresh():\n return get_mining_stats(), live_feed.get_feed()\n\n refresh_btn = gr.Button(\"πŸ”„ Refresh\", visible=False)\n refresh_btn.click(_refresh, outputs=[stats_display, live_feed_display])\n\n # Set up auto-refresh after all components are defined\n demo.load(_refresh, outputs=[stats_display, live_feed_display])\n\nif __name__ == \"__main__\":\n # Multi-platform compatibility: 7860 for Hugging Face, 5000 for Replit\n port = int(os.environ.get('PORT', 7860))\n \n # Detect if running on Replit\n if os.environ.get('REPLIT_DB_URL') or os.environ.get('REPL_ID'):\n port = 5000\n \n demo.queue().launch(\n server_name=\"0.0.0.0\", \n server_port=port, \n share=False, \n show_error=True\n )","size_bytes":37878},"replit.md":{"content":"# Solana Key Generator & Miner\n\n## Overview\nThis is a Solana key mining application built with Gradio that generates Ed25519 Base-58 keys and mines Solana addresses in real time with Discord notifications. The application was originally designed for Hugging Face Spaces and has been successfully adapted for the Replit environment.\n\n## Project Architecture\n- **Language**: Python 3.11\n- **Framework**: Gradio for web interface\n- **Main Components**:\n - Key generation system using solders and solana libraries\n - Real-time mining with RPC endpoint rotation\n - Discord webhook integration for notifications\n - Live feed of mining activity\n - Bulk key generation capabilities\n\n## Current Status\n- βœ… Python 3.11 installed and configured\n- βœ… All dependencies installed successfully\n- βœ… Application running on port 5000\n- βœ… Workflow configured for automatic startup\n- βœ… .gitignore file created for Python project\n- βœ… Compatible with Replit environment\n\n## Dependencies\nThe application uses the following key packages:\n- `gradio>=4.44.0` - Web interface framework\n- `solana>=0.34.3` - Solana blockchain interaction\n- `solders>=0.21.0` - Solana SDK for Python\n- `base58>=2.1.1` - Base58 encoding/decoding\n- `requests>=2.32.0` - HTTP requests for Discord webhooks\n- `python-dotenv>=1.0.1` - Environment variable management\n- `pydantic>=2.9.0` - Data validation\n\n## Features\n1. **Key Generation**: Generate secure Ed25519 keypairs with Base-58 encoding\n2. **Real-time Mining**: Continuously mine wallets checking for funded addresses\n3. **Discord Integration**: Automated notifications when funded wallets are discovered\n4. **Multi-RPC Support**: Automatic failover between multiple Solana RPC endpoints\n5. **Live Statistics**: Real-time performance metrics and mining statistics\n6. **Bulk Operations**: Generate up to 1000 keys at once\n\n## Configuration\nThe application supports environment variables for configuration:\n- `DISCORD_WEBHOOK` - Discord webhook URL for notifications (optional)\n- `MIN_SOL` - Minimum SOL balance to consider a wallet \"funded\" (default: 0.00001)\n- `RPC_BATCH_SIZE` - Number of wallets to check per RPC call (default: 100, max: 100)\n- `MINER_SLEEP` - Seconds between mining cycles (default: 1.0)\n- `PORT` - Application port (automatically set to 5000 for Replit)\n\n## Setup Notes\n- The application is configured to use port 5000 which is compatible with Replit\n- Host is set to 0.0.0.0 to allow external access through Replit's proxy\n- All RPC endpoints are external and don't require local Solana node\n- Discord integration is optional but recommended for notifications\n\n## Recent Changes\n- Adapted from Hugging Face Spaces to Replit environment\n- Maintained all original functionality\n- Configured proper networking for Replit's infrastructure\n- Added Python .gitignore for clean repository management","size_bytes":2838}},"version":1}
check/.local/state/replit/agent/repl_state.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:61259f05d50943542ee0c6a2f074927e34be4050b7a98a25a54b59f3ad7b8f20
3
+ size 364
check/.replit ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ modules = ["python-3.11"]
2
+ [agent]
3
+ expertMode = true
4
+
5
+ [nix]
6
+ channel = "stable-25_05"
7
+ packages = ["ffmpeg-full", "libxcrypt"]
8
+
9
+ [[ports]]
10
+ localPort = 5000
11
+ externalPort = 80
12
+
13
+ [workflows]
14
+ runButton = "Project"
15
+
16
+ [[workflows.workflow]]
17
+ name = "Project"
18
+ mode = "parallel"
19
+ author = "agent"
20
+
21
+ [[workflows.workflow.tasks]]
22
+ task = "workflow.run"
23
+ args = "Solana Miner"
24
+
25
+ [[workflows.workflow]]
26
+ name = "Solana Miner"
27
+ author = "agent"
28
+
29
+ [[workflows.workflow.tasks]]
30
+ task = "shell.exec"
31
+ args = "python app.py"
32
+ waitForPort = 5000
33
+
34
+ [workflows.workflow.metadata]
35
+ outputType = "webview"
36
+
37
+ [deployment]
38
+ deploymentTarget = "autoscale"
check/README.md ADDED
@@ -0,0 +1,251 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # πŸ” Solana Key Generator & Live Miner
3
+
4
+ A comprehensive Solana wallet mining application that generates Ed25519 Base-58 keys and mines Solana addresses in real-time with advanced Discord notifications and multi-platform support.
5
+
6
+ ## 🌟 Complete Feature Overview
7
+
8
+ ### 🎲 Single Key Generation
9
+ - **Secure Keypair Generation**: Creates cryptographically secure Ed25519 keypairs
10
+ - **Base58 Encoding**: Private keys encoded in standard Solana Base58 format
11
+ - **Multiple Format Support**: Provides both Base58 and hexadecimal representations
12
+ - **Key Validation**: Automatic validation of generated keypairs
13
+ - **Copy-to-Clipboard**: One-click copying for all generated keys
14
+ - **Key Information Display**: Shows key length, format validation, and technical details
15
+
16
+ ### πŸ“¦ Bulk Key Generation
17
+ - **High-Volume Generation**: Generate up to 1,000 keys in a single batch
18
+ - **Progress Tracking**: Real-time progress updates for large batches
19
+ - **Error Handling**: Robust error recovery and reporting
20
+ - **Batch Export**: All keys provided in easy-to-copy format
21
+ - **Performance Optimized**: Efficient generation with CPU throttling prevention
22
+ - **Memory Management**: Optimized for large key batches without memory issues
23
+
24
+ ### πŸͺ™ Advanced Wallet Mining System
25
+
26
+ #### ⛏️ Core Mining Features
27
+ - **Real-Time Mining**: Continuous background mining with 100 wallets per batch
28
+ - **30-Minute Cycle Management**: Intelligent mining cycles (30 min active, 30 min break)
29
+ - **Multi-RPC Support**: Automatic failover between 4+ Solana RPC endpoints
30
+ - **Balance Detection**: Configurable minimum SOL threshold for "funded" wallets
31
+ - **Live Performance Metrics**: Real-time statistics and performance tracking
32
+ - **Auto-Recovery**: Automatic error recovery and RPC endpoint switching
33
+
34
+ #### πŸ“Š Comprehensive Statistics
35
+ - **Mining Performance**: Wallets per second, batch processing times
36
+ - **Success Tracking**: Total mined, funded wallets found, success rates
37
+ - **Streak Monitoring**: Current and best finding streaks
38
+ - **Uptime Tracking**: Total runtime and activity monitoring
39
+ - **RPC Performance**: Individual endpoint response time tracking
40
+ - **Error Analytics**: Comprehensive error counting and categorization
41
+
42
+ #### πŸ”„ Cycle Management
43
+ - **30-Minute Active Mining**: Intensive mining periods
44
+ - **30-Minute Break Periods**: Resource conservation and rate limit management
45
+ - **Cycle Progress Tracking**: Visual progress indicators for current cycle
46
+ - **Total Cycle Counting**: Historical cycle completion tracking
47
+ - **Automatic Transitions**: Seamless switching between mining and break modes
48
+
49
+ ### πŸ’¬ Discord Integration System
50
+
51
+ #### 🚨 Instant Notifications
52
+ - **Funded Wallet Alerts**: Immediate @everyone pings when funded wallets are discovered
53
+ - **Rich Embeds**: Detailed wallet information with private keys (spoiler tags)
54
+ - **Miner Identification**: Multi-miner support with unique IDs and names
55
+ - **Startup Notifications**: Automatic notifications when miners come online
56
+ - **Status Updates**: Regular mining status updates with comprehensive metrics
57
+
58
+ #### πŸ“ˆ Advanced Discord Features
59
+ - **Live Status Embeds**: Self-updating status messages every 60 seconds
60
+ - **Performance Metrics**: Detailed mining statistics in Discord
61
+ - **RPC Health Monitoring**: Network status and endpoint performance
62
+ - **Error Reporting**: Automatic error notifications and recovery status
63
+ - **Multi-Miner Support**: Support for multiple miners with unique identification
64
+
65
+ #### πŸ›‘οΈ Discord Reliability
66
+ - **Isolated Processing**: Discord operations never block mining operations
67
+ - **Retry Logic**: Automatic retry with exponential backoff
68
+ - **Rate Limit Handling**: Intelligent Discord API rate limit management
69
+ - **Fallback Systems**: Graceful degradation when Discord is unavailable
70
+ - **Queue Management**: Message queuing to prevent loss during outages
71
+
72
+ ### πŸ“‘ Live Feed System
73
+ - **Real-Time Updates**: Continuous feed of mining activity
74
+ - **Funded Wallet Highlighting**: Special formatting for successful finds
75
+ - **Empty Wallet Sampling**: Representative sampling of checked wallets
76
+ - **Timestamp Tracking**: Precise timing information for all activities
77
+ - **Feed Management**: Automatic cleanup and size management
78
+ - **Color Coding**: Visual distinction between funded and empty wallets
79
+
80
+ ### βš™οΈ Configuration & Customization
81
+
82
+ #### πŸ”§ Environment Variables
83
+ - `DISCORD_WEBHOOK`: Discord webhook URL for notifications
84
+ - `MIN_SOL`: Minimum SOL balance threshold (default: 0.00001)
85
+ - `RPC_BATCH_SIZE`: Wallets per RPC call (max: 100)
86
+ - `MINER_SLEEP`: Delay between mining cycles (default: 1.0s)
87
+ - `MINER_ID`: Unique miner identifier
88
+ - `MINER_NAME`: Human-readable miner name
89
+ - `MINER_LOCATION`: Geographic or logical location identifier
90
+ - `PORT`: Application port (auto-configured for platform)
91
+
92
+ #### 🌐 Multi-Platform Support
93
+ - **Replit Optimization**: Automatic port and host configuration for Replit
94
+ - **Hugging Face Spaces**: Full compatibility with HF Spaces environment
95
+ - **Local Development**: Complete local development support
96
+ - **Docker Ready**: Container deployment support
97
+ - **Cloud Platform**: AWS, Google Cloud, DigitalOcean compatibility
98
+
99
+ ### πŸš€ Performance & Reliability
100
+
101
+ #### ⚑ Performance Features
102
+ - **Batch Processing**: Efficient 100-wallet batches for optimal RPC usage
103
+ - **Connection Pooling**: Persistent RPC connections with health monitoring
104
+ - **Memory Optimization**: Efficient memory usage even during extended mining
105
+ - **CPU Throttling**: Prevents system overload during intensive operations
106
+ - **Background Processing**: Non-blocking operations for all mining activities
107
+
108
+ #### πŸ›‘οΈ Reliability Systems
109
+ - **Error Recovery**: Automatic recovery from network and RPC failures
110
+ - **Health Monitoring**: Continuous system health and performance monitoring
111
+ - **Graceful Degradation**: Continues operation even when some features fail
112
+ - **State Management**: Persistent mining state across connection issues
113
+ - **Logging System**: Comprehensive logging for debugging and monitoring
114
+
115
+ ### 🎨 User Interface
116
+
117
+ #### πŸ“± Responsive Web Interface
118
+ - **Gradio Framework**: Modern, responsive web interface
119
+ - **Mobile Friendly**: Full functionality on mobile devices and tablets
120
+ - **Real-Time Updates**: Live statistics and feed updates
121
+ - **Copy Functions**: One-click copying for all generated content
122
+ - **Color Coding**: Intuitive color schemes for different wallet states
123
+
124
+ #### πŸ–₯️ Control Features
125
+ - **Start/Stop Controls**: Easy mining control with instant response
126
+ - **Feed Management**: Clear and manage live mining feed
127
+ - **Statistics Display**: Comprehensive real-time performance metrics
128
+ - **Status Indicators**: Clear visual status of all system components
129
+
130
+ ### πŸ”’ Security & Best Practices
131
+
132
+ #### πŸ›‘οΈ Security Features
133
+ - **Secure Key Generation**: Cryptographically secure random number generation
134
+ - **Environment Variable Protection**: Secure handling of sensitive configuration
135
+ - **Input Validation**: Comprehensive validation of all user inputs
136
+ - **Error Isolation**: Isolated error handling prevents system compromise
137
+ - **Rate Limiting**: Built-in rate limiting for external API calls
138
+
139
+ #### πŸ“‹ Best Practices
140
+ - **Educational Purpose**: Clearly documented educational and research use
141
+ - **Responsible Mining**: Cycle-based mining to prevent excessive resource usage
142
+ - **Privacy Considerations**: Guidelines for handling discovered private keys
143
+ - **Network Etiquette**: Respectful use of public RPC endpoints
144
+
145
+ ### πŸ”§ Technical Specifications
146
+
147
+ #### πŸ“š Dependencies
148
+ - **Python 3.8+**: Core runtime requirement
149
+ - **Gradio 4.44.0+**: Web interface framework
150
+ - **Solana SDK**: Official Solana Python libraries
151
+ - **Solders**: High-performance Solana operations
152
+ - **Base58**: Standard Base58 encoding/decoding
153
+ - **Requests**: HTTP client for Discord and RPC operations
154
+ - **Pydantic**: Data validation and settings management
155
+
156
+ #### πŸ—οΈ Architecture
157
+ - **Multi-Threading**: Separate threads for mining, Discord, and UI
158
+ - **Queue Systems**: Thread-safe communication between components
159
+ - **State Management**: Centralized state management with thread safety
160
+ - **Modular Design**: Clear separation of concerns and functionality
161
+ - **Extensible Framework**: Easy to extend with additional features
162
+
163
+ ## πŸš€ Quick Start Guide
164
+
165
+ ### For Replit (Recommended)
166
+ 1. **Fork/Import**: Import this repository to your Replit account
167
+ 2. **Environment Setup**: Add Discord webhook in Secrets tab (optional)
168
+ 3. **Run**: Click the Run button - mining starts automatically
169
+ 4. **Monitor**: Watch real-time statistics and live feed
170
+ 5. **Control**: Use the web interface to start/stop and generate keys
171
+
172
+ ### Environment Configuration
173
+ Add these optional secrets in Replit's Secrets tab:
174
+ ```
175
+ DISCORD_WEBHOOK=your_webhook_url_here
176
+ MIN_SOL=0.00001
177
+ RPC_BATCH_SIZE=100
178
+ MINER_SLEEP=1.0
179
+ MINER_NAME=MyMiner
180
+ MINER_LOCATION=Replit
181
+ ```
182
+
183
+ ### Discord Setup
184
+ 1. Create a Discord webhook in your server
185
+ 2. Copy the webhook URL
186
+ 3. Add it to your Replit secrets as `DISCORD_WEBHOOK`
187
+ 4. Start mining and receive notifications automatically
188
+
189
+ ## πŸ“ˆ Mining Statistics Explained
190
+
191
+ - **Total Mined**: Total number of wallets generated and checked
192
+ - **Funded Found**: Number of wallets discovered with SOL balance
193
+ - **Success Rate**: Percentage of funded wallets vs total checked
194
+ - **Speed**: Current wallets per second processing rate
195
+ - **Uptime**: Total time the miner has been running
196
+ - **Cycle Info**: Current 30-minute cycle status and progress
197
+ - **RPC Performance**: Response times for different endpoints
198
+ - **Streak Tracking**: Current and best consecutive find streaks
199
+
200
+ ## 🎯 Use Cases
201
+
202
+ ### Educational & Research
203
+ - Cryptocurrency key generation education
204
+ - Blockchain probability demonstrations
205
+ - Cryptographic security research
206
+ - Academic blockchain projects
207
+
208
+ ### Development & Testing
209
+ - Solana development key generation
210
+ - Testing wallet functionalities
211
+ - Blockchain application development
212
+ - Security testing and validation
213
+
214
+ ### Mining & Discovery
215
+ - Probabilistic wallet discovery
216
+ - Network analysis and research
217
+ - Performance benchmarking
218
+ - System stress testing
219
+
220
+ ## ⚠️ Important Notes
221
+
222
+ ### Responsibility & Ethics
223
+ - This tool is for educational and research purposes
224
+ - Found private keys should be handled responsibly
225
+ - Respect network resources and rate limits
226
+ - Follow applicable laws and regulations
227
+
228
+ ### Technical Limitations
229
+ - Finding funded wallets is extremely rare (probabilistic)
230
+ - RPC endpoints may rate limit requests
231
+ - Discord notifications require webhook setup
232
+ - Performance varies based on network conditions
233
+
234
+ ### Privacy & Security
235
+ - Private keys are displayed in the interface
236
+ - Discord messages contain sensitive information
237
+ - Use private channels for Discord notifications
238
+ - Keep webhook URLs confidential
239
+
240
+ ## πŸ”— Platform Support
241
+
242
+ This application is optimized for:
243
+ - βœ… **Replit** (Recommended - Auto-configured)
244
+ - βœ… **Hugging Face Spaces** (Full compatibility)
245
+ - βœ… **Local Development** (Windows, macOS, Linux)
246
+ - βœ… **Docker Containers** (Ready for containerization)
247
+ - βœ… **Cloud Platforms** (AWS, GCP, DigitalOcean)
248
+
249
+ ---
250
+
251
+ **Built with ❀️ for the Solana community | Educational purposes only**
check/app.py ADDED
@@ -0,0 +1,915 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Hugging Face Space – Solana Key Generator & Miner
3
+ Simple, reliable implementation optimized for cloud deployment
4
+ """
5
+ import os
6
+ import queue
7
+ import threading
8
+ import time
9
+ import base58
10
+ import json
11
+ import requests
12
+ import collections
13
+ import hashlib
14
+ import secrets
15
+ from typing import List, Dict, Optional, Tuple
16
+ from datetime import datetime
17
+
18
+ import gradio as gr
19
+ from solana.rpc.api import Client
20
+ from solana.rpc.core import RPCException
21
+ from solders.keypair import Keypair
22
+ from solders.pubkey import Pubkey
23
+
24
+ # ---------- Safe keypair generator ----------
25
+ def _safe_keypair() -> Keypair:
26
+ """Generate a valid keypair using the standard method."""
27
+ # Use the standard Solana keypair generation
28
+ return Keypair()
29
+
30
+ # ---------- Enhanced Console Logger ----------
31
+ import logging
32
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s")
33
+ log = logging.getLogger("solana_miner")
34
+
35
+ # ---------- Enhanced Configuration with Multi-Miner Support ----------
36
+ class Config:
37
+ DISCORD_WEBHOOK = os.getenv("DISCORD_WEBHOOK", "")
38
+ MINER_ID = os.getenv("MINER_ID", f"Miner-{secrets.token_hex(4)}")
39
+ MINER_NAME = os.getenv("MINER_NAME", f"SolMiner-{secrets.token_hex(3)}")
40
+ LOCATION = os.getenv("MINER_LOCATION", "Unknown")
41
+
42
+ RPC_URLS = [
43
+ "https://api.mainnet-beta.solana.com",
44
+ "https://solana-api.projectserum.com",
45
+ "https://rpc.ankr.com/solana",
46
+ "https://solana.public-rpc.com"
47
+ ]
48
+ current_rpc_index = 0
49
+ MIN_SOL = float(os.getenv("MIN_SOL", "0.00001"))
50
+ RPC_BATCH_SIZE = int(os.getenv("RPC_BATCH_SIZE", "100"))
51
+ MINER_SLEEP = float(os.getenv("MINER_SLEEP", "1.0"))
52
+ MAX_RETRIES = 2
53
+ FEED_MAX_ITEMS = 50
54
+
55
+ # Discord isolation settings
56
+ DISCORD_RETRY_LIMIT = 3
57
+ DISCORD_TIMEOUT = 5
58
+ DISCORD_COOLDOWN = 300 # 5 minutes between reconnect attempts
59
+
60
+ @classmethod
61
+ def get_current_rpc(cls):
62
+ return cls.RPC_URLS[cls.current_rpc_index]
63
+
64
+ @classmethod
65
+ def rotate_rpc(cls):
66
+ cls.current_rpc_index = (cls.current_rpc_index + 1) % len(cls.RPC_URLS)
67
+ log.info(f"Switched to RPC: {cls.get_current_rpc()}")
68
+
69
+ config = Config()
70
+
71
+ # ---------- Advanced Discord Management ----------
72
+ STATUS_MESSAGE_ID = None
73
+ STATUS_EDIT_URL = None
74
+ DISCORD_DISABLED = False
75
+ DISCORD_RETRY_COUNT = 0
76
+ DISCORD_LAST_ERROR = None
77
+ DISCORD_LAST_SUCCESS = time.time()
78
+ MINER_START_TIME = datetime.now()
79
+ DISCORD_QUEUE = queue.Queue(maxsize=1000) # Isolated queue for Discord operations
80
+
81
+ # ---------- Enhanced Multi-Miner State Management ----------
82
+ class MinerState:
83
+ def __init__(self):
84
+ self.total_mined = 0
85
+ self.funded_found = 0
86
+ self.errors_count = 0
87
+ self.last_funded_time = None
88
+ self.run_flag = threading.Event()
89
+ self.upload_queue = queue.Queue()
90
+ self.lock = threading.Lock()
91
+
92
+ # Enhanced tracking
93
+ self.start_time = datetime.now()
94
+ self.last_batch_time = None
95
+ self.current_rpc = None
96
+ self.rpc_switches = 0
97
+ self.total_batches = 0
98
+ self.average_batch_time = 0.0
99
+ self.best_streak = 0
100
+ self.current_streak = 0
101
+ self.wallets_per_second = 0.0
102
+ self.connection_status = "Initializing"
103
+ self.last_activity = time.time()
104
+
105
+ # Performance metrics
106
+ self.batch_times = collections.deque(maxlen=100) # Last 100 batch times
107
+ self.rpc_performance = {} # Track RPC response times
108
+
109
+ # 30-minute cycle tracking
110
+ self.cycle_start_time = time.time()
111
+ self.cycle_active = True
112
+ self.cycle_break_start = None
113
+ self.total_cycles = 0
114
+ self.in_break_mode = False
115
+
116
+ def increment_mined(self):
117
+ with self.lock:
118
+ self.total_mined += 1
119
+
120
+ def increment_errors(self):
121
+ with self.lock:
122
+ self.errors_count += 1
123
+
124
+ def update_batch_stats(self, batch_size: int, batch_time: float, rpc_url: str):
125
+ with self.lock:
126
+ self.last_batch_time = datetime.now()
127
+ self.total_batches += 1
128
+ self.batch_times.append(batch_time)
129
+ self.current_rpc = rpc_url
130
+ self.last_activity = time.time()
131
+
132
+ # Calculate averages
133
+ if self.batch_times:
134
+ self.average_batch_time = sum(self.batch_times) / len(self.batch_times)
135
+ total_time = (datetime.now() - self.start_time).total_seconds()
136
+ if total_time > 0:
137
+ self.wallets_per_second = self.total_mined / total_time
138
+
139
+ # Track RPC performance
140
+ if rpc_url not in self.rpc_performance:
141
+ self.rpc_performance[rpc_url] = []
142
+ self.rpc_performance[rpc_url].append(batch_time)
143
+ if len(self.rpc_performance[rpc_url]) > 50:
144
+ self.rpc_performance[rpc_url].pop(0)
145
+
146
+ def increment_funded(self):
147
+ with self.lock:
148
+ self.funded_found += 1
149
+ self.last_funded_time = datetime.now()
150
+ self.current_streak += 1
151
+ if self.current_streak > self.best_streak:
152
+ self.best_streak = self.current_streak
153
+
154
+ def reset_streak(self):
155
+ with self.lock:
156
+ self.current_streak = 0
157
+
158
+ def get_comprehensive_stats(self) -> Dict:
159
+ with self.lock:
160
+ uptime = datetime.now() - self.start_time
161
+ return {
162
+ # Basic stats
163
+ 'total_mined': self.total_mined,
164
+ 'funded_found': self.funded_found,
165
+ 'errors_count': self.errors_count,
166
+ 'last_funded': self.last_funded_time,
167
+ 'queue_size': self.upload_queue.qsize(),
168
+ 'is_running': self.run_flag.is_set(),
169
+
170
+ # Enhanced stats
171
+ 'miner_id': config.MINER_ID,
172
+ 'miner_name': config.MINER_NAME,
173
+ 'location': config.LOCATION,
174
+ 'start_time': self.start_time,
175
+ 'uptime_seconds': uptime.total_seconds(),
176
+ 'uptime_str': str(uptime).split('.')[0],
177
+ 'current_rpc': self.current_rpc or "None",
178
+ 'rpc_switches': self.rpc_switches,
179
+ 'total_batches': self.total_batches,
180
+ 'average_batch_time': round(self.average_batch_time, 2),
181
+ 'wallets_per_second': round(self.wallets_per_second, 2),
182
+ 'best_streak': self.best_streak,
183
+ 'current_streak': self.current_streak,
184
+ 'connection_status': self.connection_status,
185
+ 'last_activity': self.last_activity,
186
+
187
+ # 30-minute cycle info
188
+ 'cycle_active': self.cycle_active,
189
+ 'in_break_mode': self.in_break_mode,
190
+ 'total_cycles': self.total_cycles,
191
+ 'cycle_time_remaining': self.get_cycle_time_remaining(),
192
+
193
+ # Performance metrics
194
+ 'batch_times_count': len(self.batch_times),
195
+ 'rpc_performance': {rpc: round(sum(times)/len(times), 2)
196
+ for rpc, times in self.rpc_performance.items() if times}
197
+ }
198
+
199
+ def get_cycle_time_remaining(self) -> Dict:
200
+ """Calculate remaining time in current cycle (30 min active / 30 min break)"""
201
+ current_time = time.time()
202
+ cycle_duration = 30 * 60 # 30 minutes in seconds
203
+
204
+ if self.in_break_mode:
205
+ # In break mode
206
+ if self.cycle_break_start:
207
+ elapsed_break = current_time - self.cycle_break_start
208
+ remaining_break = max(0, cycle_duration - elapsed_break)
209
+ return {
210
+ 'mode': 'break',
211
+ 'remaining_seconds': int(remaining_break),
212
+ 'remaining_minutes': int(remaining_break / 60),
213
+ 'progress_percent': min(100, (elapsed_break / cycle_duration) * 100)
214
+ }
215
+ else:
216
+ # In mining mode
217
+ elapsed_mining = current_time - self.cycle_start_time
218
+ remaining_mining = max(0, cycle_duration - elapsed_mining)
219
+ return {
220
+ 'mode': 'mining',
221
+ 'remaining_seconds': int(remaining_mining),
222
+ 'remaining_minutes': int(remaining_mining / 60),
223
+ 'progress_percent': min(100, (elapsed_mining / cycle_duration) * 100)
224
+ }
225
+
226
+ return {'mode': 'unknown', 'remaining_seconds': 0, 'remaining_minutes': 0, 'progress_percent': 0}
227
+
228
+ def check_cycle_status(self) -> bool:
229
+ """Check if we should switch between mining and break mode. Returns True if should continue mining."""
230
+ current_time = time.time()
231
+ cycle_duration = 30 * 60 # 30 minutes
232
+
233
+ if self.in_break_mode:
234
+ # Currently in break, check if break time is over
235
+ if self.cycle_break_start and (current_time - self.cycle_break_start) >= cycle_duration:
236
+ # Break is over, switch to mining
237
+ self.in_break_mode = False
238
+ self.cycle_active = True
239
+ self.cycle_start_time = current_time
240
+ self.cycle_break_start = None
241
+ log.info("🟒 30-minute break completed, resuming mining...")
242
+ return True
243
+ return False # Still in break
244
+ else:
245
+ # Currently mining, check if mining time is over
246
+ if (current_time - self.cycle_start_time) >= cycle_duration:
247
+ # Mining period is over, switch to break
248
+ self.in_break_mode = True
249
+ self.cycle_active = False
250
+ self.cycle_break_start = current_time
251
+ self.total_cycles += 1
252
+ log.info(f"πŸ”΄ 30-minute mining cycle #{self.total_cycles} completed, starting 30-minute break...")
253
+ return False
254
+ return True # Continue mining
255
+
256
+ def get_stats(self) -> Dict:
257
+ # Maintain backward compatibility
258
+ return self.get_comprehensive_stats()
259
+
260
+ miner_state = MinerState()
261
+
262
+ # ---------- Live Feed ----------
263
+ class LiveFeed:
264
+ def __init__(self, max_items: int = 100):
265
+ self.feed = collections.deque(maxlen=max_items)
266
+ self.lock = threading.Lock()
267
+
268
+ def add_entry(self, secret: str, sol: float, address: str = ""):
269
+ with self.lock:
270
+ timestamp = datetime.now().strftime('%H:%M:%S')
271
+ if sol >= config.MIN_SOL:
272
+ entry = f"🟒 **FUNDED** {sol:.6f} SOL | `{secret[:20]}...` | {address[:20]}... | {timestamp}"
273
+ log.info(f"πŸ’° FUNDED WALLET: {sol:.6f} SOL")
274
+ else:
275
+ entry = f"πŸ”΄ Empty | `{secret[:20]}...` | {timestamp}"
276
+ self.feed.append(entry)
277
+
278
+ def get_feed(self) -> str:
279
+ with self.lock:
280
+ return "\n".join(self.feed)
281
+
282
+ def clear_feed(self):
283
+ with self.lock:
284
+ self.feed.clear()
285
+
286
+ live_feed = LiveFeed(config.FEED_MAX_ITEMS)
287
+
288
+ # ---------- Key Generation ----------
289
+ BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
290
+
291
+ def generate_secure_keypair() -> Tuple[str, str, Keypair]:
292
+ """Generate a secure keypair with Base58 encoding"""
293
+ try:
294
+ keypair = _safe_keypair()
295
+ seed = bytes(keypair)[:32]
296
+ private_key_b58 = base58.b58encode(seed).decode('utf-8')
297
+ public_key = str(keypair.pubkey())
298
+ return private_key_b58, public_key, keypair
299
+ except Exception as e:
300
+ log.error(f"Keypair generation failed: {e}")
301
+ raise Exception(f"Failed to generate keypair: {e}")
302
+
303
+ def get_key_info(private_key: str) -> Dict:
304
+ try:
305
+ decoded = base58.b58decode(private_key)
306
+ keypair = _safe_keypair()
307
+ return {
308
+ "private_key": private_key,
309
+ "public_key": str(keypair.pubkey()),
310
+ "key_length": len(private_key),
311
+ "is_valid": True,
312
+ "private_key_hex": decoded.hex(),
313
+ "public_key_hex": bytes(keypair.pubkey()).hex(),
314
+ }
315
+ except Exception as e:
316
+ return {"private_key": private_key, "error": str(e), "is_valid": False}
317
+
318
+ # ---------- Simple Solana Client ----------
319
+ def create_solana_client() -> Client:
320
+ """Create client with simple RPC rotation"""
321
+ for attempt in range(len(config.RPC_URLS)):
322
+ rpc_url = config.get_current_rpc()
323
+ try:
324
+ client = Client(rpc_url.strip())
325
+ client.get_slot() # Test connection
326
+ log.info(f"βœ… Connected to Solana RPC: {rpc_url}")
327
+ return client
328
+ except Exception as e:
329
+ log.warning(f"❌ RPC {rpc_url} failed: {e}")
330
+ config.rotate_rpc()
331
+ time.sleep(2)
332
+
333
+ raise Exception("All RPC endpoints failed")
334
+
335
+ def get_balances_with_retry(client: Client, addresses: List[str]) -> List[float]:
336
+ """Simple balance checking with retry logic"""
337
+ chunk_size = min(50, len(addresses))
338
+
339
+ for attempt in range(config.MAX_RETRIES):
340
+ try:
341
+ all_balances = []
342
+
343
+ for i in range(0, len(addresses), chunk_size):
344
+ chunk = addresses[i:i + chunk_size]
345
+ pubkeys = [Pubkey.from_string(addr) for addr in chunk]
346
+
347
+ time.sleep(0.5) # Rate limiting
348
+ resp = client.get_multiple_accounts(pubkeys)
349
+
350
+ chunk_balances = []
351
+ for acc in resp.value:
352
+ chunk_balances.append((acc.lamports / 1e9) if acc else 0.0)
353
+ all_balances.extend(chunk_balances)
354
+
355
+ # Small delay between chunks
356
+ if i + chunk_size < len(addresses):
357
+ time.sleep(0.2)
358
+
359
+ return all_balances
360
+
361
+ except Exception as e:
362
+ log.warning(f"Balance check attempt {attempt + 1} failed: {e}")
363
+ miner_state.increment_errors()
364
+ config.rotate_rpc()
365
+ time.sleep(2)
366
+
367
+ return [0.0] * len(addresses)
368
+
369
+ # ---------- Isolated Discord Operations ----------
370
+ def queue_discord_message(message_type: str, data: dict):
371
+ """Queue Discord message for isolated processing"""
372
+ if not config.DISCORD_WEBHOOK:
373
+ return
374
+
375
+ try:
376
+ DISCORD_QUEUE.put_nowait({
377
+ 'type': message_type,
378
+ 'data': data,
379
+ 'timestamp': time.time()
380
+ })
381
+ except queue.Full:
382
+ # If queue is full, remove oldest message and add new one
383
+ try:
384
+ DISCORD_QUEUE.get_nowait()
385
+ DISCORD_QUEUE.put_nowait({
386
+ 'type': message_type,
387
+ 'data': data,
388
+ 'timestamp': time.time()
389
+ })
390
+ except:
391
+ pass # Silently fail to avoid impacting mining
392
+
393
+ def send_funded_ping(private_key: str, public_key: str, balance: float):
394
+ """Queue funded wallet notification - never blocks mining"""
395
+ stats = miner_state.get_comprehensive_stats()
396
+ queue_discord_message('funded_wallet', {
397
+ 'private_key': private_key,
398
+ 'public_key': public_key,
399
+ 'balance': balance,
400
+ 'miner_stats': stats,
401
+ 'discovery_time': datetime.now().isoformat()
402
+ })
403
+
404
+ def process_funded_wallet_message(data: dict):
405
+ """Process funded wallet Discord message"""
406
+ stats = data['miner_stats']
407
+ payload = {
408
+ "content": f"@everyone 🚨 **{stats['miner_name']}** found FUNDED wallet!",
409
+ "embeds": [{
410
+ "title": f"πŸ’° FUNDED WALLET DISCOVERED - {stats['miner_name']}",
411
+ "color": 0x00ff00,
412
+ "thumbnail": {"url": "https://cryptologos.cc/logos/solana-sol-logo.png"},
413
+ "fields": [
414
+ {"name": "πŸ’Ό Wallet Details", "value":
415
+ f"**Balance:** {data['balance']:.8f} SOL\n"
416
+ f"**Public Key:** `{data['public_key']}`\n"
417
+ f"**Private Key:** ||{data['private_key']}||", "inline": False},
418
+
419
+ {"name": "πŸ† Miner Performance", "value":
420
+ f"**Total Mined:** {stats['total_mined']:,} wallets\n"
421
+ f"**Total Funded:** {stats['funded_found']} wallets\n"
422
+ f"**Success Rate:** {(stats['funded_found']/max(stats['total_mined'],1)*100):.6f}%", "inline": True},
423
+
424
+ {"name": "⚑ Current Stats", "value":
425
+ f"**Speed:** {stats['wallets_per_second']:.1f} wallets/sec\n"
426
+ f"**Uptime:** {stats['uptime_str']}\n"
427
+ f"**Current Streak:** {stats['current_streak']}", "inline": True},
428
+
429
+ {"name": "🌐 Miner Info", "value":
430
+ f"**ID:** {stats['miner_id']}\n"
431
+ f"**Location:** {stats['location']}\n"
432
+ f"**RPC:** {stats['current_rpc'].split('//')[-1][:25]}", "inline": True},
433
+
434
+ {"name": "πŸ“ˆ Network Stats", "value":
435
+ f"**Batches Processed:** {stats['total_batches']}\n"
436
+ f"**Avg Batch Time:** {stats['average_batch_time']}s\n"
437
+ f"**RPC Switches:** {stats['rpc_switches']}", "inline": True},
438
+
439
+ {"name": "πŸ•’ Discovery Time", "value": f"<t:{int(time.time())}:F>", "inline": False}
440
+ ],
441
+ "footer": {"text": f"Miner: {stats['miner_name']} | Best Streak: {stats['best_streak']}"}
442
+ }]
443
+ }
444
+
445
+ return requests.post(config.DISCORD_WEBHOOK, data=json.dumps(payload),
446
+ headers={"Content-Type": "application/json"},
447
+ timeout=config.DISCORD_TIMEOUT)
448
+
449
+ def queue_status_update():
450
+ """Queue status update - never blocks mining"""
451
+ stats = miner_state.get_comprehensive_stats()
452
+ queue_discord_message('status_update', {
453
+ 'stats': stats,
454
+ 'timestamp': time.time()
455
+ })
456
+
457
+ def process_status_update(data: dict):
458
+ """Process comprehensive status update"""
459
+ global STATUS_MESSAGE_ID, STATUS_EDIT_URL
460
+ stats = data['stats']
461
+
462
+ # Enhanced status embed with comprehensive information
463
+ embed = {
464
+ "title": f"πŸͺ™ {stats['miner_name']} - Live Mining Status",
465
+ "color": 0x0099ff if stats['is_running'] else 0xff4444,
466
+ "thumbnail": {"url": "https://cryptologos.cc/logos/solana-sol-logo.png"},
467
+ "fields": [
468
+ {"name": "πŸ“ˆ Core Statistics", "value":
469
+ f"**Status:** {'🟒 MINING' if stats['is_running'] else 'πŸ”΄ STOPPED'}\n"
470
+ f"**Total Mined:** {stats['total_mined']:,} wallets\n"
471
+ f"**Funded Found:** {stats['funded_found']} wallets\n"
472
+ f"**Success Rate:** {(stats['funded_found']/max(stats['total_mined'],1)*100):.6f}%", "inline": True},
473
+
474
+ {"name": "⚑ Performance Metrics", "value":
475
+ f"**Speed:** {stats['wallets_per_second']:.2f} wallets/sec\n"
476
+ f"**Uptime:** {stats['uptime_str']}\n"
477
+ f"**Batches:** {stats['total_batches']}\n"
478
+ f"**Avg Batch Time:** {stats['average_batch_time']}s", "inline": True},
479
+
480
+ {"name": "πŸŽ† Streak & Records", "value":
481
+ f"**Current Streak:** {stats['current_streak']}\n"
482
+ f"**Best Streak:** {stats['best_streak']}\n"
483
+ f"**Errors:** {stats['errors_count']}\n"
484
+ f"**Queue Size:** {stats['queue_size']}", "inline": True},
485
+
486
+ {"name": "🌐 Network & Infrastructure", "value":
487
+ f"**Current RPC:** {stats['current_rpc'].split('//')[-1][:30] if stats['current_rpc'] else 'None'}\n"
488
+ f"**RPC Switches:** {stats['rpc_switches']}\n"
489
+ f"**Connection:** {stats['connection_status']}\n"
490
+ f"**Location:** {stats['location']}", "inline": False},
491
+
492
+ {"name": "πŸ•°οΈ Timing Information", "value":
493
+ f"**Started:** <t:{int(stats['start_time'].timestamp())}:R>\n"
494
+ f"**Last Activity:** <t:{int(stats['last_activity'])}:R>\n"
495
+ f"**Last Funded:** {'<t:' + str(int(stats['last_funded'].timestamp())) + ':R>' if stats['last_funded'] else 'Never'}\n"
496
+ f"**Update:** <t:{int(time.time())}:f>", "inline": False}
497
+ ],
498
+ "footer": {
499
+ "text": f"Miner ID: {stats['miner_id']} | Batch #{stats['total_batches']}",
500
+ "icon_url": "https://cryptologos.cc/logos/solana-sol-logo.png"
501
+ },
502
+ "timestamp": datetime.utcnow().isoformat()
503
+ }
504
+
505
+ # Add RPC performance if available
506
+ if stats['rpc_performance']:
507
+ rpc_perf = "\n".join([f"**{rpc.split('//')[-1][:20]}:** {avg_time}s"
508
+ for rpc, avg_time in stats['rpc_performance'].items()])
509
+ embed["fields"].append({
510
+ "name": "πŸš€ RPC Performance",
511
+ "value": rpc_perf[:1000],
512
+ "inline": False
513
+ })
514
+
515
+ # First message or edit existing
516
+ if STATUS_MESSAGE_ID is None:
517
+ payload = {"embeds": [embed]}
518
+ r = requests.post(config.DISCORD_WEBHOOK + "?wait=true",
519
+ data=json.dumps(payload),
520
+ headers={"Content-Type": "application/json"},
521
+ timeout=config.DISCORD_TIMEOUT)
522
+ if r.status_code == 200:
523
+ data = r.json()
524
+ STATUS_MESSAGE_ID = data['id']
525
+ STATUS_EDIT_URL = f"{config.DISCORD_WEBHOOK}/messages/{STATUS_MESSAGE_ID}"
526
+ return r
527
+
528
+ if STATUS_EDIT_URL:
529
+ return requests.patch(STATUS_EDIT_URL, data=json.dumps({"embeds": [embed]}),
530
+ headers={"Content-Type": "application/json"},
531
+ timeout=config.DISCORD_TIMEOUT)
532
+ return None
533
+
534
+ def isolated_discord_worker():
535
+ """Completely isolated Discord worker - never affects mining"""
536
+ global DISCORD_DISABLED, DISCORD_RETRY_COUNT, DISCORD_LAST_ERROR, DISCORD_LAST_SUCCESS
537
+
538
+ log.info(f"πŸ’Œ Discord worker started for miner: {config.MINER_NAME}")
539
+
540
+ while True:
541
+ try:
542
+ # Process Discord queue without blocking
543
+ try:
544
+ message = DISCORD_QUEUE.get(timeout=1)
545
+
546
+ # Skip old messages (older than 5 minutes)
547
+ if time.time() - message['timestamp'] > 300:
548
+ continue
549
+
550
+ # Process message based on type
551
+ response = None
552
+ if message['type'] == 'funded_wallet':
553
+ response = process_funded_wallet_message(message['data'])
554
+ elif message['type'] == 'status_update':
555
+ response = process_status_update(message['data'])
556
+ elif message['type'] == 'miner_startup':
557
+ response = process_miner_startup(message['data'])
558
+
559
+ # Handle response
560
+ if response and response.status_code in [200, 204]:
561
+ DISCORD_RETRY_COUNT = 0
562
+ DISCORD_LAST_SUCCESS = time.time()
563
+ DISCORD_DISABLED = False
564
+ log.info(f"πŸ’¬ Discord message sent: {message['type']}")
565
+ elif response:
566
+ raise Exception(f"Discord API returned {response.status_code}: {response.text[:100]}")
567
+
568
+ except queue.Empty:
569
+ # No messages to process, continue
570
+ pass
571
+ except requests.exceptions.RequestException as e:
572
+ # Network-related errors
573
+ DISCORD_RETRY_COUNT += 1
574
+ DISCORD_LAST_ERROR = f"Network error: {str(e)[:100]}"
575
+
576
+ if DISCORD_RETRY_COUNT >= config.DISCORD_RETRY_LIMIT:
577
+ if not DISCORD_DISABLED:
578
+ log.info(f"πŸ”‡ Discord temporarily disabled after {DISCORD_RETRY_COUNT} failures. Will retry in {config.DISCORD_COOLDOWN}s")
579
+ DISCORD_DISABLED = True
580
+ time.sleep(config.DISCORD_COOLDOWN) # Long cooldown
581
+ DISCORD_RETRY_COUNT = 0 # Reset after cooldown
582
+ else:
583
+ time.sleep(min(10, DISCORD_RETRY_COUNT * 2)) # Exponential backoff
584
+
585
+ except Exception as e:
586
+ # Other errors
587
+ DISCORD_LAST_ERROR = f"Processing error: {str(e)[:100]}"
588
+ log.warning(f"⚠️ Discord processing error: {e}")
589
+ time.sleep(5)
590
+
591
+ # Auto-queue status updates every 2 minutes when not disabled
592
+ if not DISCORD_DISABLED and time.time() - DISCORD_LAST_SUCCESS > 120:
593
+ queue_status_update()
594
+
595
+ except Exception as e:
596
+ # Critical error handler - never crash the Discord worker
597
+ log.error(f"🚨 Critical Discord worker error: {e}")
598
+ time.sleep(30) # Long sleep after critical errors
599
+
600
+ time.sleep(0.1) # Small sleep to prevent tight loop
601
+
602
+ def process_miner_startup(data: dict):
603
+ """Process miner startup notification"""
604
+ stats = data['stats']
605
+ payload = {
606
+ "content": f"πŸš€ **{stats['miner_name']}** has started mining!",
607
+ "embeds": [{
608
+ "title": f"πŸš€ New Miner Online - {stats['miner_name']}",
609
+ "color": 0x00ff88,
610
+ "fields": [
611
+ {"name": "πŸŽ† Miner Information", "value":
612
+ f"**Name:** {stats['miner_name']}\n"
613
+ f"**ID:** {stats['miner_id']}\n"
614
+ f"**Location:** {stats['location']}\n"
615
+ f"**Started:** <t:{int(time.time())}:F>", "inline": True},
616
+
617
+ {"name": "βš™οΈ Configuration", "value":
618
+ f"**Min SOL:** {config.MIN_SOL}\n"
619
+ f"**Batch Size:** {config.RPC_BATCH_SIZE}\n"
620
+ f"**Sleep Time:** {config.MINER_SLEEP}s\n"
621
+ f"**RPC Endpoints:** {len(config.RPC_URLS)}", "inline": True}
622
+ ],
623
+ "footer": {"text": f"Miner ready to start discovering funded wallets!"}
624
+ }]
625
+ }
626
+
627
+ return requests.post(config.DISCORD_WEBHOOK, data=json.dumps(payload),
628
+ headers={"Content-Type": "application/json"},
629
+ timeout=config.DISCORD_TIMEOUT)
630
+
631
+ # Start isolated Discord worker
632
+ threading.Thread(target=isolated_discord_worker, daemon=True).start()
633
+
634
+ # Queue startup notification
635
+ if config.DISCORD_WEBHOOK:
636
+ queue_discord_message('miner_startup', {
637
+ 'stats': {
638
+ 'miner_name': config.MINER_NAME,
639
+ 'miner_id': config.MINER_ID,
640
+ 'location': config.LOCATION
641
+ }
642
+ })
643
+
644
+ # Auto-start mining code will be placed after mining_loop function is defined
645
+
646
+ def upload_daemon():
647
+ """Background uploader for funded wallets - integrated with new Discord system"""
648
+ while True:
649
+ try:
650
+ private_key, public_key, balance = miner_state.upload_queue.get(timeout=1)
651
+ # Use the new isolated Discord system
652
+ send_funded_ping(private_key, public_key, balance)
653
+ miner_state.upload_queue.task_done()
654
+ except queue.Empty:
655
+ continue
656
+ except Exception as e:
657
+ log.error(f"Upload daemon error: {e}")
658
+
659
+ threading.Thread(target=upload_daemon, daemon=True).start()
660
+
661
+ # ---------- Simple Mining Loop ----------
662
+ def mining_loop():
663
+ """Main mining loop with 30-minute cycle management"""
664
+ log.info("πŸš€ Mining loop started with 30-minute cycles")
665
+ log.info(f"🏁 Run flag status: {miner_state.run_flag.is_set()}")
666
+ client = None
667
+ consecutive_errors = 0
668
+
669
+ batch_private_keys, batch_addresses = [], []
670
+
671
+ while miner_state.run_flag.is_set():
672
+ try:
673
+ # Check 30-minute cycle status
674
+ should_mine = miner_state.check_cycle_status()
675
+ if not should_mine:
676
+ # In break mode, sleep and continue
677
+ miner_state.connection_status = "On Break (30 min cycle)"
678
+ log.info(f"πŸ’€ In break mode, sleeping for 60 seconds...")
679
+ time.sleep(60) # Check every minute during break
680
+ continue
681
+
682
+ miner_state.connection_status = "Mining Active"
683
+ log.info(f"⛏️ Starting mining batch of {config.RPC_BATCH_SIZE} wallets...")
684
+ # Ensure client connection
685
+ if client is None:
686
+ try:
687
+ client = create_solana_client()
688
+ consecutive_errors = 0
689
+ except Exception as e:
690
+ log.error(f"Cannot connect to RPC: {e}")
691
+ time.sleep(10)
692
+ continue
693
+
694
+ # Generate keypair batch
695
+ log.info(f"πŸ”‘ Generating batch of {config.RPC_BATCH_SIZE} keypairs...")
696
+ while len(batch_addresses) < config.RPC_BATCH_SIZE and miner_state.run_flag.is_set():
697
+ try:
698
+ private_key, public_key, _ = generate_secure_keypair()
699
+ batch_private_keys.append(private_key)
700
+ batch_addresses.append(public_key)
701
+ miner_state.increment_mined()
702
+
703
+ if len(batch_addresses) % 20 == 0:
704
+ log.info(f"Generated {len(batch_addresses)} keypairs so far...")
705
+ time.sleep(0.01) # Prevent CPU hogging
706
+
707
+ except Exception as e:
708
+ log.error(f"Keypair generation error: {e}")
709
+ continue
710
+
711
+ log.info(f"βœ… Generated {len(batch_addresses)} keypairs, checking balances...")
712
+
713
+ # Check balances
714
+ if batch_addresses:
715
+ batch_start_time = time.time()
716
+ log.info(f"πŸ” Checking {len(batch_addresses)} addresses...")
717
+ balances = get_balances_with_retry(client, batch_addresses)
718
+
719
+ if not balances or len(balances) != len(batch_addresses):
720
+ log.warning("RPC response mismatch, reconnecting...")
721
+ client = None
722
+ continue
723
+
724
+ funded_in_batch = 0
725
+ for i, balance in enumerate(balances):
726
+ if balance >= config.MIN_SOL:
727
+ priv, addr = batch_private_keys[i], batch_addresses[i]
728
+ funded_in_batch += 1
729
+ miner_state.increment_funded()
730
+ miner_state.upload_queue.put((priv, addr, balance))
731
+ log.info(f"πŸ’° FUNDED: {balance:.8f} SOL | {addr}")
732
+ live_feed.add_entry(priv, balance, addr)
733
+ elif i % 50 == 0: # Sample empty wallets
734
+ live_feed.add_entry(batch_private_keys[i], balance, batch_addresses[i])
735
+
736
+ log.info(f"βœ… Batch complete: {funded_in_batch} funded, {len(batch_addresses)} total")
737
+
738
+ # Update comprehensive stats
739
+ batch_time = time.time() - batch_start_time
740
+ miner_state.update_batch_stats(len(batch_addresses), batch_time, config.get_current_rpc())
741
+ miner_state.connection_status = "Active Mining"
742
+
743
+ # Reset batch
744
+ batch_private_keys, batch_addresses = [], []
745
+ consecutive_errors = 0
746
+
747
+ # Queue status update every 50 batches or when funded wallet found
748
+ if funded_in_batch > 0 or miner_state.total_batches % 50 == 0:
749
+ queue_status_update()
750
+
751
+ # Sleep between batches
752
+ time.sleep(config.MINER_SLEEP)
753
+
754
+ except Exception as e:
755
+ consecutive_errors += 1
756
+ log.error(f"Mining loop error: {e}")
757
+ miner_state.increment_errors()
758
+
759
+ if consecutive_errors >= 3:
760
+ client = None
761
+ miner_state.connection_status = "Reconnecting"
762
+ miner_state.rpc_switches += 1
763
+ log.info("Resetting RPC connection due to errors")
764
+ time.sleep(5)
765
+
766
+ log.info("πŸ›‘ Mining loop stopped")
767
+
768
+ # Auto-start mining when app loads
769
+ log.info("πŸš€ Auto-starting mining on app launch...")
770
+ miner_state.run_flag.set()
771
+ threading.Thread(target=mining_loop, daemon=True).start()
772
+
773
+ # ---------- Gradio Controls ----------
774
+ def start_mining() -> str:
775
+ if miner_state.run_flag.is_set():
776
+ return "⚠️ Already running"
777
+ log.info("πŸš€ Starting mining manually via button...")
778
+ miner_state.run_flag.set()
779
+ threading.Thread(target=mining_loop, daemon=True).start()
780
+ return "🟒 Mining started (background)"
781
+
782
+ def stop_mining() -> str:
783
+ if not miner_state.run_flag.is_set():
784
+ return "⚠️ Not running"
785
+ miner_state.run_flag.clear()
786
+ return "πŸ”΄ Mining stopped!"
787
+
788
+ def get_mining_stats() -> str:
789
+ stats = miner_state.get_comprehensive_stats()
790
+ running = "🟒 Running" if stats['is_running'] else "πŸ”΄ Stopped"
791
+ last = ""
792
+ if stats['last_funded']:
793
+ ago = (datetime.now() - stats['last_funded']).seconds
794
+ last = f" | Last funded: {ago//3600}h {(ago//60)%60}m ago"
795
+
796
+ # Add cycle information
797
+ cycle_info = stats['cycle_time_remaining']
798
+ if cycle_info['mode'] == 'break':
799
+ cycle_status = f"πŸ”΄ Break Mode ({cycle_info['remaining_minutes']}m left)"
800
+ elif cycle_info['mode'] == 'mining':
801
+ cycle_status = f"🟒 Mining ({cycle_info['remaining_minutes']}m left)"
802
+ else:
803
+ cycle_status = "πŸ”„ Cycle Starting"
804
+
805
+ return (f"{running} | {cycle_status} | Cycles: {stats['total_cycles']} | "
806
+ f"Mined: {stats['total_mined']:,} | Funded: {stats['funded_found']} | "
807
+ f"Speed: {stats['wallets_per_second']:.1f}/s | Errors: {stats['errors_count']} | "
808
+ f"Uptime: {stats['uptime_str']}{last}")
809
+
810
+ def clear_feed() -> str:
811
+ live_feed.clear_feed()
812
+ return ""
813
+
814
+ def generate_single_key() -> tuple:
815
+ try:
816
+ private_key, public_key, _ = generate_secure_keypair()
817
+ info = get_key_info(private_key)
818
+ return private_key, public_key, info.get('private_key_hex', ''), str(info.get('key_length', 0))
819
+ except Exception as e:
820
+ log.error(f"Key generation error: {e}")
821
+ err = f"Error: {e}"
822
+ return err, err, err, err
823
+
824
+ def generate_bulk_keys(count: int) -> str:
825
+ if count <= 0 or count > 1000:
826
+ return "❌ Enter 1-1000"
827
+ keys = []
828
+ errors = 0
829
+ for i in range(count):
830
+ try:
831
+ private_key, _, _ = generate_secure_keypair()
832
+ keys.append(private_key)
833
+ if count > 100 and (i + 1) % 50 == 0:
834
+ log.info(f"Generated {i + 1}/{count} keys...")
835
+ except Exception as e:
836
+ errors += 1
837
+ log.error(f"Failed to generate key {i + 1}: {e}")
838
+ if errors > 10:
839
+ return f"❌ Too many errors. Generated {len(keys)} keys successfully."
840
+
841
+ result = "\n".join(keys)
842
+ if errors > 0:
843
+ result += f"\n\n⚠️ Note: {errors} keys failed to generate"
844
+ return result
845
+
846
+ # ---------- Gradio Interface ----------
847
+ css = """
848
+ #live_feed {
849
+ font-family: monospace;
850
+ font-size: 12px;
851
+ max-height: 500px;
852
+ overflow-y: auto;
853
+ }
854
+ """
855
+
856
+ with gr.Blocks(title="Solana Key Generator & Miner", css=css, theme=gr.themes.Soft()) as demo:
857
+
858
+ gr.Markdown(f"# πŸ” Enhanced Solana Key Generator & Miner")
859
+ gr.Markdown(f"**{config.MINER_NAME}** ({config.MINER_ID}) - Multi-miner Discord integration enabled!")
860
+ gr.Markdown("Optimized for Hugging Face Spaces - runs forever even if you close the browser.")
861
+
862
+ with gr.Tab("🎲 Single Key Generator"):
863
+ with gr.Row():
864
+ gen_btn = gr.Button("🎯 Generate New Keypair", variant="primary")
865
+ with gr.Row():
866
+ private_key_out = gr.Textbox(label="πŸ” Private Key (Base58)", show_copy_button=True)
867
+ public_key_out = gr.Textbox(label="πŸ“ Public Address", show_copy_button=True)
868
+ with gr.Row():
869
+ private_hex_out = gr.Textbox(label="πŸ”’ Private Key (Hex)", show_copy_button=True)
870
+ key_info_out = gr.Textbox(label="ℹ️ Key Information", interactive=False)
871
+ gen_btn.click(generate_single_key, outputs=[private_key_out, public_key_out, private_hex_out, key_info_out])
872
+
873
+ with gr.Tab("πŸ“¦ Bulk Key Generator"):
874
+ count = gr.Slider(1, 1000, value=10, step=1, label="Number of Keys")
875
+ btn = gr.Button("πŸš€ Generate Bulk Keys", variant="primary")
876
+ keys = gr.Textbox(label="Generated Private Keys", lines=20, show_copy_button=True)
877
+ btn.click(generate_bulk_keys, inputs=count, outputs=keys)
878
+
879
+ with gr.Tab("πŸͺ™ Wallet Miner"):
880
+ with gr.Row():
881
+ start_btn = gr.Button("🟒 Start Mining", variant="primary", size="lg")
882
+ stop_btn = gr.Button("πŸ”΄ Stop Mining", variant="stop", size="lg")
883
+ clear_btn = gr.Button("🧹 Clear Feed", variant="secondary")
884
+ status = gr.Textbox(label="🎯 Mining Status", value="Ready to start mining...", interactive=False)
885
+ stats_display = gr.Textbox(label="πŸ“Š Real-time Statistics", interactive=False)
886
+ live_feed_display = gr.Textbox(label="πŸ“‘ Live Mining Feed", lines=25, max_lines=30, interactive=False, elem_id="live_feed")
887
+
888
+ start_btn.click(start_mining, outputs=status)
889
+ stop_btn.click(stop_mining, outputs=status)
890
+ clear_btn.click(clear_feed, outputs=live_feed_display)
891
+
892
+ # Auto-refresh for real-time updates
893
+ def _refresh():
894
+ return get_mining_stats(), live_feed.get_feed()
895
+
896
+ refresh_btn = gr.Button("πŸ”„ Refresh", visible=False)
897
+ refresh_btn.click(_refresh, outputs=[stats_display, live_feed_display])
898
+
899
+ # Set up auto-refresh after all components are defined
900
+ demo.load(_refresh, outputs=[stats_display, live_feed_display])
901
+
902
+ if __name__ == "__main__":
903
+ # Multi-platform compatibility: 7860 for Hugging Face, 5000 for Replit
904
+ port = int(os.environ.get('PORT', 7860))
905
+
906
+ # Detect if running on Replit
907
+ if os.environ.get('REPLIT_DB_URL') or os.environ.get('REPL_ID'):
908
+ port = 5000
909
+
910
+ demo.queue().launch(
911
+ server_name="0.0.0.0",
912
+ server_port=port,
913
+ share=False,
914
+ show_error=True
915
+ )
check/replit.md ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Solana Key Generator & Miner
2
+
3
+ ## Overview
4
+ This is a Solana key mining application built with Gradio that generates Ed25519 Base-58 keys and mines Solana addresses in real time with Discord notifications. The application was originally designed for Hugging Face Spaces and has been successfully adapted for the Replit environment.
5
+
6
+ ## Project Architecture
7
+ - **Language**: Python 3.11
8
+ - **Framework**: Gradio for web interface
9
+ - **Main Components**:
10
+ - Key generation system using solders and solana libraries
11
+ - Real-time mining with RPC endpoint rotation
12
+ - Discord webhook integration for notifications
13
+ - Live feed of mining activity
14
+ - Bulk key generation capabilities
15
+
16
+ ## Current Status
17
+ - βœ… Python 3.11 installed and configured
18
+ - βœ… All dependencies installed successfully
19
+ - βœ… Application running on port 5000
20
+ - βœ… Workflow configured for automatic startup
21
+ - βœ… .gitignore file created for Python project
22
+ - βœ… Compatible with Replit environment
23
+
24
+ ## Dependencies
25
+ The application uses the following key packages:
26
+ - `gradio>=4.44.0` - Web interface framework
27
+ - `solana>=0.34.3` - Solana blockchain interaction
28
+ - `solders>=0.21.0` - Solana SDK for Python
29
+ - `base58>=2.1.1` - Base58 encoding/decoding
30
+ - `requests>=2.32.0` - HTTP requests for Discord webhooks
31
+ - `python-dotenv>=1.0.1` - Environment variable management
32
+ - `pydantic>=2.9.0` - Data validation
33
+
34
+ ## Features
35
+ 1. **Key Generation**: Generate secure Ed25519 keypairs with Base-58 encoding
36
+ 2. **Real-time Mining**: Continuously mine wallets checking for funded addresses
37
+ 3. **Discord Integration**: Automated notifications when funded wallets are discovered
38
+ 4. **Multi-RPC Support**: Automatic failover between multiple Solana RPC endpoints
39
+ 5. **Live Statistics**: Real-time performance metrics and mining statistics
40
+ 6. **Bulk Operations**: Generate up to 1000 keys at once
41
+
42
+ ## Configuration
43
+ The application supports environment variables for configuration:
44
+ - `DISCORD_WEBHOOK` - Discord webhook URL for notifications (optional)
45
+ - `MIN_SOL` - Minimum SOL balance to consider a wallet "funded" (default: 0.00001)
46
+ - `RPC_BATCH_SIZE` - Number of wallets to check per RPC call (default: 100, max: 100)
47
+ - `MINER_SLEEP` - Seconds between mining cycles (default: 1.0)
48
+ - `PORT` - Application port (automatically set to 5000 for Replit)
49
+
50
+ ## Setup Notes
51
+ - The application is configured to use port 5000 which is compatible with Replit
52
+ - Host is set to 0.0.0.0 to allow external access through Replit's proxy
53
+ - All RPC endpoints are external and don't require local Solana node
54
+ - Discord integration is optional but recommended for notifications
55
+
56
+ ## Recent Changes
57
+ - Adapted from Hugging Face Spaces to Replit environment
58
+ - Maintained all original functionality
59
+ - Configured proper networking for Replit's infrastructure
60
+ - Added Python .gitignore for clean repository management
check/requirements.txt ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ gradio>=4.44.0
2
+ solana>=0.34.3
3
+ solders>=0.21.0
4
+ base58>=2.1.1
5
+ requests>=2.32.0
6
+ python-dotenv>=1.0.1
7
+ pydantic>=2.9.0
8
+
9
+ base58>=2.1.1
10
+ gradio>=4.44.0
11
+ pydantic>=2.9.0
12
+ python-dotenv>=1.0.1
13
+ requests>=2.32.0
14
+ solana>=0.34.3
15
+ solders>=0.21.0