diff --git a/internal/dependencymanager/add.go b/internal/dependencymanager/add.go index b08810a06..d589d89dd 100644 --- a/internal/dependencymanager/add.go +++ b/internal/dependencymanager/add.go @@ -42,10 +42,11 @@ var addFlags = addFlagsCollection{ var addCommand = &command.Command{ Cmd: &cobra.Command{ - Use: "add ", - Short: "Add a single contract and its dependencies.", - Example: "flow dependencies add testnet://0afe396ebc8eee65.FlowToken", - Args: cobra.ExactArgs(1), + Use: "add ", + Short: "Add a single contract and its dependencies.", + Example: `flow dependencies add testnet://0afe396ebc8eee65.FlowToken +flow dependencies add FlowToken`, + Args: cobra.ExactArgs(1), }, RunS: add, Flags: &struct{}{}, @@ -75,6 +76,16 @@ func add( return nil, err } + // First check if the dependency is a core contract. + if isCoreContract(dep) { + if err := installer.AddByCoreContractName(dep, addFlags.name); err != nil { + logger.Error(fmt.Sprintf("Error: %v", err)) + return nil, err + } + return nil, nil + } + + // Otherwise, add the dependency by source string. if err := installer.AddBySourceString(dep, addFlags.name); err != nil { logger.Error(fmt.Sprintf("Error: %v", err)) return nil, err diff --git a/internal/dependencymanager/dependencyinstaller.go b/internal/dependencymanager/dependencyinstaller.go index d6c3b63ac..f902b1d87 100644 --- a/internal/dependencymanager/dependencyinstaller.go +++ b/internal/dependencymanager/dependencyinstaller.go @@ -203,19 +203,40 @@ func (di *DependencyInstaller) AddBySourceString(depSource, customName string) e }, } - if err := di.processDependency(dep); err != nil { - return fmt.Errorf("error processing dependency: %w", err) + return di.Add(dep) +} + +func (di *DependencyInstaller) AddByCoreContractName(coreContractName, customName string) error { + var depNetwork, depAddress, depContractName string + sc := systemcontracts.SystemContractsForChain(flowGo.Mainnet) + for _, coreContract := range sc.All() { + if coreContract.Name == coreContractName { + depAddress = coreContract.Address.String() + depNetwork = config.MainnetNetwork.Name + depContractName = coreContractName + break + } } - di.checkForConflictingContracts() + if depAddress == "" { + return fmt.Errorf("contract %s not found in core contracts", coreContractName) + } - if err := di.saveState(); err != nil { - return err + name := depContractName + if customName != "" { + name = customName } - di.logs.LogAll(di.Logger) + dep := config.Dependency{ + Name: name, + Source: config.Source{ + NetworkName: depNetwork, + Address: flowsdk.HexToAddress(depAddress), + ContractName: depContractName, + }, + } - return nil + return di.Add(dep) } // Add processes a single dependency and installs it and any dependencies it has, as well as adding it to the state @@ -224,6 +245,8 @@ func (di *DependencyInstaller) Add(dep config.Dependency) error { return fmt.Errorf("error processing dependency: %w", err) } + di.checkForConflictingContracts() + if err := di.saveState(); err != nil { return err } diff --git a/internal/dependencymanager/dependencyinstaller_test.go b/internal/dependencymanager/dependencyinstaller_test.go index 6850f2d7d..2957d3ef7 100644 --- a/internal/dependencymanager/dependencyinstaller_test.go +++ b/internal/dependencymanager/dependencyinstaller_test.go @@ -185,6 +185,45 @@ func TestDependencyInstallerAdd(t *testing.T) { assert.NoError(t, err, "Failed to read generated file") assert.NotNil(t, fileContent) }) + + t.Run("Add by core contract name", func(t *testing.T) { + gw := mocks.DefaultMockGateway() + + gw.GetAccount.Run(func(args mock.Arguments) { + addr := args.Get(1).(flow.Address) + assert.Equal(t, addr.String(), "1654653399040a61") + acc := tests.NewAccountWithAddress(addr.String()) + acc.Contracts = map[string][]byte{ + "FlowToken": []byte("access(all) contract FlowToken {}"), + } + + gw.GetAccount.Return(acc, nil) + }) + + di := &DependencyInstaller{ + Gateways: map[string]gateway.Gateway{ + config.EmulatorNetwork.Name: gw.Mock, + config.TestnetNetwork.Name: gw.Mock, + config.MainnetNetwork.Name: gw.Mock, + }, + Logger: logger, + State: state, + SaveState: true, + TargetDir: "", + SkipDeployments: true, + SkipAlias: true, + dependencies: make(map[string]config.Dependency), + } + + err := di.AddByCoreContractName("FlowToken", "") + assert.NoError(t, err, "Failed to install dependencies") + + filePath := fmt.Sprintf("imports/%s/%s.cdc", "1654653399040a61", "FlowToken") + fileContent, err := state.ReaderWriter().ReadFile(filePath) + assert.NoError(t, err, "Failed to read generated file") + assert.NotNil(t, fileContent) + assert.Contains(t, string(fileContent), "contract FlowToken") + }) } func TestDependencyInstallerAddMany(t *testing.T) {