Asset / app.py
Really-amin's picture
Upload 3 files
f2cbe2d verified
# 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()