StarkNetScript / app.py
Rooobert's picture
Update app.py
31e3c19 verified
import streamlit as st
import secrets
import hashlib
import os
import subprocess
import json
from starknet_py.net.account.account import Account
from starknet_py.net.models import StarknetChainId
from starknet_py.net.signer.stark_curve_signer import KeyPair
st.set_page_config(
page_title="StarkNet Development Toolkit",
page_icon="🌟",
layout="wide"
)
st.title("StarkNet Development Toolkit")
st.markdown("A complete workflow for StarkNet development including contract compilation, key generation, and more.")
# Sidebar for navigation
st.sidebar.title("Navigation")
page = st.sidebar.radio("Choose a step:", [
"1. Introduction",
"2. Write & Compile Contract",
"3. Generate Keys",
"4. Interact with StarkNet"
])
# Page 1: Introduction
if page == "1. Introduction":
st.header("Introduction to StarkNet Development")
st.write("""
StarkNet is a permissionless decentralized ZK-Rollup operating as an L2 network over Ethereum.
This application helps you with the full development workflow:
1. **Write and compile Cairo contracts** - Create smart contracts with Cairo language
2. **Generate key pairs and addresses** - Create cryptographic keys for StarkNet
3. **Interact with StarkNet** - Deploy contracts and interact with the network
Use the sidebar to navigate through different steps of the workflow.
""")
st.info("This is a development tool. For production use, please ensure proper security measures.")
# Page 2: Write & Compile Contract
elif page == "2. Write & Compile Contract":
st.header("Write & Compile Cairo Contract")
# Default example contract
default_contract = """
%lang cairo
@external
func transfer{syscall_ptr: felt*, range_check_ptr}(
from_address: felt,
to_address: felt,
amount: felt
) -> (success: felt):
# This is just a simple simulated transfer function
# In a real application, you would need to perform balance checks and state updates
return (1) # Return success
end
@view
func get_balance{syscall_ptr: felt*, range_check_ptr}(
address: felt
) -> (balance: felt):
# This is just a simple simulated balance query function
# In a real application, you would read the actual balance from storage
return (1000) # Return simulated balance
end
"""
# Contract editor
st.subheader("Contract Editor")
contract_code = st.text_area("Edit your Cairo contract:", default_contract, height=400)
# Compile button
if st.button("Compile Contract"):
try:
# Save the contract to a file
with open('token_contract.cairo', 'w') as file:
file.write(contract_code)
# Run the compilation command
with st.spinner("Compiling..."):
result = subprocess.run(
["cairo-compile", "token_contract.cairo", "--output", "token_compiled.json"],
capture_output=True,
text=True
)
if result.returncode == 0:
st.success("Contract compiled successfully!")
# Display compilation output
with open("token_compiled.json", "r") as f:
compiled_json = json.load(f)
# Allow downloading the compiled contract
st.download_button(
label="Download Compiled Contract",
data=json.dumps(compiled_json, indent=2),
file_name="token_compiled.json",
mime="application/json"
)
else:
st.error(f"Compilation failed: {result.stderr}")
except Exception as e:
st.error(f"Error during compilation: {str(e)}")
# Page 3: Generate Keys
elif page == "3. Generate Keys":
st.header("Generate StarkNet Keys")
col1, col2 = st.columns(2)
with col1:
st.subheader("Key Generation")
# Network selection
st.write("Select StarkNet Network:")
network_options = {
"Goerli Testnet": "GOERLI",
"Sepolia Testnet": "SEPOLIA",
"Mainnet": "MAINNET",
"Custom": "CUSTOM"
}
network = st.selectbox("Network", list(network_options.keys()))
if network == "Custom":
chain_id_value = st.number_input("Enter Chain ID value:", value=1536727068981429685321)
else:
try:
chain_id_attr = getattr(StarknetChainId, network_options[network])
chain_id_value = chain_id_attr.value
except (AttributeError, KeyError):
chain_id_value = 1536727068981429685321
st.warning(f"Using default chain ID: {chain_id_value}")
if st.button("Generate New Keys"):
with st.spinner("Generating..."):
# Generate a random private key
private_key = secrets.randbits(251)
private_key_hex = hex(private_key)
# Create key pair
key_pair = KeyPair.from_private_key(private_key)
# Get the public key
public_key = key_pair.public_key
public_key_hex = hex(public_key)
# Create account object
account = Account(
address=0, # Will be populated after deployment
client=None, # No client needed in this example
key_pair=key_pair,
chain=chain_id_value
)
# Get the account address
address = account.address
# Store in session state
st.session_state['private_key'] = private_key_hex
st.session_state['public_key'] = public_key_hex
st.session_state['address'] = hex(address)
st.session_state['chain_id'] = chain_id_value
st.success("Keys generated successfully!")
with col2:
st.subheader("Key Information")
if 'private_key' in st.session_state:
st.markdown("**Private Key:**")
st.code(st.session_state['private_key'])
st.markdown("**Public Key:**")
st.code(st.session_state['public_key'])
st.markdown("**Address:**")
st.code(st.session_state['address'])
st.markdown("**Chain ID:**")
st.code(str(st.session_state['chain_id']))
# Create downloadable key file
key_info = f"""Private Key: {st.session_state['private_key']}
Public Key: {st.session_state['public_key']}
Address: {st.session_state['address']}
Chain ID: {st.session_state['chain_id']}
"""
st.download_button(
label="Download Key Information",
data=key_info,
file_name="starknet_keys.txt",
mime="text/plain"
)
st.warning("⚠️ Keep your private key secure! Never share it with anyone.")
else:
st.info("Generate keys to see the information here.")
# Page 4: Interact with StarkNet
elif page == "4. Interact with StarkNet":
st.header("Interact with StarkNet")
st.info("""
This section provides sample code for interacting with StarkNet.
For actual interaction, you would need:
1. A deployed contract address
2. The contract ABI
3. A funded account
Below is sample code that you can modify for your needs.
""")
interaction_code = """
# StarkNet Interaction Example
from starknet_py.net.gateway_client import GatewayClient
from starknet_py.net.models import StarknetChainId
from starknet_py.contract import Contract
# Set up StarkNet client (using Goerli testnet)
client = GatewayClient(net="goerli") # Or "mainnet" for the mainnet
# Replace with your contract's address and ABI
contract_address = 0x123456789 # Replace with the real contract address
contract_abi = [...] # Contract's ABI, typically obtained from compilation output
# Load the deployed contract
contract = Contract(
address=contract_address,
abi=contract_abi,
client=client,
)
# Replace with your account information
private_key = "YOUR_PRIVATE_KEY"
key_pair = KeyPair.from_private_key(int(private_key, 16))
account = Account(
address=0x..., # Your account address
client=client,
key_pair=key_pair,
chain=StarknetChainId.GOERLI
)
# Example: Call a contract function
async def transfer_tokens():
response = await account.execute(
calls=[
contract.functions["transfer"].prepare(
from_address=account.address,
to_address=0x987654321, # Receiver address
amount=100
)
]
)
print(f"Transaction hash: {response.transaction_hash}")
# Example: Query contract state
async def check_balance(address):
balance = await contract.functions["get_balance"].call(
address=address
)
print(f"Balance: {balance.balance}")
"""
st.code(interaction_code, language="python")
st.subheader("Resources")
st.markdown("""
- [StarkNet Documentation](https://docs.starknet.io/)
- [Cairo Programming Language](https://cairo-lang.org/)
- [starknet-py Library](https://github.com/software-mansion/starknet.py)
""")
st.sidebar.markdown("---")
st.sidebar.info("This application is for educational purposes. Always follow best security practices when working with cryptographic keys.")