Skip to content

Commit 3b83c2c

Browse files
authored
Merge pull request #1491 from onflow/jribbink/merge-sc
Merge `master` into `feature/stable-cadence`
2 parents e2ade3f + 212c9ae commit 3b83c2c

File tree

8 files changed

+136
-74
lines changed

8 files changed

+136
-74
lines changed

cmd/flow/main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,11 @@ func main() {
160160

161161
cmd.SetUsageTemplate(command.UsageTemplate)
162162

163+
// Don't print usage on error
164+
cmd.SilenceUsage = true
165+
// Don't print errors on error (we handle them)
166+
cmd.SilenceErrors = true
167+
163168
if err := cmd.Execute(); err != nil {
164169
util.Exit(1, err.Error())
165170
}

internal/dependencymanager/add.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ import (
3030
)
3131

3232
type addFlagsCollection struct {
33-
name string `default:"" flag:"name" info:"Name of the dependency"`
34-
skipDeployments bool `default:"false" flag:"skip-deployments" info:"Skip adding the dependency to deployments"`
33+
dependencyManagerFlagsCollection
34+
name string `default:"" flag:"name" info:"Name of the dependency"`
3535
}
3636

3737
var addFlags = addFlagsCollection{}
@@ -58,7 +58,7 @@ func add(
5858

5959
dep := args[0]
6060

61-
installer, err := NewDependencyInstaller(logger, state, addFlags.skipDeployments)
61+
installer, err := NewDependencyInstaller(logger, state, addFlags.dependencyManagerFlagsCollection)
6262
if err != nil {
6363
logger.Error(fmt.Sprintf("Error: %v", err))
6464
return nil, err
@@ -69,9 +69,5 @@ func add(
6969
return nil, err
7070
}
7171

72-
logger.Info("✅ Dependency installation complete. Check your flow.json")
73-
logger.Info("Ensure you add any required dependencies to your 'deployments' section. This can be done using the 'flow config add deployment' command.")
74-
logger.Info("Note: Core contracts do not need to be added to deployments. For reference, see this URL: https://github.com/onflow/flow-core-contracts")
75-
7672
return nil, nil
7773
}

internal/dependencymanager/dependencyinstaller.go

Lines changed: 86 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,48 @@ import (
4343
"github.com/onflow/flowkit/v2/output"
4444
)
4545

46+
type categorizedLogs struct {
47+
fileSystemActions []string
48+
stateUpdates []string
49+
}
50+
51+
func (cl *categorizedLogs) LogAll(logger output.Logger) {
52+
logger.Info("📝 Dependency Manager Actions Summary")
53+
logger.Info("") // Add a line break after the section
54+
55+
if len(cl.fileSystemActions) > 0 {
56+
logger.Info("🗃️ File System Actions:")
57+
for _, msg := range cl.fileSystemActions {
58+
logger.Info(fmt.Sprintf("✅ %s", msg))
59+
}
60+
logger.Info("") // Add a line break after the section
61+
}
62+
63+
if len(cl.stateUpdates) > 0 {
64+
logger.Info("💾 State Updates:")
65+
for _, msg := range cl.stateUpdates {
66+
logger.Info(fmt.Sprintf("✅ %s", msg))
67+
}
68+
logger.Info("") // Add a line break after the section
69+
}
70+
}
71+
72+
type dependencyManagerFlagsCollection struct {
73+
skipDeployments bool `default:"false" flag:"skip-deployments" info:"Skip adding the dependency to deployments"`
74+
skipAlias bool `default:"false" flag:"skip-alias" info:"Skip prompting for an alias"`
75+
}
76+
4677
type DependencyInstaller struct {
4778
Gateways map[string]gateway.Gateway
4879
Logger output.Logger
4980
State *flowkit.State
5081
SkipDeployments bool
82+
SkipAlias bool
83+
logs categorizedLogs
5184
}
5285

5386
// NewDependencyInstaller creates a new instance of DependencyInstaller
54-
func NewDependencyInstaller(logger output.Logger, state *flowkit.State, skipDeployments bool) (*DependencyInstaller, error) {
87+
func NewDependencyInstaller(logger output.Logger, state *flowkit.State, flags dependencyManagerFlagsCollection) (*DependencyInstaller, error) {
5588
emulatorGateway, err := gateway.NewGrpcGateway(config.EmulatorNetwork)
5689
if err != nil {
5790
return nil, fmt.Errorf("error creating emulator gateway: %v", err)
@@ -83,7 +116,8 @@ func NewDependencyInstaller(logger output.Logger, state *flowkit.State, skipDepl
83116
Gateways: gateways,
84117
Logger: logger,
85118
State: state,
86-
SkipDeployments: skipDeployments,
119+
SkipDeployments: flags.skipDeployments,
120+
SkipAlias: flags.skipAlias,
87121
}, nil
88122
}
89123

@@ -95,6 +129,14 @@ func (di *DependencyInstaller) Install() error {
95129
return err
96130
}
97131
}
132+
133+
err := di.State.SaveDefault()
134+
if err != nil {
135+
return fmt.Errorf("error saving state: %w", err)
136+
}
137+
138+
di.logs.LogAll(di.Logger)
139+
98140
return nil
99141
}
100142

@@ -124,6 +166,13 @@ func (di *DependencyInstaller) Add(depSource, customName string) error {
124166
return fmt.Errorf("error processing dependency: %w", err)
125167
}
126168

169+
err = di.State.SaveDefault()
170+
if err != nil {
171+
return fmt.Errorf("error saving state: %w", err)
172+
}
173+
174+
di.logs.LogAll(di.Logger)
175+
127176
return nil
128177
}
129178

@@ -218,7 +267,7 @@ func (di *DependencyInstaller) handleFileSystem(contractAddr, contractName, cont
218267
return fmt.Errorf("failed to create contract file: %w", err)
219268
}
220269

221-
di.Logger.Info(fmt.Sprintf("Dependency Manager: %s from %s on %s installed", contractName, contractAddr, networkName))
270+
di.logs.fileSystemActions = append(di.logs.fileSystemActions, fmt.Sprintf("%s from %s on %s installed", contractName, contractAddr, networkName))
222271
}
223272

