Skip to content

Commit

Permalink
brownie support mvp
Browse files Browse the repository at this point in the history
  • Loading branch information
Malcador committed May 20, 2021
1 parent e1ad496 commit 6d64c74
Show file tree
Hide file tree
Showing 11 changed files with 341 additions and 46 deletions.
18 changes: 18 additions & 0 deletions brownie/brownie.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package brownie

import (
"github.com/tenderly/tenderly-cli/providers"
)

type DeploymentProvider struct {
}

func NewDeploymentProvider() *DeploymentProvider {
return &DeploymentProvider{}
}

var _ providers.DeploymentProvider = (*DeploymentProvider)(nil)

func (*DeploymentProvider) GetProviderName() providers.DeploymentProviderName {
return providers.BrownieDeploymentProvider
}
77 changes: 77 additions & 0 deletions brownie/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package brownie

import (
"fmt"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/tenderly/tenderly-cli/config"
"github.com/tenderly/tenderly-cli/providers"
"github.com/tenderly/tenderly-cli/userError"
"gopkg.in/yaml.v3"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strings"
)

type BrownieCompilerSettings struct {
Compiler providers.Compiler `json:"compiler,omitempty" yaml:"compiler,omitempty"`
}

func (dp *DeploymentProvider) GetConfig(configName string, projectDir string) (*providers.Config, error) {
browniePath := filepath.Join(projectDir, configName)

logrus.Debugf("Trying Brownie config path: %s", browniePath)
_, err := os.Stat(browniePath)
if os.IsNotExist(err) {
return nil, err
}
if err != nil {
return nil, fmt.Errorf("cannot find %s, tried path: %s, error: %s", configName, browniePath, err)
}

if runtime.GOOS == "windows" {
browniePath = strings.ReplaceAll(browniePath, `\`, `\\`)
}

data, err := ioutil.ReadFile(browniePath)
if err != nil {
return nil, errors.Wrap(err, "read brownie config")
}

var brownieConfig providers.Config
err = yaml.Unmarshal(data, &brownieConfig)
if err != nil {
return nil, errors.Wrap(err, "parse brownie config")
}

return &providers.Config{
ProjectDirectory: projectDir,
BuildDirectory: configName,
ConfigType: configName,
Compilers: brownieConfig.Compilers,
}, nil
}

func (dp *DeploymentProvider) MustGetConfig() (*providers.Config, error) {
projectDir, err := filepath.Abs(config.ProjectDirectory)
brownieConfigFile := providers.BrownieConfigFile

if err != nil {
return nil, userError.NewUserError(
fmt.Errorf("get absolute project dir: %s", err),
"Couldn't get absolute project path",
)
}

brownieConfig, err := dp.GetConfig(brownieConfigFile, projectDir)
if err != nil {
return nil, userError.NewUserError(
fmt.Errorf("unable to fetch config: %s", err),
"Couldn't read Brownie config file",
)
}

return brownieConfig, nil
}
164 changes: 164 additions & 0 deletions brownie/contract.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package brownie

import (
"encoding/json"
"fmt"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/tenderly/tenderly-cli/model"
"github.com/tenderly/tenderly-cli/providers"
"io/ioutil"
"os"
"path/filepath"
"strings"
)

const (
BrownieContractDirectoryPath = "contracts"
BrownieContractDeploymentPath = "deployments"
BrownieContractMapFile = "map.json"

BrownieDependencySeparator = "packages"
)

func (dp *DeploymentProvider) GetContracts(
buildDir string,
networkIDs []string,
objects ...*model.StateObject,
) ([]providers.Contract, int, error) {
contractsPath := filepath.Join(buildDir, BrownieContractDirectoryPath)
files, err := ioutil.ReadDir(contractsPath)
if err != nil {
return nil, 0, errors.Wrap(err, "failed listing build files")
}

networkIDFilterMap := make(map[string]bool)
for _, networkID := range networkIDs {
networkIDFilterMap[networkID] = true
}
objectMap := make(map[string]*model.StateObject)
for _, object := range objects {
if object.Code == nil || len(object.Code) == 0 {
continue
}
objectMap[hexutil.Encode(object.Code)] = object
}

contractMap := make(map[string]*providers.Contract)
var numberOfContractsWithANetwork int
for _, contractFile := range files {
if contractFile.IsDir() {
dependencyPath := filepath.Join(contractsPath, contractFile.Name())
err = dp.resolveDependencies(dependencyPath, contractMap)
if err != nil {
logrus.Debug(fmt.Sprintf("Failed resolving dependencies at %s with error: %s", dependencyPath, err))
break
}
continue
}
if !strings.HasSuffix(contractFile.Name(), ".json") {
continue
}
contractFilePath := filepath.Join(contractsPath, contractFile.Name())
data, err := ioutil.ReadFile(contractFilePath)
if err != nil {
logrus.Debug(fmt.Sprintf("Failed reading build file at %s with error: %s", contractFilePath, err))
break
}

var contractData providers.Contract
err = json.Unmarshal(data, &contractData)
if err != nil {
logrus.Debug(fmt.Sprintf("Failed parsing build file at %s with error: %s", contractFilePath, err))
break
}

contractMap[contractData.Name] = &contractData
}

deploymentMapFile := filepath.Join(buildDir, BrownieContractDeploymentPath, BrownieContractMapFile)

data, err := ioutil.ReadFile(deploymentMapFile)
if err != nil {
logrus.Debug(fmt.Sprintf("Failed reading map file at %s with error: %s", deploymentMapFile, err))
return nil, 0, errors.Wrap(err, "failed reading map file")
}

var deploymentMap map[string]map[string][]string
err = json.Unmarshal(data, &deploymentMap)
if err != nil {
logrus.Debug(fmt.Sprintf("Failed parsing map file at %s with error: %s", deploymentMapFile, err))
return nil, 0, errors.Wrap(err, "failed unmarshaling map file")
}
for networkID, contractDeployments := range deploymentMap {
for contractName, deploymentAddresses := range contractDeployments {
if _, ok := contractMap[contractName]; !ok {
continue
}

if len(networkIDFilterMap) > 0 && !networkIDFilterMap[networkID] {
continue
}

if contractMap[contractName].Networks == nil {
contractMap[contractName].Networks = make(map[string]providers.ContractNetwork)
}
//We only take the latest deployment to some network
contractMap[contractName].Networks[networkID] = providers.ContractNetwork{
Address: deploymentAddresses[0],
}
numberOfContractsWithANetwork += 1
}
}

var contracts []providers.Contract
for _, contract := range contractMap {
contracts = append(contracts, *contract)
}

return contracts, numberOfContractsWithANetwork, nil
}

func (dp *DeploymentProvider) resolveDependencies(path string, contractMap map[string]*providers.Contract) error {
info, err := os.Stat(path)
if err != nil {
logrus.Debugf("Failed reading dependency at %s", path)
return errors.Wrap(err, "failed reading dependency files")
}
if info.IsDir() {
files, err := ioutil.ReadDir(path)
if err != nil {
logrus.Debugf("Failed reading dependency at %s", path)
return errors.Wrap(err, "failed reading dependency files")
}

for _, file := range files {
newFilePath := filepath.Join(path, file.Name())
err = dp.resolveDependencies(newFilePath, contractMap)
if err != nil {
return err
}
}
return nil
}

data, err := ioutil.ReadFile(path)
if err != nil {
logrus.Debug(fmt.Sprintf("Failed reading build file at %s with error: %s", path, err))
return errors.Wrap(err, "failed reading contract")
}

var contractData providers.Contract
err = json.Unmarshal(data, &contractData)
if err != nil {
logrus.Debug(fmt.Sprintf("Failed parsing build file at %s with error: %s", path, err))
return errors.Wrap(err, "failed parsing contract")
}

sourcePath := strings.Split(contractData.SourcePath, BrownieDependencySeparator)
contractData.SourcePath = strings.TrimPrefix(sourcePath[1], string(os.PathSeparator))
contractMap[contractData.Name] = &contractData

return nil
}
25 changes: 25 additions & 0 deletions brownie/detect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package brownie

import (
"os"
"path"
)

var brownieFolders = []string{
"build",
}

func FindDirectories() []string {
return []string{}
}

func (dp *DeploymentProvider) CheckIfProviderStructure(directory string) bool {
for _, folder := range brownieFolders {
folderPath := path.Join(directory, folder)
if _, err := os.Stat(folderPath); err != nil {
return false
}
}

return true
}
2 changes: 1 addition & 1 deletion commands/commonMessages.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func CheckLogin() {

func CheckProvider(deploymentProvider providers.DeploymentProvider) {
if deploymentProvider == nil {
logrus.Error("Hardhat, Buidler, OpenZeppelin or Truffle configuration was not detected.\n\n",
logrus.Error("Brownie, Hardhat, Buidler, OpenZeppelin or Truffle configuration was not detected.\n\n",
"Please re-run this command in a folder where at least one of the frameworks is configured.")
os.Exit(1)
}
Expand Down
27 changes: 24 additions & 3 deletions commands/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"github.com/sirupsen/logrus"
"github.com/tenderly/tenderly-cli/brownie"
"github.com/tenderly/tenderly-cli/buidler"
"github.com/tenderly/tenderly-cli/config"
"github.com/tenderly/tenderly-cli/hardhat"
Expand Down Expand Up @@ -234,6 +235,7 @@ func initProvider() {
buidlerPath := filepath.Join(config.ProjectDirectory, providers.BuidlerConfigFile)
hardhatPath := filepath.Join(config.ProjectDirectory, providers.HardhatConfigFile)
hardhatPathTs := filepath.Join(config.ProjectDirectory, providers.HardhatConfigFileTs)
browniePath := filepath.Join(config.ProjectDirectory, providers.BrownieConfigFile)

var provider providers.DeploymentProviderName

Expand Down Expand Up @@ -351,6 +353,21 @@ func initProvider() {
)
}

logrus.Debugf("Trying brownie config path: %s", browniePath)

if provider == providers.BrownieDeploymentProvider || provider == "" {
_, err := os.Stat(browniePath)
if err == nil {
deploymentProvider = brownie.NewDeploymentProvider()
return
}

logrus.Debugf(
fmt.Sprintf("unable to fetch config\n%s",
" Couldn't read Brownie config file"),
)
}

logrus.Debugf("Trying truffle config path: %s", trufflePath)

_, err := os.Stat(trufflePath)
Expand Down Expand Up @@ -398,15 +415,19 @@ func GetConfigPayload(providerConfig *providers.Config) *payloads.Config {
}
}
if providerConfig.ConfigType == providers.OpenzeppelinConfigFile && providerConfig.Compilers != nil {
return payloads.ParseOpenZeppelinConfig(providerConfig.Compilers)
return payloads.ParseSolcConfigWithSettings(providerConfig.Compilers)
}

if providerConfig.ConfigType == providers.BuidlerConfigFile && providerConfig.Compilers != nil {
return payloads.ParseBuidlerConfig(providerConfig.Compilers)
return payloads.ParseSolcConfigWithOptimizer(providerConfig.Compilers)
}

if (providerConfig.ConfigType == providers.HardhatConfigFile || providerConfig.ConfigType == providers.HardhatConfigFileTs) && providerConfig.Compilers != nil {
return payloads.ParseHardhatConfig(providerConfig.Compilers)
return payloads.ParseSolcConfigWithSettings(providerConfig.Compilers)
}

if providerConfig.ConfigType == providers.BrownieConfigFile && providerConfig.Compilers != nil {
return payloads.ParseSolcConfigWithOptimizer(providerConfig.Compilers)
}

return nil
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ require (
github.com/spf13/cobra v1.1.3
github.com/spf13/viper v1.7.0
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
)
Loading

0 comments on commit 6d64c74

Please sign in to comment.