github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/utilities/common/compiler/vyper.go (about)

     1  package compiler
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"os/exec"
     9  	"strconv"
    10  	"strings"
    11  )
    12  
    13  type Vyper struct {
    14  	Path, Version, FullVersion string
    15  	Major, Minor, Patch        int
    16  }
    17  
    18  func (s *Vyper) makeArgs() []string {
    19  	p := []string{
    20  		"-f", "combined_json",
    21  	}
    22  	return p
    23  }
    24  
    25  func VyperVersion(vyper string) (*Vyper, error) {
    26  	if vyper == "" {
    27  		vyper = "vyper"
    28  	}
    29  	var out bytes.Buffer
    30  	cmd := exec.Command(vyper, "--version")
    31  	cmd.Stdout = &out
    32  	err := cmd.Run()
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	matches := versionRegexp.FindStringSubmatch(out.String())
    37  	if len(matches) != 4 {
    38  		return nil, fmt.Errorf("can't parse vyper version %q", out.String())
    39  	}
    40  	s := &Vyper{Path: cmd.Path, FullVersion: out.String(), Version: matches[0]}
    41  	if s.Major, err = strconv.Atoi(matches[1]); err != nil {
    42  		return nil, err
    43  	}
    44  	if s.Minor, err = strconv.Atoi(matches[2]); err != nil {
    45  		return nil, err
    46  	}
    47  	if s.Patch, err = strconv.Atoi(matches[3]); err != nil {
    48  		return nil, err
    49  	}
    50  	return s, nil
    51  }
    52  
    53  func CompileVyper(vyper string, sourcefiles ...string) (map[string]*Contract, error) {
    54  	if len(sourcefiles) == 0 {
    55  		return nil, errors.New("vyper: no source files")
    56  	}
    57  	source, err := slurpFiles(sourcefiles)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  	s, err := VyperVersion(vyper)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  	args := s.makeArgs()
    66  	cmd := exec.Command(s.Path, append(args, sourcefiles...)...)
    67  	return s.run(cmd, source)
    68  }
    69  
    70  func (s *Vyper) run(cmd *exec.Cmd, source string) (map[string]*Contract, error) {
    71  	var stderr, stdout bytes.Buffer
    72  	cmd.Stderr = &stderr
    73  	cmd.Stdout = &stdout
    74  	if err := cmd.Run(); err != nil {
    75  		return nil, fmt.Errorf("vyper: %v\n%s", err, stderr.Bytes())
    76  	}
    77  
    78  	return ParseVyperJSON(stdout.Bytes(), source, s.Version, s.Version, strings.Join(s.makeArgs(), " "))
    79  }
    80  
    81  func ParseVyperJSON(combinedJSON []byte, source string, languageVersion string, compilerVersion string, compilerOptions string) (map[string]*Contract, error) {
    82  	var output map[string]interface{}
    83  	if err := json.Unmarshal(combinedJSON, &output); err != nil {
    84  		return nil, err
    85  	}
    86  
    87  	contracts := make(map[string]*Contract)
    88  	for name, info := range output {
    89  
    90  		if name == "version" {
    91  			continue
    92  		}
    93  		c := info.(map[string]interface{})
    94  
    95  		contracts[name] = &Contract{
    96  			Code:        c["bytecode"].(string),
    97  			RuntimeCode: c["bytecode_runtime"].(string),
    98  			Info: ContractInfo{
    99  				Source:          source,
   100  				Language:        "Vyper",
   101  				LanguageVersion: languageVersion,
   102  				CompilerVersion: compilerVersion,
   103  				CompilerOptions: compilerOptions,
   104  				SrcMap:          c["source_map"],
   105  				SrcMapRuntime:   "",
   106  				AbiDefinition:   c["abi"],
   107  				UserDoc:         "",
   108  				DeveloperDoc:    "",
   109  				Metadata:        "",
   110  			},
   111  		}
   112  	}
   113  	return contracts, nil
   114  }