import streamlit as st from solcx import compile_source, install_solc import json import streamlit.components.v1 as components # --- PAGE CONFIG --- st.set_page_config( layout="wide", page_title="Vivara Forge", page_icon="🦁", initial_sidebar_state="collapsed", ) # --- HIDE ALL STREAMLIT UI --- st.markdown( """ """, unsafe_allow_html=True, ) # --- SESSION STATE --- if "code" not in st.session_state: st.session_state.code = """// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract MyToken { string public name = "Vivara Coin"; string public symbol = "VIVR"; uint8 public decimals = 18; uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); constructor(uint256 _initialSupply) { totalSupply = _initialSupply * 10 ** decimals; balanceOf[msg.sender] = totalSupply; emit Transfer(address(0), msg.sender, totalSupply); } function transfer(address to, uint256 amount) public returns (bool) { require(balanceOf[msg.sender] >= amount, "Insufficient balance"); balanceOf[msg.sender] -= amount; balanceOf[to] += amount; emit Transfer(msg.sender, to, amount); return true; } function approve(address spender, uint256 amount) public returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transferFrom(address from, address to, uint256 amount) public returns (bool) { require(balanceOf[from] >= amount, "Insufficient balance"); require(allowance[from][msg.sender] >= amount, "Allowance exceeded"); allowance[from][msg.sender] -= amount; balanceOf[from] -= amount; balanceOf[to] += amount; emit Transfer(from, to, amount); return true; } }""" if "abi" not in st.session_state: st.session_state.abi = None if "bytecode" not in st.session_state: st.session_state.bytecode = None if "contract_name" not in st.session_state: st.session_state.contract_name = None if "logs" not in st.session_state: st.session_state.logs = [] if "compile_trigger" not in st.session_state: st.session_state.compile_trigger = False # --- COMPILE FUNCTION --- def do_compile(): try: st.session_state.logs.append("[INFO] Installing solc 0.8.20...") install_solc("0.8.20") st.session_state.logs.append("[INFO] Compiling Solidity code...") compiled = compile_source( st.session_state.code, output_values=["abi", "bin"], solc_version="0.8.20" ) contract_id, interface = list(compiled.items())[-1] st.session_state.abi = interface["abi"] st.session_state.bytecode = interface["bin"] st.session_state.contract_name = contract_id.split(":")[-1] st.session_state.logs.append( f"[SUCCESS] Compiled: {st.session_state.contract_name}" ) return True except Exception as e: st.session_state.logs.append(f"[ERROR] {str(e)}") return False # Check for compile trigger if st.session_state.compile_trigger: do_compile() st.session_state.compile_trigger = False # --- FULL REMIX-LIKE HTML APP --- abi_json = json.dumps(st.session_state.abi) if st.session_state.abi else "null" bytecode = st.session_state.bytecode or "" contract_name = st.session_state.contract_name or "No Contract" logs_html = ( "\\n".join(st.session_state.logs[-15:]) if st.session_state.logs else "[INFO] Vivara Forge Ready - Connect MetaMask to deploy" ) # Escape the code for JS code_escaped = ( st.session_state.code.replace("\\", "\\\\") .replace("`", "\\`") .replace("${", "\\${") ) html = f"""
Not Connected 0x...
📄 Contract.sol ×
📟 Terminal
🚀 Deploy & Run
Contract {contract_name}
Status {"✅ Compiled" if st.session_state.bytecode else "⏳ Not Compiled"}
Bytecode {len(bytecode) if bytecode else 0} bytes
🦁 Vivara Forge v2.0.1
Network: --
Balance: --
""" # Check URL params for compile trigger query_params = st.query_params if query_params.get("compile") == "true": do_compile() # Clear the param st.query_params.clear() # Render full-screen HTML IDE components.html(html, height=850, scrolling=False)