Skip to content

Commit

Permalink
Add flow deps discover command (#1761)
Browse files Browse the repository at this point in the history
  • Loading branch information
jribbink authored Sep 23, 2024
1 parent 8da218b commit f99a061
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 55 deletions.
1 change: 1 addition & 0 deletions internal/dependencymanager/dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,5 @@ var Cmd = &cobra.Command{
func init() {
addCommand.AddToParent(Cmd)
installCommand.AddToParent(Cmd)
discoverCommand.AddToParent(Cmd)
}
131 changes: 131 additions & 0 deletions internal/dependencymanager/discover.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* Flow CLI
*
* Copyright Flow Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package dependencymanager

import (
"fmt"
"slices"

flowsdk "github.com/onflow/flow-go-sdk"
"github.com/onflow/flow-go/fvm/systemcontracts"

"github.com/spf13/cobra"

"github.com/onflow/flowkit/v2"
"github.com/onflow/flowkit/v2/output"

flowGo "github.com/onflow/flow-go/model/flow"
flowkitConfig "github.com/onflow/flowkit/v2/config"

"github.com/onflow/flow-cli/internal/command"
"github.com/onflow/flow-cli/internal/prompt"
"github.com/onflow/flow-cli/internal/util"
)

type DiscoverResult struct {
Contracts []string `json:"contracts"`
}

var discoverCommand = &command.Command{
Cmd: &cobra.Command{
Use: "discover",
Short: "Discover available contracts to add to your project.",
Example: "flow dependencies discover",
Args: cobra.NoArgs,
},
RunS: discover,
Flags: &struct{}{},
}

func discover(
_ []string,
globalFlags command.GlobalFlags,
logger output.Logger,
flow flowkit.Services,
state *flowkit.State,
) (command.Result, error) {
installedDeps := state.Dependencies()
if installedDeps == nil {
installedDeps = new(flowkitConfig.Dependencies)
}

installedContracts := make([]string, 0)
for _, dep := range *installedDeps {
installedContracts = append(installedContracts, dep.Name)
}

err := PromptInstallCoreContracts(logger, state, "", installedContracts)
if err != nil {
return nil, err
}

err = state.SaveDefault()
return nil, err
}

func PromptInstallCoreContracts(logger output.Logger, state *flowkit.State, targetDir string, excludeContracts []string) error {
// Prompt to ask which core contracts should be installed
sc := systemcontracts.SystemContractsForChain(flowGo.Mainnet)
promptMessage := "Select any core contracts you would like to install or skip to continue."

contractNames := make([]string, 0)

for _, contract := range sc.All() {
if slices.Contains(excludeContracts, contract.Name) {
continue
}
contractNames = append(contractNames, contract.Name)
}

selectedContractNames, err := prompt.RunSelectOptions(contractNames, promptMessage)
if err != nil {
return fmt.Errorf("error running dependency selection: %v\n", err)
}

var dependencies []flowkitConfig.Dependency

// Loop standard contracts and add them to the dependencies if selected
for _, contract := range sc.All() {
if slices.Contains(selectedContractNames, contract.Name) {
dependencies = append(dependencies, flowkitConfig.Dependency{
Name: contract.Name,
Source: flowkitConfig.Source{
NetworkName: flowkitConfig.MainnetNetwork.Name,
Address: flowsdk.HexToAddress(contract.Address.String()),
ContractName: contract.Name,
},
})
}
}

logger.Info("")
logger.Info(util.MessageWithEmojiPrefix("🔄", "Installing selected core contracts and dependencies..."))

// Add the selected core contracts as dependencies
installer, err := NewDependencyInstaller(logger, state, false, targetDir, Flags{})
if err != nil {
return err
}

if err := installer.AddMany(dependencies); err != nil {
return err
}

return nil
}
56 changes: 1 addition & 55 deletions internal/super/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@ import (
"os"
"path/filepath"

flowsdk "github.com/onflow/flow-go-sdk"
"github.com/onflow/flow-go/fvm/systemcontracts"
flowGo "github.com/onflow/flow-go/model/flow"
flowkitConfig "github.com/onflow/flowkit/v2/config"
"golang.org/x/exp/slices"

"github.com/onflow/flow-cli/internal/dependencymanager"
"github.com/onflow/flow-cli/internal/util"

Expand Down Expand Up @@ -245,7 +239,7 @@ func startInteractiveSetup(

msg := "Would you like to install any core contracts and their dependencies?"
if prompt.GenericBoolPrompt(msg) {
err := installCoreContracts(logger, state, tempDir)
err := dependencymanager.PromptInstallCoreContracts(logger, state, tempDir, nil)
if err != nil {
return "", err
}
Expand All @@ -270,54 +264,6 @@ func startInteractiveSetup(
return targetDir, nil
}

func installCoreContracts(logger output.Logger, state *flowkit.State, tempDir string) error {
// Prompt to ask which core contracts should be installed
sc := systemcontracts.SystemContractsForChain(flowGo.Mainnet)
promptMessage := "Select any core contracts you would like to install or skip to continue."

contractNames := make([]string, 0)

for _, contract := range sc.All() {
contractNames = append(contractNames, contract.Name)
}

selectedContractNames, err := prompt.RunSelectOptions(contractNames, promptMessage)
if err != nil {
return fmt.Errorf("error running dependency selection: %v\n", err)
}

var dependencies []flowkitConfig.Dependency

// Loop standard contracts and add them to the dependencies if selected
for _, contract := range sc.All() {
if slices.Contains(selectedContractNames, contract.Name) {
dependencies = append(dependencies, flowkitConfig.Dependency{
Name: contract.Name,
Source: flowkitConfig.Source{
NetworkName: flowkitConfig.MainnetNetwork.Name,
Address: flowsdk.HexToAddress(contract.Address.String()),
ContractName: contract.Name,
},
})
}
}

logger.Info("")
logger.Info(util.MessageWithEmojiPrefix("🔄", "Installing selected core contracts and dependencies..."))

// Add the selected core contracts as dependencies
installer, err := dependencymanager.NewDependencyInstaller(logger, state, false, tempDir, dependencymanager.Flags{})
if err != nil {
return err
}

if err := installer.AddMany(dependencies); err != nil {
return err
}

return nil
}

// getTargetDirectory checks if the specified directory path is suitable for use.
// It verifies that the path points to an existing, empty directory.
// If the directory does not exist, the function returns the path without error,
Expand Down

0 comments on commit f99a061

Please sign in to comment.