224273
return nil
@@ -273,12 +322,26 @@ func (di *DependencyInstaller) handleFoundContract(networkName, contractAddr, as
273322
return err
274323
}
275324

325+
// If the contract is not a core contract and the user does not want to skip deployments, then prompt for a deployment
276326
if !di.SkipDeployments && !isCoreContract(contractName) {
277327
err = di.updateDependencyDeployment(contractName)
278328
if err != nil {
279329
di.Logger.Error(fmt.Sprintf("Error updating deployment: %v", err))
280330
return err
281331
}
332+
333+
di.logs.stateUpdates = append(di.logs.stateUpdates, fmt.Sprintf("%s added to emulator deployments", contractName))
334+
}
335+
336+
// If the contract is not a core contract and the user does not want to skip aliasing, then prompt for an alias
337+
if !di.SkipAlias && !isCoreContract(contractName) {
338+
err = di.updateDependencyAlias(contractName, networkName)
339+
if err != nil {
340+
di.Logger.Error(fmt.Sprintf("Error updating alias: %v", err))
341+
return err
342+
}
343+
344+
di.logs.stateUpdates = append(di.logs.stateUpdates, fmt.Sprintf("Alias added for %s on %s", contractName, networkName))
282345
}
283346

284347
return nil
@@ -302,13 +365,30 @@ func (di *DependencyInstaller) updateDependencyDeployment(contractName string) e
302365
for _, c := range raw.Contracts {
303366
deployment.AddContract(config.ContractDeployment{Name: c})
304367
}
368+
}
369+
370+
return nil
371+
}
372+
373+
func (di *DependencyInstaller) updateDependencyAlias(contractName, aliasNetwork string) error {
374+
var missingNetwork string
375+
376+
if aliasNetwork == config.TestnetNetwork.Name {
377+
missingNetwork = config.MainnetNetwork.Name
378+
} else {
379+
missingNetwork = config.TestnetNetwork.Name
380+
}
305381

306-
err := di.State.SaveDefault()
382+
label := fmt.Sprintf("Enter an alias address for %s on %s if you have one, otherwise leave blank", contractName, missingNetwork)
383+
raw := util.AddressPromptOrEmpty(label, "Invalid alias address")
384+
385+
if raw != "" {
386+
contract, err := di.State.Contracts().ByName(contractName)
307387
if err != nil {
308388
return err
309389
}
310390

311-
di.Logger.Info(fmt.Sprintf("Dependency Manager: %s added to emulator deployments in flow.json", contractName))
391+
contract.Aliases.Add(missingNetwork, flowsdk.HexToAddress(raw))
312392
}
313393

314394
return nil
@@ -329,13 +409,9 @@ func (di *DependencyInstaller) updateDependencyState(networkName, contractAddres
329409

330410
di.State.Dependencies().AddOrUpdate(dep)
331411
di.State.Contracts().AddDependencyAsContract(dep, networkName)
332-
err := di.State.SaveDefault()
333-
if err != nil {
334-
return err
335-
}
336412

337413
if isNewDep {
338-
di.Logger.Info(fmt.Sprintf("Dependency Manager: %s added to flow.json", dep.Name))
414+
di.logs.stateUpdates = append(di.logs.stateUpdates, fmt.Sprintf("%s added to flow.json", dep.Name))
339415
}
340416

341417
return nil

internal/dependencymanager/dependencyinstaller_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ func TestDependencyInstallerInstall(t *testing.T) {
7878
Logger: logger,
7979
State: state,
8080
SkipDeployments: true,
81+
SkipAlias: true,
8182
}
8283

8384
err := di.Install()
@@ -122,6 +123,7 @@ func TestDependencyInstallerAdd(t *testing.T) {
122123
Logger: logger,
123124
State: state,
124125
SkipDeployments: true,
126+
SkipAlias: true,
125127
}
126128

127129
sourceStr := fmt.Sprintf("emulator://%s.%s", serviceAddress.String(), tests.ContractHelloString.Name)

internal/dependencymanager/install.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,7 @@ import (
2929
"github.com/onflow/flow-cli/internal/command"
3030
)
3131

32-
type installFlagsCollection struct {
33-
skipDeployments bool `default:"false" flag:"skip-deployments" info:"Skip adding the dependency to deployments"`
34-
}
35-
36-
var installFlags = installFlagsCollection{}
32+
var installFlags = dependencyManagerFlagsCollection{}
3733

3834
var installCommand = &command.Command{
3935
Cmd: &cobra.Command{
@@ -54,7 +50,7 @@ func install(
5450
) (result command.Result, err error) {
5551
logger.Info("🔄 Installing dependencies from flow.json...")
5652

57-
installer, err := NewDependencyInstaller(logger, state, installFlags.skipDeployments)
53+
installer, err := NewDependencyInstaller(logger, state, installFlags)
5854
if err != nil {
5955
logger.Error(fmt.Sprintf("Error: %v", err))
6056
return nil, err
@@ -65,7 +61,5 @@ func install(
6561
return nil, err
6662
}
6763

68-
logger.Info("✅ Dependency installation complete. Check your flow.json")
69-
7064
return nil, nil
7165
}

internal/util/prompt.go

Lines changed: 29 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,34 @@ func secureNetworkKeyPrompt() string {
204204
return networkKey
205205
}
206206

207-
func addressPrompt() string {
207+
func addressPrompt(label, errorMessage string) string {
208208
addressPrompt := promptui.Prompt{
209-
Label: "Enter address",
209+
Label: label,
210210
Validate: func(s string) error {
211211
if flow.HexToAddress(s) == flow.EmptyAddress {
212-
return fmt.Errorf("invalid address")
212+
return fmt.Errorf(errorMessage)
213+
}
214+
return nil
215+
},
216+
}
217+
218+
address, err := addressPrompt.Run()
219+
if err == promptui.ErrInterrupt {
220+
os.Exit(-1)
221+
}
222+
223+
return address
224+
}
225+
226+
func AddressPromptOrEmpty(label, errorMessage string) string {
227+
addressPrompt := promptui.Prompt{
228+
Label: label,
229+
Validate: func(s string) error {
230+
if s == "" {
231+
return nil
232+
}
233+
if flow.HexToAddress(s) == flow.EmptyAddress {
234+
return fmt.Errorf(errorMessage)
213235
}
214236
return nil
215237
},
@@ -286,7 +308,7 @@ func NewAccountPrompt() *AccountData {
286308
var err error
287309
account := &AccountData{
288310
Name: NamePrompt(),
289-
Address: addressPrompt(),
311+
Address: addressPrompt("Enter address", "invalid address"),
290312
}
291313

292314
sigAlgoPrompt := promptui.Select{
@@ -372,41 +394,9 @@ func NewContractPrompt() *ContractData {
372394
os.Exit(-1)
373395
}
374396

375-
emulatorAliasPrompt := promptui.Prompt{
376-
Label: "Enter emulator alias, if exists",
377-
Validate: func(s string) error {
378-
if s != "" && flow.HexToAddress(s) == flow.EmptyAddress {
379-
return fmt.Errorf("invalid alias address")
380-
}
381-
382-
return nil
383-
},
384-
}
385-
contract.Emulator, _ = emulatorAliasPrompt.Run()
386-
387-
testnetAliasPrompt := promptui.Prompt{
388-
Label: "Enter testnet alias, if exists",
389-
Validate: func(s string) error {
390-
if s != "" && flow.HexToAddress(s) == flow.EmptyAddress {
391-
return fmt.Errorf("invalid testnet address")
392-
}
393-
394-
return nil
395-
},
396-
}
397-
contract.Testnet, _ = testnetAliasPrompt.Run()
398-
399-
mainnetAliasPrompt := promptui.Prompt{
400-
Label: "Enter mainnet alias, if exists",
401-
Validate: func(s string) error {
402-
if s != "" && flow.HexToAddress(s) == flow.EmptyAddress {
403-
return fmt.Errorf("invalid mainnet address")
404-
}
405-
406-
return nil
407-
},
408-
}
409-
contract.Mainnet, _ = mainnetAliasPrompt.Run()
397+
contract.Emulator = addressPrompt("Enter emulator alias, if exists", "invalid alias address")
398+
contract.Testnet = addressPrompt("Enter testnet alias, if exists", "invalid testnet address")
399+
contract.Mainnet = addressPrompt("Enter mainnet alias, if exists", "invalid mainnet address")
410400

411401
return contract
412402
}

0 commit comments

Comments
 (0)