PureVersation / src /dynamic_compiler.py
GitHub Actions
🚀 Automated sync from GitHub
eae31d8
import os
import json
import solcx
def compile_contract(sol_file_path, contract_name="PureVersation"):
"""
Compiles a Solidity smart contract using py-solc-x.
Returns the ABI and Bytecode.
Caches the result to a JSON file to speed up subsequent loads.
"""
# Define cache file next to the sol file
cache_file = sol_file_path.replace('.sol', '_compiled.json')
# Optional: If you want to force recompile on every run, remove the cache check
if os.path.exists(cache_file):
try:
with open(cache_file, 'r', encoding='utf-8') as f:
data = json.load(f)
print(f"Loaded compiled contract from cache: {cache_file}")
return data["abi"], data["bytecode"]
except Exception as e:
print(f"Failed to load cached compiled contract: {e}. Recompiling...")
print(f"Dynamically compiling {sol_file_path} ...")
# 1. Install or load solc version 0.8.0
solc_version = "0.8.0"
try:
solcx.install_solc(solc_version)
solcx.set_solc_version(solc_version)
except Exception as e:
print(f"Failed to install/set solc compiler: {e}")
# If running in a restricted environment where binary download fails,
# it will throw an exception here.
raise e
# 2. Compile the .sol file
try:
compiled_sol = solcx.compile_files(
[sol_file_path],
output_values=["abi", "bin"],
solc_version=solc_version
)
# 3. Extract ABI and Bytecode
# The key in compiled_sol looks like: '<absolute_path>:<ContractName>'
contract_key = f"{sol_file_path}:{contract_name}"
if contract_key not in compiled_sol:
# Fallback if path separators cause mismatch
for key in compiled_sol.keys():
if key.endswith(f":{contract_name}"):
contract_key = key
break
contract_interface = compiled_sol[contract_key]
abi = contract_interface['abi']
bytecode = contract_interface['bin']
# 4. Save to cache
with open(cache_file, 'w', encoding='utf-8') as f:
json.dump({"abi": abi, "bytecode": bytecode}, f, indent=4)
print(f"Compilation successful! Saved to {cache_file}")
return abi, bytecode
except Exception as e:
print(f"Compilation failed: {e}")
raise e
# Provide a quick fetcher that integrates with config
def get_contract_interface():
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sol_path = os.path.join(base_dir, "src", "PureVersation.sol")
return compile_contract(sol_path, "PureVersation")
if __name__ == "__main__":
# Test the compiler when run standalone
print("Testing Dynamic Compiler...")
try:
abi, bin_code = get_contract_interface()
print(f"Success! ABI length: {len(abi)} methods, Bytecode length: {len(bin_code)} chars")
except Exception as e:
print(e)