github.com/aergoio/aergo@v1.3.1/cmd/brick/exec/deployContract.go (about)

     1  package exec
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"math/big"
     7  	"net/http"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  
    12  	"github.com/aergoio/aergo/cmd/brick/context"
    13  	"github.com/aergoio/aergo/contract"
    14  )
    15  
    16  func init() {
    17  	registerExec(&deployContract{})
    18  }
    19  
    20  type deployContract struct{}
    21  
    22  func (c *deployContract) Command() string {
    23  	return "deploy"
    24  }
    25  
    26  func (c *deployContract) Syntax() string {
    27  	return fmt.Sprintf("%s %s %s %s %s", context.AccountSymbol, context.AmountSymbol,
    28  		context.ContractSymbol, context.PathSymbol, context.ContractArgsSymbol)
    29  }
    30  
    31  func (c *deployContract) Usage() string {
    32  	return fmt.Sprintf("deploy <sender_name> <amount> <contract_name> `<definition_file_path>` `[contructor_json_arg]`")
    33  }
    34  
    35  func (c *deployContract) Describe() string {
    36  	return "deploy a smart contract"
    37  }
    38  
    39  func (c *deployContract) Validate(args string) error {
    40  
    41  	// check whether chain is loaded
    42  	if context.Get() == nil {
    43  		return fmt.Errorf("load chain first")
    44  	}
    45  
    46  	_, _, _, _, _, err := c.parse(args)
    47  
    48  	return err
    49  }
    50  
    51  func (c *deployContract) readDefFile(defPath string) ([]byte, error) {
    52  	if strings.HasPrefix(defPath, "http") {
    53  		// search in the web
    54  		req, err := http.NewRequest("GET", defPath, nil)
    55  		if err != nil {
    56  			return nil, err
    57  		}
    58  		client := &http.Client{}
    59  		resp, err := client.Do(req)
    60  		if err != nil {
    61  			return nil, err
    62  		}
    63  		defer resp.Body.Close()
    64  		defByte, _ := ioutil.ReadAll(resp.Body)
    65  
    66  		return defByte, nil
    67  	}
    68  
    69  	// search in a local file system
    70  	if _, err := os.Stat(defPath); os.IsNotExist(err) {
    71  		return nil, err
    72  	}
    73  	defByte, err := ioutil.ReadFile(defPath)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  
    78  	return defByte, nil
    79  
    80  }
    81  
    82  func (c *deployContract) parse(args string) (string, *big.Int, string, string, string, error) {
    83  	splitArgs := context.SplitSpaceAndAccent(args, false)
    84  	if len(splitArgs) < 4 {
    85  		return "", nil, "", "", "", fmt.Errorf("need 4 arguments. usage: %s", c.Usage())
    86  	}
    87  
    88  	amount, success := new(big.Int).SetString(splitArgs[1].Text, 10)
    89  	if success == false {
    90  		return "", nil, "", "", "", fmt.Errorf("fail to parse number %s", splitArgs[1].Text)
    91  	}
    92  
    93  	defPath := splitArgs[3].Text
    94  	if _, err := c.readDefFile(defPath); err != nil {
    95  		return "", nil, "", "", "", fmt.Errorf("fail to read a contrat def file %s: %s", splitArgs[3].Text, err.Error())
    96  	}
    97  
    98  	constuctorArg := "[]"
    99  	if len(splitArgs) == 5 {
   100  		constuctorArg = splitArgs[4].Text
   101  	} else if len(splitArgs) > 5 {
   102  		return "", nil, "", "", "", fmt.Errorf("too many arguments. usage: %s", c.Usage())
   103  	}
   104  
   105  	return splitArgs[0].Text, //accountName
   106  		amount, // amount
   107  		splitArgs[2].Text, // contractName
   108  		defPath, // defPath
   109  		constuctorArg,
   110  		nil
   111  }
   112  
   113  func (c *deployContract) Run(args string) (string, error) {
   114  	accountName, amount, contractName, defPath, constuctorArg, _ := c.parse(args)
   115  
   116  	defByte, err := c.readDefFile(defPath)
   117  	if err != nil {
   118  		return "", err
   119  	}
   120  
   121  	updateContractInfoInterface(contractName, defPath)
   122  
   123  	err = context.Get().ConnectBlock(
   124  		contract.NewRawLuaTxDefBig(accountName, contractName, amount, string(defByte)).Constructor(constuctorArg),
   125  	)
   126  
   127  	if enableWatch && !strings.HasPrefix(defPath, "http") {
   128  		absPath, _ := filepath.Abs(defPath)
   129  		watcher.Add(absPath)
   130  	}
   131  
   132  	if err != nil {
   133  		return "", err
   134  	}
   135  
   136  	Index(context.ContractSymbol, contractName)
   137  	Index(context.AccountSymbol, contractName)
   138  
   139  	return "deploy a smart contract successfully", nil
   140  }