File size: 3,073 Bytes
eae31d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
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)