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: ':' 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)