Kancil / app.py
Benny-Tang's picture
Update app.py
fb71589 verified
import gradio as gr
import pandas as pd
import time
# --- 1. Compliance Simulator Logic ---
def compliance_check(investor_country, accreditation_status, investment_amount):
"""
Simulates the Kancil L1's native Compliance Engine pre-compile check.
Compliance rules are hardcoded for demonstration purposes.
"""
time.sleep(1) # Simulate network latency
# Rule 1: Must be an accredited investor for high-value RWA
if accreditation_status != "Accredited Investor":
return f"❌ **Transaction Rejected**\n\nReason: Investor status '{accreditation_status}' does not meet the minimum requirement of 'Accredited Investor' for this RWA token. Compliance enforced at L1 protocol level."
# Rule 2: Geo-fencing (e.g., cannot invest from a sanctioned country)
if investor_country in ["North Korea", "Iran", "Syria"]:
return f"❌ **Transaction Rejected**\n\nReason: Investor country '{investor_country}' is on the network's restricted list. Compliance enforced at L1 protocol level."
# Rule 3: Minimum investment threshold
if investment_amount < 10000:
return f"❌ **Transaction Rejected**\n\nReason: Investment amount (${investment_amount:,.2f}) is below the minimum required threshold of $10,000. Compliance enforced at L1 protocol level."
# If all checks pass
return f"βœ… **Transaction Approved**\n\nCompliance Engine Pre-Compile Check Passed. Token transfer is authorized."
# --- 2. DAO Voting Mockup Logic ---
# Initial state of the DAO proposal
dao_proposal = {
"title": "K-DAO Proposal 001: Approve Tokenization of Dubai Office Tower (Asset ID: DXB-CRE-001)",
"description": "Proposal to onboard a $50M Commercial Real Estate asset located in the Dubai International Financial Centre (DIFC).",
"yes_votes": 1500000,
"no_votes": 500000,
"quorum": 2000000,
"status": "Active",
"end_date": "2026-01-31"
}
# Mock function to update the vote count
def cast_vote(vote_type, voting_power):
global dao_proposal
if dao_proposal["status"] != "Active":
return "Voting is closed."
try:
power = int(voting_power)
except ValueError:
return "Invalid voting power. Please enter a number."
if vote_type == "Yes":
dao_proposal["yes_votes"] += power
elif vote_type == "No":
dao_proposal["no_votes"] += power
# Check if quorum is met
total_votes = dao_proposal["yes_votes"] + dao_proposal["no_votes"]
if total_votes >= dao_proposal["quorum"]:
dao_proposal["status"] = "Passed" if dao_proposal["yes_votes"] > dao_proposal["no_votes"] else "Failed"
return display_dao_status()
# Function to display the current DAO status
def display_dao_status():
total_votes = dao_proposal["yes_votes"] + dao_proposal["no_votes"]
progress = (total_votes / dao_proposal["quorum"]) * 100
status_text = f"""
**Proposal:** {dao_proposal['title']}
**Status:** {dao_proposal['status']}
**Quorum Required:** {dao_proposal['quorum']:,} $KANCIL
**Total Votes Cast:** {total_votes:,} $KANCIL
**Yes Votes:** {dao_proposal['yes_votes']:,} $KANCIL
**No Votes:** {dao_proposal['no_votes']:,} $KANCIL
**Voting Ends:** {dao_proposal['end_date']}
"""
return status_text
# --- 3. Asset Dashboard Mockup (Static) ---
asset_data = {
"Metric": ["Asset ID", "Asset Type", "Location", "Total Value Tokenized", "Tokens Issued", "Compliance Status", "Last Income Distribution"],
"Value": ["DXB-CRE-001", "Commercial Real Estate (Office)", "Dubai, UAE", "$50,000,000", "50,000,000", "Fully Compliant (Kancil L1 Enforced)", "2025-12-01 (Automated by Smart Contract)"]
}
asset_df = pd.DataFrame(asset_data)
# --- Gradio Interface Setup ---
# Compliance Simulator Tab
compliance_tab = gr.Interface(
fn=compliance_check,
inputs=[
gr.Dropdown(["USA", "UAE", "Singapore", "Germany", "UK", "Japan"], label="Investor Country (Simulated Geo-Fencing)"),
gr.Dropdown(["Accredited Investor", "Non-Accredited Investor", "Institutional Investor"], label="Accreditation Status (Simulated Whitelist)"),
gr.Slider(minimum=1000, maximum=100000, step=1000, value=10000, label="Investment Amount (Simulated Threshold)")
],
outputs=gr.Markdown(label="Kancil L1 Compliance Engine Result"),
title="Kancil L1 Compliance Simulator",
description="Demonstrates the L1's native pre-compile for enforcing RWA compliance rules before a transaction is executed."
)
# DAO Voting Tab
dao_status_output = gr.Markdown(value=display_dao_status())
dao_tab = gr.Interface(
fn=cast_vote,
inputs=[
gr.Radio(["Yes", "No"], label="Your Vote"),
gr.Number(label="Your Voting Power ($KANCIL)", value=1000)
],
outputs=dao_status_output,
title="Kancil Asset Management DAO (K-DAO) Mockup",
description="Simulates the decentralized governance process for approving new assets and network changes."
)
# Asset Dashboard Tab
with gr.Blocks() as asset_tab:
gr.Markdown("## Tokenized Asset Dashboard (Static Mockup)")
gr.Markdown("A static view of a tokenized asset, showing the data transparency and visual representation enabled by the Kancil L1.")
# FIX: Removed type="filepath" and relied on Gradio's static file serving for the value.
# This avoids the internal file-moving logic that caused the NotADirectoryError.
gr.Image(label="Tokenized Asset Visual (DXB-CRE-001)", value="assets/cre_exterior.png")
gr.Dataframe(value=asset_df, label="Asset Metadata")
# Combine all tabs
demo = gr.TabbedInterface(
[compliance_tab, dao_tab, asset_tab],
["Compliance Simulator", "K-DAO Voting", "Asset Dashboard"],
title="Kancil: Autonomous RWA L1 MVP(Demo)"
)
if __name__ == "__main__":
demo.launch()