Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import requests | |
| # Fetch the flagged addresses once at startup from the data feed (static JSON file) | |
| API_URL = "https://dt074px2e9qbh.cloudfront.net/exploit-api.json" | |
| try: | |
| response = requests.get(API_URL) | |
| flagged_addresses = response.json() # Load the JSON data into a list of strings or dictionaries | |
| # Ensure the data is a list of strings or dictionaries (addresses) | |
| if not isinstance(flagged_addresses, list): | |
| flagged_addresses = [] | |
| except Exception as e: | |
| flagged_addresses = [] | |
| print(f"Failed to load API data: {e}") | |
| # Function to infer the blockchain using Hugging Face API | |
| def infer_chain(address, hf_token): | |
| headers = { | |
| "Authorization": f"Bearer {hf_token}" | |
| } | |
| prompt = f"Identify the blockchain of the following cryptocurrency address: {address}" | |
| # Make the request to Hugging Face's Inference API | |
| try: | |
| response = requests.post( | |
| "https://api-inference.huggingface.co/models/mistralai/Mixtral-8x7B-Instruct-v0.1", | |
| headers=headers, | |
| json={"inputs": prompt} | |
| ) | |
| response.raise_for_status() | |
| result = response.json() | |
| # Return the inferred blockchain (if available) | |
| return result[0]["generated_text"].strip() | |
| except Exception as e: | |
| return "Unknown" # Fallback if there's an error | |
| # Function to check if the address is flagged | |
| def check_flagged_address(address: str, hf_token: str): | |
| """Check if a cryptocurrency address is flagged in the Bybit hack database.""" | |
| # Normalize the input address (lowercase and stripped of whitespace) | |
| normalized_address = address.strip().lower() | |
| # Infer the chain of the address | |
| chain = infer_chain(address, hf_token) | |
| # Check if the address is in the flagged addresses | |
| flagged = False | |
| for entry in flagged_addresses: | |
| # Check if entry is a string (address) | |
| if isinstance(entry, str): | |
| if entry.strip().lower() == normalized_address: | |
| flagged = True | |
| break | |
| # Check if entry is a dictionary (with "address" key) | |
| elif isinstance(entry, dict) and "address" in entry: | |
| if entry["address"].strip().lower() == normalized_address: | |
| flagged = True | |
| break | |
| # Format the response | |
| if flagged: | |
| return f"Address {address} is Flagged ✅\nChain: {chain}\nStatus: Present in Bybit hack database" | |
| else: | |
| return f"Address {address} is Not Flagged ❌\nChain: {chain}\nStatus: Not present in Bybit hack database" | |
| # Function to handle multiple addresses input | |
| def handle_multiple_addresses(user_input, hf_token): | |
| """Process multiple addresses separated by commas.""" | |
| results = [] | |
| # Split input into multiple addresses by commas and strip any whitespace | |
| addresses = [addr.strip() for addr in user_input.split(",")] | |
| # Process each address individually | |
| for address in addresses: | |
| if address: # Skip empty inputs | |
| result = check_flagged_address(address, hf_token) | |
| results.append(result) | |
| else: | |
| results.append("Empty address entered, please try again.") | |
| return "\n\n".join(results) # Combine results with two newlines | |
| # Gradio chat function | |
| def chat_with_agent(user_input, chat_history, hf_token): | |
| if not chat_history: | |
| chat_history = [] | |
| # If the user input is empty, respond like a chatbot | |
| if not user_input.strip(): | |
| chat_history.append({"role": "user", "content": "I didn't enter an address."}) | |
| chat_history.append({"role": "assistant", "content": "It seems like you didn't enter an address. Please input a valid cryptocurrency address to check if it’s flagged."}) | |
| return chat_history, "" | |
| # Check if token is provided | |
| if not hf_token or hf_token.strip() == "": | |
| chat_history.append({"role": "user", "content": user_input}) | |
| chat_history.append({"role": "assistant", "content": "Please enter a valid Hugging Face API token."}) | |
| return chat_history, "" | |
| # Handle multiple addresses | |
| response = handle_multiple_addresses(user_input, hf_token) | |
| # Append as OpenAI-style messages | |
| chat_history.append({"role": "user", "content": user_input}) | |
| chat_history.append({"role": "assistant", "content": response}) | |
| # Return updated history and clear the input box | |
| return chat_history, "" | |
| # Create the Gradio interface with tabs | |
| with gr.Blocks(title="Bybit Hack Address Checker") as demo: | |
| gr.Markdown("# Bybit Hack Address Checker") | |
| with gr.Tabs(): | |
| # Tab 1: Address Checker UI | |
| with gr.Tab(label="Check Address"): | |
| gr.Markdown("Enter one or more cryptocurrency addresses (separated by commas) to check if they're flagged in the Bybit hack database.") | |
| gr.Markdown("Provide your Hugging Face API token below (get it from [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens)).") | |
| # HF Token input | |
| hf_token_input = gr.Textbox( | |
| placeholder="Enter your Hugging Face API token here", | |
| label="Hugging Face API Token", | |
| type="password", | |
| lines=1 | |
| ) | |
| # Chatbot component with messages format | |
| chatbot = gr.Chatbot(label="Conversation", type="messages") | |
| # Address input | |
| msg = gr.Textbox( | |
| placeholder="Enter address(es) here (separated by commas)", | |
| label="Address", | |
| lines=1 | |
| ) | |
| # Clear button | |
| clear = gr.Button("Clear") | |
| # Submit event | |
| msg.submit( | |
| fn=chat_with_agent, | |
| inputs=[msg, chatbot, hf_token_input], | |
| outputs=[chatbot, msg] | |
| ) | |
| # Clear event | |
| clear.click( | |
| fn=lambda: ([], ""), | |
| inputs=None, | |
| outputs=[chatbot, msg] | |
| ) | |
| # Tab 2: Explanation | |
| with gr.Tab(label="About This App"): | |
| gr.Markdown(""" | |
| ## What This App Does | |
| This application helps you verify if a cryptocurrency address is associated with the Bybit hack, as tracked by the Elliptic dataset. Here’s how it works: | |
| 1. **Input one or more Addresses**: Enter one or more wallet addresses (separated by commas). | |
| 2. **Provide HF Token**: Supply a Hugging Face API token to access the AI model powering the agent. | |
| 3. **Agent Processing**: The app uses a **language model** to infer the blockchain of each address (Ethereum, Bitcoin, Tron, etc.). | |
| 4. **Flag Check**: It then checks each address against a list of flagged addresses from the Elliptic Bybit hack dataset (`https://dt074px2e9qbh.cloudfront.net/exploit-api.json`). | |
| 5. **Result**: You’ll see whether each address is flagged ✅ or not ❌, its chain type, and if it’s present in the database. | |
| ### Why It’s Useful | |
| - **Security**: Quickly check if any address you're dealing with is linked to a known exploit. | |
| - **Free & Open**: Uses free-tier AI and public data, making it accessible to anyone with an HF account. | |
| - **Educational**: Demonstrates AI-driven blockchain analysis with a large language model. | |
| Get started by entering your HF token and addresses in the 'Check Address' tab! | |
| """) | |
| # Launch the app | |
| demo.launch() | |