# app.py # Hugging Face Space (Gradio) for checking BSC/Ethereum balances and optional BEP20 transfers. # WARNING: Never paste your private key into public/shared Spaces. This UI allows optional local signing # but you must understand the security risks. Prefer using WalletConnect / local signing or set # PRIVATE_KEY as a secret in a private Space only if you know what you're doing. from web3 import Web3 import gradio as gr import os from dotenv import load_dotenv load_dotenv() BSC_RPC = os.environ.get('BSC_RPC','https://bsc-dataseed.binance.org/') ETH_RPC = os.environ.get('ETH_RPC','https://mainnet.infura.io/v3/YOUR_INFURA_KEY') w3_bsc = Web3(Web3.HTTPProvider(BSC_RPC)) w3_eth = Web3(Web3.HTTPProvider(ETH_RPC)) COMMON_TOKENS = { 'BUSD': '0xe9e7cea3dedca5984780bafc599bd69add087d56', 'WETH_BEP20': '0x2170ed0880ac9a755fd29b2688956bd959f933f8' } ERC20_ABI = [ {"constant":True,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"type":"function"}, {"constant":True,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"type":"function"}, {"constant":True,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"type":"function"}, {"constant":False,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"type":"function"} ] def checksum(addr): try: return w3_bsc.toChecksumAddress(addr) except Exception: return None def check_address(addr): addr = addr.strip() c = checksum(addr) if not c: return ("آدرس نامعتبر است. لطفاً آدرس را با 0x شروع وارد کنید.", "") out_lines = [] try: bnb = w3_bsc.fromWei(w3_bsc.eth.get_balance(c), 'ether') out_lines.append(f"BNB (BSC) balance: {bnb} BNB") except Exception as e: out_lines.append(f"خطا در خواندن موجودی BSC: {e}") try: eth = w3_eth.fromWei(w3_eth.eth.get_balance(c), 'ether') out_lines.append(f"ETH (Ethereum) balance: {eth} ETH") except Exception: out_lines.append("Ethereum RPC not configured or error reading.") token_lines = [] for sym, taddr in COMMON_TOKENS.items(): try: token = w3_bsc.eth.contract(address=w3_bsc.toChecksumAddress(taddr), abi=ERC20_ABI) bal = token.functions.balanceOf(c).call() dec = token.functions.decimals().call() if bal > 0: token_lines.append(f"{sym}: {bal / (10**dec)} ({taddr})") except Exception: pass if token_lines: out_lines.append("\nTokens on BSC found:") out_lines += token_lines else: out_lines.append("\nNo common tokens (BUSD/WETH_BEP20) found with nonzero balance.") bscscan = f"https://bscscan.com/address/{c}" out_lines.append(f"\nView on BscScan: {bscscan}") return ("\n".join(out_lines), bscscan) def send_bep20(token_addr, to_addr, amount_str, private_key): # Security: This function will perform a real on-chain transfer if called. # Use only in a private Space or run locally. The app warns the user strongly. try: token_addr = w3_bsc.toChecksumAddress(token_addr) to_addr = w3_bsc.toChecksumAddress(to_addr) except Exception as e: return f"آدرس‌ها نامعتبر هستند: {e}" try: token = w3_bsc.eth.contract(address=token_addr, abi=ERC20_ABI) decimals = token.functions.decimals().call() amt = int(float(amount_str) * (10 ** decimals)) except Exception as e: return f"خطا در آماده‌سازی مقدار یا ABI توکن: {e}" try: acct = w3_bsc.eth.account.from_key(private_key) except Exception as e: return f"خطا در private key: {e}" from_addr = acct.address # Check balance try: bal = token.functions.balanceOf(from_addr).call() if bal < amt: return f"موجودی توکن کافی نیست. موجودی: {bal / (10**decimals)}" except Exception as e: return f"خطا در خواندن موجودی: {e}" # Build tx nonce = w3_bsc.eth.get_transaction_count(from_addr) tx = token.functions.transfer(to_addr, amt).buildTransaction({ 'chainId': 56, 'gas': 200000, 'gasPrice': w3_bsc.eth.gas_price, 'nonce': nonce }) try: signed = w3_bsc.eth.account.sign_transaction(tx, private_key=private_key) tx_hash = w3_bsc.eth.send_raw_transaction(signed.rawTransaction) return f"Transaction submitted: {tx_hash.hex()} — View: https://bscscan.com/tx/{tx_hash.hex()}" except Exception as e: return f"خطا در ارسال تراکنش: {e}" with gr.Blocks() as demo: gr.Markdown("# BSC Address Checker & (optional) BEP20 Transfer") gr.Markdown("**Warnings:** Do not paste private keys into public/shared spaces. Use this tool **locally** or in a private Hugging Face Space. Prefer wallet-based signing (WalletConnect) or using environment secrets.") with gr.Tab("Check Address"): addr_in = gr.Textbox(label="Address (0x...)", placeholder="0x...") out_text = gr.Textbox(label="Result", lines=12) bscscan_link = gr.Textbox(label="BscScan link") check_btn = gr.Button("Check") check_btn.click(fn=check_address, inputs=addr_in, outputs=[out_text, bscscan_link]) with gr.Tab("Send BEP20 (DANGEROUS)"): gr.Markdown("Use only in a private environment. This will perform a live on-chain transfer if you provide a valid private key.") token_addr = gr.Textbox(label="Token contract address (BSC)", placeholder="0x...") to_addr = gr.Textbox(label="Destination address (0x...)") amount = gr.Textbox(label="Amount (decimal string, e.g. 1.23)") pk = gr.Textbox(label="Private key (hex) — optional (DANGEROUS)", placeholder="0x...", type="password") send_out = gr.Textbox(label="Send result", lines=4) send_btn = gr.Button("Send") send_btn.click(fn=send_bep20, inputs=[token_addr, to_addr, amount, pk], outputs=send_out) gr.Markdown("⚠️ This Space is a convenience tool. The authors are not responsible for funds lost. Always test with tiny amounts first.") if __name__ == "__main__": demo.launch()