|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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") |
|
|
|
|
|
|
|
|
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}" |
|
|
|
|
|
|
|
|
st.sidebar.subheader("π Blockchain Configuration") |
|
|
BLOCKCHAIN_NODE_URL = st.sidebar.text_input("Blockchain Node URL", value="https://rpc.buildbear.io/linguistic-doctorstrange-fb0930a4") |
|
|
|
|
|
|
|
|
CONTRACT_ADDRESS = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" |
|
|
|
|
|
|
|
|
st.sidebar.subheader("π€ OpenAI Configuration") |
|
|
OPENAI_API_KEY = st.sidebar.text_input("OpenAI API Key (Optional)", type="password") |
|
|
|
|
|
|
|
|
st.sidebar.subheader("π Your Blockchain Address") |
|
|
default_token_address = st.sidebar.text_input("Your Blockchain Address (0x...)", value="0x7B35A86fa8cE689b6D8111C09217E7466B5c442A") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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() |
|
|
|
|
|
|
|
|
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.") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Base = declarative_base() |
|
|
|
|
|
class Token(Base): |
|
|
__tablename__ = 'tokens' |
|
|
|
|
|
id = Column(String(36), primary_key=True) |
|
|
value = Column(Float, nullable=False) |
|
|
text = Column(String(256), nullable=False) |
|
|
recipient_address = Column(String(42), nullable=False) |
|
|
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) |
|
|
|
|
|
|
|
|
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() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
try: |
|
|
|
|
|
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", |
|
|
prompt=grading_prompt, |
|
|
max_tokens=10, |
|
|
temperature=0, |
|
|
n=1, |
|
|
stop=None |
|
|
) |
|
|
grade_text = response.choices[0].text.strip() |
|
|
grade = int(grade_text) |
|
|
|
|
|
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", |
|
|
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)}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
st.header("π Dashboard π") |
|
|
|
|
|
|
|
|
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}") |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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}") |
|
|
|
|
|
token_amount = calculate_token_grade(ai_output) |
|
|
if token_amount > 0: |
|
|
|
|
|
token_address = default_token_address |
|
|
token_contract = CONTRACT_ADDRESS |
|
|
balance = "100" |
|
|
mint_success, mint_response = mint_tokens_via_api(token_address, token_contract, balance) |
|
|
if mint_success: |
|
|
st.success("β
Token minted successfully via API!") |
|
|
|
|
|
token = Token( |
|
|
id=str(uuid.uuid4()), |
|
|
value=token_amount, |
|
|
text=input_text, |
|
|
recipient_address=token_address, |
|
|
verified=False, |
|
|
verification_hash=hashlib.sha256(ai_output.encode()).hexdigest() |
|
|
) |
|
|
session.add(token) |
|
|
session.commit() |
|
|
|
|
|
st.session_state.balance += token_amount |
|
|
|
|
|
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_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_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() |
|
|
|
|
|
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_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: |
|
|
|
|
|
token.recipient_address = default_token_address |
|
|
session.commit() |
|
|
|
|
|
st.session_state.balance += token.value |
|
|
|
|
|
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_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.") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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", |
|
|
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_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.* |
|
|
""") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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..."): |
|
|
|
|
|
token_contract = CONTRACT_ADDRESS |
|
|
balance = "100" |
|
|
mint_success, mint_response = mint_tokens_via_api(mint_address, token_contract, balance) |
|
|
|
|
|
if mint_success: |
|
|
st.sidebar.success("β
Token minted successfully via API!") |
|
|
|
|
|
token = Token( |
|
|
id=str(uuid.uuid4()), |
|
|
value=100.0, |
|
|
text=mint_text, |
|
|
recipient_address=mint_address, |
|
|
verified=False, |
|
|
verification_hash=hashlib.sha256(mint_text.encode()).hexdigest() |
|
|
) |
|
|
session.add(token) |
|
|
session.commit() |
|
|
|
|
|
|
|
|
st.session_state.balance += token.value |
|
|
|
|
|
|
|
|
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}") |
|
|
|