# app.py # Author: James Burvel O'Callaghan III # Company: CITIBANK DEMO BUSINESS INC # Description: Self-Sustaining Blockchain-Integrated AI Monetization Ecosystem with Streamlit Interface import os import uuid import hashlib import json from datetime import datetime import streamlit as st import requests from sqlalchemy import create_engine, Column, Integer, String, Float, Boolean, DateTime, ForeignKey from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker import openai # ======================== # Streamlit Configuration UI # ======================== st.set_page_config(page_title="CITIBANK DEMO BUSINESS INC AI Crypto Ecosystem", layout="wide") st.title("🌟 CITIBANK DEMO BUSINESS INC AI Crypto Ecosystem 🌟") st.sidebar.header("🔧 Configuration Settings") # Database Configuration st.sidebar.subheader("📚 Database Configuration") db_type = st.sidebar.selectbox("Select Database Type", ("SQLite", "PostgreSQL")) if db_type == "SQLite": sqlite_db_path = st.sidebar.text_input("SQLite Database File Path", value="citibank_demo_business_inc_ai_crypto.db") DATABASE_URI = f"sqlite:///{sqlite_db_path}" elif db_type == "PostgreSQL": pg_host = st.sidebar.text_input("PostgreSQL Host", value="localhost") pg_port = st.sidebar.number_input("PostgreSQL Port", min_value=1, max_value=65535, value=5432) pg_user = st.sidebar.text_input("PostgreSQL Username", value="postgres") pg_password = st.sidebar.text_input("PostgreSQL Password", type="password") pg_db = st.sidebar.text_input("PostgreSQL Database Name", value="citibank_demo_business_inc_ai_crypto") DATABASE_URI = f"postgresql://{pg_user}:{pg_password}@{pg_host}:{pg_port}/{pg_db}" # Blockchain Configuration st.sidebar.subheader("🔗 Blockchain Configuration") BLOCKCHAIN_NODE_URL = st.sidebar.text_input("Blockchain Node URL", value="https://rpc.buildbear.io/linguistic-doctorstrange-fb0930a4") # Hardcoded Smart Contract Address CONTRACT_ADDRESS = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" # USDC Token Address # OpenAI Configuration (Optional) st.sidebar.subheader("🤖 OpenAI Configuration") OPENAI_API_KEY = st.sidebar.text_input("OpenAI API Key (Optional)", type="password") # Blockchain Address Configuration st.sidebar.subheader("🔗 Your Blockchain Address") default_token_address = st.sidebar.text_input("Your Blockchain Address (0x...)", value="0x7B35A86fa8cE689b6D8111C09217E7466B5c442A") # Example address # ======================== # Validate Configuration Inputs # ======================== config_valid = True config_errors = [] if not BLOCKCHAIN_NODE_URL.startswith("http"): config_valid = False config_errors.append("Blockchain Node URL must start with http or https.") if not (CONTRACT_ADDRESS.startswith("0x") and len(CONTRACT_ADDRESS) == 42): config_valid = False config_errors.append("Invalid Smart Contract Address.") if db_type == "PostgreSQL": if not all([pg_host, pg_port, pg_user, pg_password, pg_db]): config_valid = False config_errors.append("All PostgreSQL configuration fields must be filled.") if not config_valid: st.error("âš ī¸ **Configuration Errors:**") for error in config_errors: st.error(f"- {error}") st.stop() # Initialize OpenAI API if API key is provided if OPENAI_API_KEY: openai.api_key = OPENAI_API_KEY openai_enabled = True st.sidebar.success("🔌 OpenAI Connected") else: openai_enabled = False st.sidebar.info("🤖 OpenAI not connected. AI features are disabled.") # ======================== # Database Setup # ======================== Base = declarative_base() class Token(Base): __tablename__ = 'tokens' id = Column(String(36), primary_key=True) # UUID value = Column(Float, nullable=False) text = Column(String(256), nullable=False) # Text to store on blockchain recipient_address = Column(String(42), nullable=False) # Address receiving tokens verified = Column(Boolean, default=False) verification_hash = Column(String(64)) created_at = Column(DateTime, default=datetime.utcnow) class Transaction(Base): __tablename__ = 'transactions' id = Column(Integer, primary_key=True) token_id = Column(String(36), ForeignKey('tokens.id'), nullable=True) action = Column(String(50), nullable=False) value = Column(Float, nullable=True) hash = Column(String(64), nullable=True) timestamp = Column(DateTime, default=datetime.utcnow) class Stake(Base): __tablename__ = 'stakes' id = Column(Integer, primary_key=True) amount = Column(Float, nullable=False) timestamp = Column(DateTime, default=datetime.utcnow) # Create database engine and session if db_type == "SQLite": engine = create_engine(DATABASE_URI, connect_args={"check_same_thread": False}) else: engine = create_engine(DATABASE_URI) Base.metadata.create_all(engine) Session = sessionmaker(bind=engine) session = Session() # ======================== # Utility Functions # ======================== def mint_tokens_via_api(address, token, balance): """ Mints tokens by calling the external API endpoint. Returns True if successful, False otherwise. """ url = 'https://backend.buildbear.io/node/faucet/erc20/linguistic-doctorstrange-fb0930a4' headers = { 'accept': '*/*', 'accept-language': 'en-US,en;q=0.9', 'cache-control': 'no-cache', 'content-type': 'application/json', 'dnt': '1', 'origin': 'https://faucet.buildbear.io', 'pragma': 'no-cache', 'priority': 'u=1, i', 'referer': 'https://faucet.buildbear.io/', 'sec-ch-ua': '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Chrome OS"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-site', 'user-agent': 'Mozilla/5.0 (X11; CrOS x86_64 14541.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36' } payload = { "address": address, "token": token, "balance": balance } try: response = requests.post(url, headers=headers, json=payload) if response.status_code == 200: return True, None else: return False, response.text except requests.exceptions.RequestException as e: return False, str(e) def calculate_token_grade(ai_output): """ Sends AI output back to AI to grade it based on a predefined rubric. Returns the grade which determines the number of tokens. """ if not openai_enabled: return 0 # No grading if OpenAI is not enabled try: # Define the grading rubric as a prompt grading_prompt = f""" Please grade the following AI-generated content based on its relevance, coherence, and usefulness. Use a scale from 1 to 10, where 10 is highly valuable and 1 is not valuable at all. AI Output: \"\"\" {ai_output} \"\"\" Grade: """ response = openai.Completion.create( engine="text-davinci-003", # Use 'gpt-4' if available prompt=grading_prompt, max_tokens=10, temperature=0, n=1, stop=None ) grade_text = response.choices[0].text.strip() grade = int(grade_text) # Define maximum tokens per grade max_tokens = 100 token_amount = (grade / 10) * max_tokens return token_amount except Exception as e: st.error(f"❌ Error grading AI output: {str(e)}") return 0 def process_ai(input_text): """ Processes input text using OpenAI's GPT-4 API. """ if not openai_enabled: return "❌ OpenAI is not configured. Please provide an OpenAI API Key to use AI features." try: response = openai.Completion.create( engine="text-davinci-003", # Use 'gpt-4' if available prompt=input_text, max_tokens=150, temperature=0.7, n=1, stop=None ) ai_output = response.choices[0].text.strip() return ai_output except Exception as e: return f"❌ Error processing AI output: {str(e)}" # ======================== # Initialize Application State # ======================== # For the purpose of this version without user authentication, # we'll manage a single global balance and staked tokens. # In a multi-user scenario, this should be adjusted accordingly. if 'balance' not in st.session_state: st.session_state.balance = 0.0 if 'staked' not in st.session_state: st.session_state.staked = 0.0 # ======================== # User Dashboard with Tabs # ======================== st.header("🌟 Dashboard 🌟") # Display Balance st.subheader("💰 Balance") col1, col2 = st.columns(2) col1.metric("Tokens", f"{st.session_state.balance:.2f}") col2.metric("Staked Tokens", f"{st.session_state.staked:.2f}") # Create Tabs based on OpenAI configuration tabs_titles = ["Token Management", "Staking", "Trading", "Transaction History"] if openai_enabled: tabs_titles.insert(0, "AI Query") tabs_titles.append("Chat") tabs_titles.append("About") tabs = st.tabs(tabs_titles) # ======================== # AI Query Submission (Optional) # ======================== if openai_enabled: with tabs[0]: st.subheader("🤖 Submit AI Query") with st.form("ai_query_form"): input_text = st.text_area("Enter your query here...", height=100) submit_button = st.form_submit_button(label='Submit') if submit_button: if input_text.strip() == "": st.error("❌ Input text cannot be empty.") else: with st.spinner("🔍 Processing your AI query..."): ai_output = process_ai(input_text) if ai_output.startswith("❌"): st.error(ai_output) else: st.success("✅ AI Query Processed!") st.write(f"**AI Output:** {ai_output}") # Grade AI Output token_amount = calculate_token_grade(ai_output) if token_amount > 0: # Mint Token via API token_address = default_token_address # Using configurable address token_contract = CONTRACT_ADDRESS # Using hardcoded contract address balance = "100" # Adjust as needed mint_success, mint_response = mint_tokens_via_api(token_address, token_contract, balance) if mint_success: st.success("✅ Token minted successfully via API!") # Update local database token = Token( id=str(uuid.uuid4()), value=token_amount, text=input_text, # Store the input text recipient_address=token_address, verified=False, verification_hash=hashlib.sha256(ai_output.encode()).hexdigest() ) session.add(token) session.commit() # Update session state balance st.session_state.balance += token_amount # Record transaction transaction = Transaction( token_id=token.id, action='minted', value=token.value, hash=token.verification_hash ) session.add(transaction) session.commit() st.write(f"**Token ID:** {token.id}") st.write(f"**Tokens Earned:** {token.value:.2f}") st.write(f"**Stored Text:** {token.text}") else: st.error(f"❌ Token minting failed: {mint_response}") else: st.error("❌ Token amount determined as zero. Please try again.") # ======================== # Token Management # ======================== token_tab_index = 0 if openai_enabled: token_tab_index = 1 with tabs[token_tab_index]: st.subheader("đŸĒ™ Tokens") tokens = session.query(Token).all() if tokens: token_data = [] for token in tokens: token_info = { "Token ID": token.id, "Value": f"{token.value:.2f}", "Recipient Address": token.recipient_address, "Text": token.text, "Verified": "Yes" if token.verified else "No", "Verification Hash": token.verification_hash or "N/A", "Created At": token.created_at.strftime('%Y-%m-%d %H:%M:%S') } token_data.append(token_info) st.table(token_data) else: st.write("📭 No tokens found.") # ======================== # Staking # ======================== staking_tab_index = token_tab_index + 1 with tabs[staking_tab_index]: st.subheader("📈 Stake Tokens") with st.form("stake_form"): stake_amount = st.number_input("Amount to Stake", min_value=0.0, step=1.0) stake_button = st.form_submit_button(label='Stake Tokens') if stake_button: if stake_amount <= 0: st.error("❌ Stake amount must be greater than zero.") elif st.session_state.balance < stake_amount: st.error("❌ Insufficient balance.") else: st.session_state.balance -= stake_amount st.session_state.staked += stake_amount stake = Stake( amount=stake_amount ) session.add(stake) session.commit() # Record transaction transaction = Transaction( action='stake', value=stake_amount ) session.add(transaction) session.commit() st.success("✅ Staked successfully.") st.write(f"**New Balance:** {st.session_state.balance:.2f}") st.write(f"**Total Staked:** {st.session_state.staked:.2f}") # ======================== # Trading # ======================== trading_tab_index = staking_tab_index + 1 with tabs[trading_tab_index]: st.subheader("🔄 Trade Tokens") with st.form("trade_form"): seller_address = st.text_input("Seller Blockchain Address (0x...)") token_id = st.text_input("Token ID") trade_button = st.form_submit_button(label='Trade Token') if trade_button: if seller_address.strip() == "" or token_id.strip() == "": st.error("❌ Seller address and Token ID are required.") elif not (seller_address.startswith("0x") and len(seller_address) == 42): st.error("❌ Invalid Blockchain Address format.") else: token = session.query(Token).filter_by(id=token_id, recipient_address=seller_address).first() if not token: st.error("❌ Token not found or unauthorized.") else: # Transfer ownership by updating recipient address token.recipient_address = default_token_address # Using configurable address session.commit() # Update session state balance st.session_state.balance += token.value # Record transaction transaction = Transaction( token_id=token.id, action='trade', value=token.value ) session.add(transaction) session.commit() st.success("✅ Trade successful.") st.write(f"**New Balance:** {st.session_state.balance:.2f}") st.write(f"**Token Value:** {token.value:.2f}") # ======================== # Transaction History # ======================== transaction_history_tab_index = trading_tab_index + 1 with tabs[transaction_history_tab_index]: st.subheader("📜 Transaction History") transactions = session.query(Transaction).order_by(Transaction.timestamp.desc()).all() if transactions: transaction_data = [] for tx in transactions: tx_info = { "Action": tx.action, "Value": f"{tx.value:.2f}" if tx.value else "N/A", "Hash": tx.hash or "N/A", "Timestamp": tx.timestamp.strftime('%Y-%m-%d %H:%M:%S') } transaction_data.append(tx_info) st.table(transaction_data) else: st.write("📭 No transactions found.") # ======================== # Chat Interface (Optional) # ======================== if openai_enabled: chat_tab_index = transaction_history_tab_index + 1 with tabs[chat_tab_index]: st.subheader("đŸ’Ŧ Chat with CITIBANK DEMO BUSINESS INC AI") if 'chat_history' not in st.session_state: st.session_state['chat_history'] = [] def get_ai_response(user_input): """ Generate AI response using OpenAI. """ try: response = openai.Completion.create( engine="text-davinci-003", # Use 'gpt-4' if available prompt=user_input, max_tokens=150, temperature=0.7, n=1, stop=None ) ai_output = response.choices[0].text.strip() return ai_output except Exception as e: return f"❌ Error processing AI output: {str(e)}" user_input = st.text_input("You:", key="chat_input") if st.button("Send"): if user_input.strip() == "": st.warning("❌ Please enter a message.") else: st.session_state.chat_history.append(("You", user_input)) ai_response = get_ai_response(user_input) st.session_state.chat_history.append(("CITIBANK DEMO BUSINESS INC AI", ai_response)) for sender, message in st.session_state.chat_history: if sender == "You": st.markdown(f"**You:** {message}") else: st.markdown(f"**CITIBANK DEMO BUSINESS INC AI:** {message}") # ======================== # About Me Tab # ======================== about_me_tab_index = transaction_history_tab_index + (2 if openai_enabled else 1) with tabs[about_me_tab_index]: st.subheader("â„šī¸ About CITIBANK DEMO BUSINESS INC AI Crypto Ecosystem") st.markdown(""" ### 🌟 Overview The **CITIBANK DEMO BUSINESS INC AI Crypto Ecosystem** is a cutting-edge platform that seamlessly integrates **Artificial Intelligence** with **Blockchain Technology** to create a **self-sustaining** and **monetizable** ecosystem. This system empowers users to interact with AI services, earn and manage cryptocurrency tokens, and participate in a transparent and decentralized economy. ### 🚀 Features - **AI Query Submission:** Submit queries to the AI and receive insightful responses. *(Requires OpenAI API Key)* - **AI Grading Mechanism:** AI evaluates its own outputs based on a predefined rubric to determine token rewards. *(Requires OpenAI API Key)* - **Token Minting:** Earn tokens based on the AI-generated content's quality. - **Token Management:** View and manage your tokens, including verification status. - **Staking:** Stake your tokens to earn rewards and support the ecosystem. - **Trading:** Trade tokens within the ecosystem. - **Transaction History:** Transparent logs of all your activities. - **Chat Interface:** Interact with the AI through a dedicated chat box. *(Requires OpenAI API Key)* - **About Section:** Detailed information about the ecosystem and its functionalities. ### đŸ› ī¸ Technology Stack - **Backend:** Streamlit, SQLAlchemy - **Frontend:** Streamlit Interface with Tabs - **Blockchain:** Solidity, Ethereum (or any EVM-compatible blockchain) - **Database:** SQLite (for demonstration) or PostgreSQL (for production) - **AI Services:** OpenAI GPT-4 API *(Optional)* ### 🔒 Security - **Input Validation:** Comprehensive validation to prevent vulnerabilities like SQL injection and XSS attacks. - **Secure Data Handling:** Sensitive information such as API keys are managed securely within the application interface. ### 🌐 Deployment The application is optimized for deployment on **Hugging Face Spaces**, ensuring accessibility and scalability. Users can configure all necessary settings directly through the Streamlit interface, eliminating the need for external environment variables. ### 📈 Scalability - **Modular Design:** Each component is isolated, allowing for independent scaling and maintenance. - **Efficient Database Management:** Utilizing SQLAlchemy for optimized interactions. - **Asynchronous Processing:** Background threads handle long-running tasks without blocking the main application. - **Optimized API Interactions:** Efficient handling of API requests to manage high volumes of token minting. --- *Embark on this transformative journey with **CITIBANK DEMO BUSINESS INC** to redefine the synergy between AI and blockchain, creating an unparalleled decentralized economy.* """) # ======================== # Mint Token Functionality # ======================== st.sidebar.header("đŸĒ™ Mint Token") with st.sidebar.form("mint_token_form"): mint_address = st.text_input("Recipient Address (0x...)", value=default_token_address) mint_text = st.text_input("Mint Text", value="") mint_button = st.form_submit_button(label='Mint Token') if mint_button: if not mint_address or not mint_text: st.sidebar.error("❌ Both Address and Text are required.") elif not (mint_address.startswith("0x") and len(mint_address) == 42): st.sidebar.error("❌ Invalid Blockchain Address format.") else: with st.spinner("🔍 Minting tokens and storing text..."): # Mint tokens via external API token_contract = CONTRACT_ADDRESS # Using hardcoded contract address balance = "100" # Adjust as needed or make it dynamic mint_success, mint_response = mint_tokens_via_api(mint_address, token_contract, balance) if mint_success: st.sidebar.success("✅ Token minted successfully via API!") # Update local database token = Token( id=str(uuid.uuid4()), value=100.0, # Assuming balance is 100 tokens text=mint_text, # Store the input text recipient_address=mint_address, verified=False, verification_hash=hashlib.sha256(mint_text.encode()).hexdigest() ) session.add(token) session.commit() # Update session state balance st.session_state.balance += token.value # Record transaction transaction = Transaction( token_id=token.id, action='minted', value=token.value, hash=token.verification_hash ) session.add(transaction) session.commit() st.sidebar.write(f"**Token ID:** {token.id}") st.sidebar.write(f"**Tokens Earned:** {token.value:.2f}") st.sidebar.write(f"**Stored Text:** {token.text}") else: st.sidebar.error(f"❌ Token minting failed: {mint_response}")