File size: 9,776 Bytes
6aa5728
 
 
31e3c19
6aa5728
 
 
 
 
 
 
31e3c19
6aa5728
 
 
 
31e3c19
 
6aa5728
31e3c19
 
 
 
 
 
 
 
6aa5728
31e3c19
 
 
 
 
 
6aa5728
31e3c19
 
 
6aa5728
31e3c19
 
6aa5728
31e3c19
6aa5728
31e3c19
 
 
6aa5728
31e3c19
 
 
6aa5728
 
 
 
 
 
 
31e3c19
 
 
6aa5728
 
 
 
 
 
31e3c19
 
 
6aa5728
 
 
31e3c19
 
 
6aa5728
31e3c19
 
 
 
 
 
6aa5728
31e3c19
 
 
 
 
 
 
 
 
 
 
 
 
 
6aa5728
31e3c19
 
 
 
 
 
 
6aa5728
31e3c19
 
 
6aa5728
31e3c19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6aa5728
31e3c19
 
 
 
 
 
6aa5728
31e3c19
 
6aa5728
31e3c19
 
6aa5728
31e3c19
 
6aa5728
31e3c19
 
 
 
 
 
6aa5728
31e3c19
 
6aa5728
 
 
31e3c19
 
 
 
6aa5728
31e3c19
 
 
6aa5728
31e3c19
 
 
6aa5728
31e3c19
 
 
6aa5728
31e3c19
 
6aa5728
31e3c19
 
 
 
 
6aa5728
31e3c19
 
6aa5728
31e3c19
 
 
6aa5728
31e3c19
6aa5728
31e3c19
 
 
6aa5728
 
31e3c19
 
 
 
 
 
 
 
6aa5728
 
31e3c19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
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.")