Spaces:
Sleeping
Sleeping
| # 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() |