diff --git a/internal/accounts/accounts.go b/internal/accounts/accounts.go index ed4bb1ca5..3f3d8c68d 100644 --- a/internal/accounts/accounts.go +++ b/internal/accounts/accounts.go @@ -22,6 +22,8 @@ import ( "bytes" "fmt" + "github.com/onflow/flow-cli/internal/command" + "github.com/onflow/cadence" "github.com/onflow/flow-go-sdk" "github.com/spf13/cobra" @@ -48,6 +50,7 @@ func init() { type AccountResult struct { *flow.Account showCode bool + include []string } // JSON convert result to JSON @@ -97,24 +100,32 @@ func (r *AccountResult) String() string { _, _ = fmt.Fprintf(writer, "\tSignature Algorithm\t %s\n", key.SigAlgo) _, _ = fmt.Fprintf(writer, "\tHash Algorithm\t %s\n", key.HashAlgo) _, _ = fmt.Fprintf(writer, "\tRevoked \t %t\n", key.Revoked) - fmt.Fprintf(writer, "\tSequence Number \t %d\n", key.SequenceNumber) - fmt.Fprintf(writer, "\tIndex \t %d\n", key.Index) - fmt.Fprintf(writer, "\n") + _, _ = fmt.Fprintf(writer, "\tSequence Number \t %d\n", key.SequenceNumber) + _, _ = fmt.Fprintf(writer, "\tIndex \t %d\n", key.Index) + _, _ = fmt.Fprintf(writer, "\n") + + // only show up to 3 keys and then show label to expand more info + if i == 3 && !command.ContainsFlag(r.include, "keys") { + _, _ = fmt.Fprint(writer, "...keys minimized, use --include keys flag if you want to view all\n\n") + break + } } - fmt.Fprintf(writer, "Contracts Deployed: %d\n", len(r.Contracts)) + _, _ = fmt.Fprintf(writer, "Contracts Deployed: %d\n", len(r.Contracts)) for name := range r.Contracts { - fmt.Fprintf(writer, "Contract: '%s'\n", name) + _, _ = fmt.Fprintf(writer, "Contract: '%s'\n", name) } - if r.showCode { + if r.showCode || command.ContainsFlag(r.include, "contracts") { for name, code := range r.Contracts { - fmt.Fprintf(writer, "Contracts '%s':\n", name) - fmt.Fprintln(writer, string(code)) + _, _ = fmt.Fprintf(writer, "Contracts '%s':\n", name) + _, _ = fmt.Fprintln(writer, string(code)) } + } else { + _, _ = fmt.Fprint(writer, "\n\nContracts (hidden, use --include contracts)") } - writer.Flush() + _ = writer.Flush() return b.String() } diff --git a/internal/accounts/contract-add.go b/internal/accounts/contract-add.go index 19643c5f8..34f9006b7 100644 --- a/internal/accounts/contract-add.go +++ b/internal/accounts/contract-add.go @@ -28,8 +28,9 @@ import ( ) type flagsAddContract struct { - Signer string `default:"emulator-account" flag:"signer" info:"Account name from configuration used to sign the transaction"` - Results bool `default:"false" flag:"results" info:"⚠️ Deprecated: results are provided by default"` + Signer string `default:"emulator-account" flag:"signer" info:"Account name from configuration used to sign the transaction"` + Results bool `default:"false" flag:"results" info:"⚠️ Deprecated: results are provided by default"` + Include []string `default:"" flag:"include" info:"Fields to include in the output"` } var addContractFlags = flagsAddContract{} @@ -66,6 +67,7 @@ var AddContractCommand = &command.Command{ return &AccountResult{ Account: account, showCode: false, + include: addContractFlags.Include, }, nil }, } diff --git a/internal/accounts/contract-remove.go b/internal/accounts/contract-remove.go index e41787c44..9cc16c547 100644 --- a/internal/accounts/contract-remove.go +++ b/internal/accounts/contract-remove.go @@ -28,8 +28,9 @@ import ( ) type flagsRemoveContract struct { - Signer string `default:"emulator-account" flag:"signer" info:"Account name from configuration used to sign the transaction"` - Results bool `default:"false" flag:"results" info:"⚠️ Deprecated: results are provided by default"` + Signer string `default:"emulator-account" flag:"signer" info:"Account name from configuration used to sign the transaction"` + Results bool `default:"false" flag:"results" info:"⚠️ Deprecated: results are provided by default"` + Include []string `default:"" flag:"include" info:"Fields to include in the output"` } var flagsRemove = flagsRemoveContract{} @@ -63,6 +64,7 @@ var RemoveCommand = &command.Command{ return &AccountResult{ Account: account, showCode: false, + include: flagsRemove.Include, }, nil }, } diff --git a/internal/accounts/contract-update.go b/internal/accounts/contract-update.go index a411ef952..9e23337f0 100644 --- a/internal/accounts/contract-update.go +++ b/internal/accounts/contract-update.go @@ -28,8 +28,9 @@ import ( ) type flagsUpdateContract struct { - Signer string `default:"emulator-account" flag:"signer" info:"Account name from configuration used to sign the transaction"` - Results bool `default:"false" flag:"results" info:"⚠️ Deprecated: results are provided by default"` + Signer string `default:"emulator-account" flag:"signer" info:"Account name from configuration used to sign the transaction"` + Results bool `default:"false" flag:"results" info:"⚠️ Deprecated: results are provided by default"` + Include []string `default:"" flag:"include" info:"Fields to include in the output"` } var updateFlags = flagsUpdateContract{} @@ -65,6 +66,7 @@ var UpdateCommand = &command.Command{ return &AccountResult{ Account: account, showCode: false, + include: updateFlags.Include, }, nil }, } diff --git a/internal/accounts/create.go b/internal/accounts/create.go index feb5ecfb7..27e5a3d7c 100644 --- a/internal/accounts/create.go +++ b/internal/accounts/create.go @@ -35,6 +35,7 @@ type flagsCreate struct { HashAlgo string `default:"SHA3_256" flag:"hash-algo" info:"Hash used for the digest"` Contracts []string `flag:"contract" info:"Contract to be deployed during account creation. "` Results bool `default:"false" flag:"results" info:"⚠️ Deprecated: results are provided by default"` + Include []string `default:"" flag:"include" info:"Fields to include in the output"` } var createFlags = flagsCreate{} @@ -71,6 +72,7 @@ var CreateCommand = &command.Command{ return &AccountResult{ Account: account, + include: createFlags.Include, }, nil }, } diff --git a/internal/accounts/get.go b/internal/accounts/get.go index 26433c52a..4c2cac4a8 100644 --- a/internal/accounts/get.go +++ b/internal/accounts/get.go @@ -28,8 +28,9 @@ import ( ) type flagsGet struct { - Contracts bool `default:"false" flag:"contracts" info:"Display contracts deployed to the account"` - Code bool `default:"false" flag:"code" info:"⚠️ Deprecated: use contracts flag instead"` + Contracts bool `default:"false" flag:"contracts" info:"⚠️ Deprecated: use include flag instead"` + Code bool `default:"false" flag:"code" info:"⚠️ Deprecated: use contracts flag instead"` + Include []string `default:"" flag:"include" info:"Fields to include in the output"` } var getFlags = flagsGet{} @@ -52,6 +53,10 @@ var GetCommand = &command.Command{ fmt.Println("⚠️ DEPRECATION WARNING: use contracts flag instead") } + if getFlags.Contracts { + fmt.Println("⚠️ DEPRECATION WARNING: use include contracts flag instead") + } + account, err := services.Accounts.Get(args[0]) // address if err != nil { return nil, err @@ -60,6 +65,7 @@ var GetCommand = &command.Command{ return &AccountResult{ Account: account, showCode: getFlags.Contracts || getFlags.Code, + include: getFlags.Include, }, nil }, } diff --git a/internal/blocks/blocks.go b/internal/blocks/blocks.go index b86a88cc7..d0e51733c 100644 --- a/internal/blocks/blocks.go +++ b/internal/blocks/blocks.go @@ -22,6 +22,8 @@ import ( "bytes" "fmt" + "github.com/onflow/flow-cli/internal/command" + "github.com/onflow/flow-go-sdk" "github.com/onflow/flow-go-sdk/client" "github.com/spf13/cobra" @@ -46,6 +48,7 @@ type BlockResult struct { events []client.BlockEvents collections []*flow.Collection verbose bool + included []string } // JSON convert result to JSON @@ -94,7 +97,7 @@ func (r *BlockResult) String() string { for i, guarantee := range r.block.CollectionGuarantees { _, _ = fmt.Fprintf(writer, " Collection %d:\t%s\n", i, guarantee.CollectionID) - if r.verbose { + if r.verbose || command.ContainsFlag(r.included, "transactions") { for x, tx := range r.collections[i].TransactionIDs { _, _ = fmt.Fprintf(writer, " Transaction %d: %s\n", x, tx) } @@ -108,7 +111,7 @@ func (r *BlockResult) String() string { _, _ = fmt.Fprintf(writer, "%s", e.String()) } - writer.Flush() + _ = writer.Flush() return b.String() } diff --git a/internal/blocks/get.go b/internal/blocks/get.go index f11e99575..2a58691c5 100644 --- a/internal/blocks/get.go +++ b/internal/blocks/get.go @@ -28,11 +28,12 @@ import ( ) type flagsBlocks struct { - Events string `default:"" flag:"events" info:"List events of this type for the block"` - Verbose bool `default:"false" flag:"verbose" info:"Display transactions in block"` - Latest bool `default:"false" flag:"latest" info:"⚠️ No longer supported: use command argument"` - BlockID string `default:"" flag:"id" info:"⚠️ No longer supported: use command argument"` - BlockHeight uint64 `default:"0" flag:"height" info:"⚠️ No longer supported: use command argument"` + Events string `default:"" flag:"events" info:"List events of this type for the block"` + Include []string `default:"" flag:"include" info:"Fields to include in the output"` + Verbose bool `default:"false" flag:"verbose" info:"⚠️ Deprecated: use include transactions flag instead"` + Latest bool `default:"false" flag:"latest" info:"⚠️ No longer supported: use command argument"` + BlockID string `default:"" flag:"id" info:"⚠️ No longer supported: use command argument"` + BlockHeight uint64 `default:"0" flag:"height" info:"⚠️ No longer supported: use command argument"` } var blockFlags = flagsBlocks{} @@ -55,6 +56,10 @@ var GetCommand = &command.Command{ return nil, fmt.Errorf("⚠️ No longer supported: use command argument.") } + if blockFlags.Verbose { + fmt.Println("⚠️ DEPRECATION WARNING: use include transactions flag instead") + } + block, events, collections, err := services.Blocks.GetBlock( args[0], // block id blockFlags.Events, diff --git a/internal/command/command.go b/internal/command/command.go index ea8ff954c..35f552d62 100644 --- a/internal/command/command.go +++ b/internal/command/command.go @@ -301,7 +301,7 @@ func outputResult(result string, saveFlag string, formatFlag string, filterFlag Fs: afero.NewOsFs(), } - fmt.Printf("💾 result saved to: %s \n", saveFlag) + fmt.Printf("%s result saved to: %s \n", output.SaveEmoji(), saveFlag) return af.WriteFile(saveFlag, []byte(result), 0644) } @@ -350,32 +350,32 @@ func handleError(description string, err error) { // handle rpc error switch t := err.(type) { case *client.RPCError: - _, _ = fmt.Fprintf(os.Stderr, "❌ Grpc Error: %s \n", t.GRPCStatus().Err().Error()) + _, _ = fmt.Fprintf(os.Stderr, "%s Grpc Error: %s \n", output.ErrorEmoji(), t.GRPCStatus().Err().Error()) default: if errors.Is(err, config.ErrOutdatedFormat) { - _, _ = fmt.Fprintf(os.Stderr, "❌ Config Error: %s \n", err.Error()) - _, _ = fmt.Fprintf(os.Stderr, "🙏 Please reset configuration using: 'flow init --reset'. Read more about new configuration here: https://github.com/onflow/flow-cli/releases/tag/v0.17.0") + _, _ = fmt.Fprintf(os.Stderr, "%s Config Error: %s \n", output.ErrorEmoji(), err.Error()) + _, _ = fmt.Fprintf(os.Stderr, "%s Please reset configuration using: 'flow init --reset'. Read more about new configuration here: https://github.com/onflow/flow-cli/releases/tag/v0.17.0", output.TryEmoji()) } else if strings.Contains(err.Error(), "transport:") { - _, _ = fmt.Fprintf(os.Stderr, "❌ %s \n", strings.Split(err.Error(), "transport:")[1]) - _, _ = fmt.Fprintf(os.Stderr, "🙏 Make sure your emulator is running or connection address is correct.") + _, _ = fmt.Fprintf(os.Stderr, "%s %s \n", output.ErrorEmoji(), strings.Split(err.Error(), "transport:")[1]) + _, _ = fmt.Fprintf(os.Stderr, "%s Make sure your emulator is running or connection address is correct.", output.TryEmoji()) } else if strings.Contains(err.Error(), "NotFound desc =") { - _, _ = fmt.Fprintf(os.Stderr, "❌ Not Found:%s \n", strings.Split(err.Error(), "NotFound desc =")[1]) + _, _ = fmt.Fprintf(os.Stderr, "%s Not Found:%s \n", output.ErrorEmoji(), strings.Split(err.Error(), "NotFound desc =")[1]) } else if strings.Contains(err.Error(), "code = InvalidArgument desc = ") { desc := strings.Split(err.Error(), "code = InvalidArgument desc = ") - _, _ = fmt.Fprintf(os.Stderr, "❌ Invalid argument: %s \n", desc[len(desc)-1]) + _, _ = fmt.Fprintf(os.Stderr, "%s Invalid argument: %s \n", output.ErrorEmoji(), desc[len(desc)-1]) if strings.Contains(err.Error(), "is invalid for chain") { - _, _ = fmt.Fprintf(os.Stderr, "🙏 Check you are connecting to the correct network or account address you use is correct.") + _, _ = fmt.Fprintf(os.Stderr, "%s Check you are connecting to the correct network or account address you use is correct.", output.TryEmoji()) } else { - _, _ = fmt.Fprintf(os.Stderr, "🙏 Check your argument and flags value, you can use --help.") + _, _ = fmt.Fprintf(os.Stderr, "%s Check your argument and flags value, you can use --help.", output.TryEmoji()) } } else if strings.Contains(err.Error(), "invalid signature:") { - _, _ = fmt.Fprintf(os.Stderr, "❌ Invalid signature: %s \n", strings.Split(err.Error(), "invalid signature:")[1]) - _, _ = fmt.Fprintf(os.Stderr, "🙏 Check the signer private key is provided or is in the correct format. If running emulator, make sure it's using the same configuration as this command.") + _, _ = fmt.Fprintf(os.Stderr, "%s Invalid signature: %s \n", output.ErrorEmoji(), strings.Split(err.Error(), "invalid signature:")[1]) + _, _ = fmt.Fprintf(os.Stderr, "%s Check the signer private key is provided or is in the correct format. If running emulator, make sure it's using the same configuration as this command.", output.TryEmoji()) } else if strings.Contains(err.Error(), "signature could not be verified using public key with") { - _, _ = fmt.Fprintf(os.Stderr, "❌ %s: %s \n", description, err) - _, _ = fmt.Fprintf(os.Stderr, "🙏 If you are running emulator locally make sure that the emulator was started with the same config as used in this command. \nTry restarting the emulator.") + _, _ = fmt.Fprintf(os.Stderr, "%s %s: %s \n", output.ErrorEmoji(), description, err) + _, _ = fmt.Fprintf(os.Stderr, "%s If you are running emulator locally make sure that the emulator was started with the same config as used in this command. \nTry restarting the emulator.", output.TryEmoji()) } else { - _, _ = fmt.Fprintf(os.Stderr, "❌ %s: %s", description, err) + _, _ = fmt.Fprintf(os.Stderr, "%s %s: %s", output.ErrorEmoji(), description, err) } } @@ -396,8 +396,9 @@ func checkVersion(logger output.Logger) { if latestVersion != build.Semver() { logger.Info(fmt.Sprintf( - "\n⚠️ Version warning: a new version of Flow CLI is available (%s).\n"+ - "Read the installation guide for upgrade instructions: https://docs.onflow.org/flow-cli/install", + "\n%s Version warning: a new version of Flow CLI is available (%s).\n"+ + " Read the installation guide for upgrade instructions: https://docs.onflow.org/flow-cli/install\n", + output.WarningEmoji(), strings.ReplaceAll(string(latestVersion), "\n", ""), )) } diff --git a/internal/command/result.go b/internal/command/result.go index 994e7d462..13723dd40 100644 --- a/internal/command/result.go +++ b/internal/command/result.go @@ -18,8 +18,23 @@ package command +import ( + "strings" +) + type Result interface { String() string Oneliner() string JSON() interface{} } + +// ContainsFlag checks if output flag is present for the provided field +func ContainsFlag(flags []string, field string) bool { + for _, n := range flags { + if strings.ToLower(n) == field { + return true + } + } + + return false +} diff --git a/internal/config/init.go b/internal/config/init.go index 0937c0559..990e1f241 100644 --- a/internal/config/init.go +++ b/internal/config/init.go @@ -22,6 +22,8 @@ import ( "bytes" "fmt" + "github.com/onflow/flow-cli/pkg/flowcli/output" + "github.com/spf13/cobra" "github.com/onflow/flow-cli/internal/command" @@ -84,11 +86,11 @@ func (r *InitResult) String() string { account, _ := r.Project.EmulatorServiceAccount() _, _ = fmt.Fprintf(writer, "Configuration initialized\n") - _, _ = fmt.Fprintf(writer, "Service account: %s\n\n", util.Bold("0x"+account.Address().String())) + _, _ = fmt.Fprintf(writer, "Service account: %s\n\n", output.Bold("0x"+account.Address().String())) _, _ = fmt.Fprintf(writer, "Start emulator by running: %s \nReset configuration using: %s\n", - util.Bold("'flow emulator'"), - util.Bold("'flow init --reset'"), + output.Bold("'flow emulator'"), + output.Bold("'flow init --reset'"), ) writer.Flush() diff --git a/internal/keys/keys.go b/internal/keys/keys.go index 69b602881..16986039f 100644 --- a/internal/keys/keys.go +++ b/internal/keys/keys.go @@ -23,6 +23,8 @@ import ( "encoding/hex" "fmt" + "github.com/onflow/flow-cli/pkg/flowcli/output" + "github.com/onflow/flow-go-sdk" "github.com/onflow/flow-go-sdk/crypto" "github.com/spf13/cobra" @@ -65,7 +67,7 @@ func (k *KeyResult) String() string { writer := util.CreateTabWriter(&b) if k.privateKey != nil { - _, _ = fmt.Fprintf(writer, "🔴️ Store private key safely and don't share with anyone! \n") + _, _ = fmt.Fprintf(writer, "%s Store private key safely and don't share with anyone! \n", output.StopEmoji()) _, _ = fmt.Fprintf(writer, "Private Key \t %x \n", k.privateKey.Encode()) } diff --git a/internal/status/status.go b/internal/status/status.go index 5b1a33ea0..ee1a45095 100644 --- a/internal/status/status.go +++ b/internal/status/status.go @@ -22,6 +22,8 @@ import ( "bytes" "fmt" + "github.com/onflow/flow-cli/pkg/flowcli/output" + "github.com/spf13/cobra" "github.com/onflow/flow-cli/internal/command" @@ -62,39 +64,31 @@ type Result struct { err error } -const ( - OnlineIcon = "🟢" - OnlineStatus = "ONLINE" - - OfflineIcon = "🔴" - OfflineStatus = "OFFLINE" -) - // getStatus returns string representation for Flow network status. func (r *Result) getStatus() string { if r.err == nil { - return OnlineStatus + return "ONLINE" } - return OfflineStatus + return "OFFLINE" } // getColoredStatus returns colored string representation for Flow network status. func (r *Result) getColoredStatus() string { if r.err == nil { - return util.Green(OnlineStatus) + return output.Green(r.getStatus()) } - return util.Red(OfflineStatus) + return output.Red(output.Red(r.getStatus())) } // getIcon returns emoji icon representing Flow network status. func (r *Result) getIcon() string { if r.err == nil { - return OnlineIcon + return output.GoEmoji() } - return OfflineIcon + return output.StopEmoji() } // String converts result to a string. diff --git a/internal/transactions/get.go b/internal/transactions/get.go index 60dc5b4f9..ad44855ca 100644 --- a/internal/transactions/get.go +++ b/internal/transactions/get.go @@ -28,8 +28,10 @@ import ( ) type flagsGet struct { - Sealed bool `default:"true" flag:"sealed" info:"Wait for a sealed result"` - Code bool `default:"false" flag:"code" info:"Display transaction code"` + Sealed bool `default:"true" flag:"sealed" info:"Wait for a sealed result"` + Code bool `default:"false" flag:"code" info:"⚠️ Deprecated: use include flag"` + Include []string `default:"" flag:"include" info:"Fields to include in the output"` + Exclude []string `default:"" flag:"exclude" info:"Fields to exclude from the output (events)"` } var getFlags = flagsGet{} @@ -53,6 +55,10 @@ var GetCommand = &command.Command{ fmt.Println("⚠️ DEPRECATION WARNING: use \"flow transactions get\" instead") } + if getFlags.Code { + fmt.Println("⚠️ DEPRECATION WARNING: use include flag instead") + } + tx, result, err := services.Transactions.GetStatus( args[0], // transaction id getFlags.Sealed, @@ -62,9 +68,11 @@ var GetCommand = &command.Command{ } return &TransactionResult{ - result: result, - tx: tx, - code: getFlags.Code, + result: result, + tx: tx, + code: getFlags.Code, + include: getFlags.Include, + exclude: getFlags.Exclude, }, nil }, } diff --git a/internal/transactions/send-signed.go b/internal/transactions/send-signed.go index 0dbac74df..61de3e88f 100644 --- a/internal/transactions/send-signed.go +++ b/internal/transactions/send-signed.go @@ -26,6 +26,8 @@ import ( ) type flagsSendSigned struct { + Include []string `default:"" flag:"include" info:"Fields to include in the output"` + Exclude []string `default:"" flag:"exclude" info:"Fields to exclude from the output (events)"` } var sendSignedFlags = flagsSendSigned{} @@ -53,8 +55,10 @@ var SendSignedCommand = &command.Command{ } return &TransactionResult{ - result: result, - tx: tx, + result: result, + tx: tx, + include: sendSignedFlags.Include, + exclude: sendSignedFlags.Exclude, }, nil }, } diff --git a/internal/transactions/send.go b/internal/transactions/send.go index 5b861229f..1dfc07be2 100644 --- a/internal/transactions/send.go +++ b/internal/transactions/send.go @@ -32,6 +32,8 @@ type flagsSend struct { Arg []string `default:"" flag:"arg" info:"argument in Type:Value format"` Signer string `default:"emulator-account" flag:"signer" info:"Account name from configuration used to sign the transaction"` GasLimit uint64 `default:"1000" flag:"gas-limit" info:"transaction gas limit"` + Include []string `default:"" flag:"include" info:"Fields to include in the output"` + Exclude []string `default:"" flag:"exclude" info:"Fields to exclude from the output (events)"` Code string `default:"" flag:"code" info:"⚠️ Deprecated: use filename argument"` Results bool `default:"" flag:"results" info:"⚠️ Deprecated: all transactions will provide result"` Args string `default:"" flag:"args" info:"⚠️ Deprecated: use arg or args-json flag"` @@ -86,8 +88,10 @@ var SendCommand = &command.Command{ } return &TransactionResult{ - result: result, - tx: tx, + result: result, + tx: tx, + include: sendFlags.Include, + exclude: sendFlags.Exclude, }, nil }, } diff --git a/internal/transactions/transactions.go b/internal/transactions/transactions.go index d19575fc5..e80a87247 100644 --- a/internal/transactions/transactions.go +++ b/internal/transactions/transactions.go @@ -23,6 +23,10 @@ import ( "encoding/json" "fmt" + "github.com/onflow/flow-cli/pkg/flowcli/output" + + "github.com/onflow/flow-cli/internal/command" + jsoncdc "github.com/onflow/cadence/encoding/json" "github.com/onflow/flow-go-sdk" "github.com/spf13/cobra" @@ -47,9 +51,11 @@ func init() { // TransactionResult represent result from all account commands type TransactionResult struct { - result *flow.TransactionResult - tx *flow.Transaction - code bool + result *flow.TransactionResult + tx *flow.Transaction + code bool + include []string + exclude []string } // JSON convert result to JSON @@ -90,12 +96,12 @@ func (r *TransactionResult) String() string { if r.result != nil { if r.result.Error != nil { - _, _ = fmt.Fprintf(writer, "❌ Transaction Error \n%s\n\n\n", r.result.Error.Error()) + _, _ = fmt.Fprintf(writer, "%s Transaction Error \n%s\n\n\n", output.ErrorEmoji(), r.result.Error.Error()) } statusBadge := "" if r.result.Status == flow.TransactionStatusSealed { - statusBadge = "✅" + statusBadge = output.OkEmoji() } _, _ = fmt.Fprintf(writer, "Status\t%s %s\n", statusBadge, r.result.Status) } @@ -118,20 +124,32 @@ func (r *TransactionResult) String() string { } for i, e := range r.tx.PayloadSignatures { - _, _ = fmt.Fprintf(writer, "\nPayload Signature %v:\n", i) - _, _ = fmt.Fprintf(writer, " Address\t%s\n", e.Address) - _, _ = fmt.Fprintf(writer, " Signature\t%x\n", e.Signature) - _, _ = fmt.Fprintf(writer, " Key Index\t%d\n", e.KeyIndex) + if command.ContainsFlag(r.include, "signatures") { + _, _ = fmt.Fprintf(writer, "\nPayload Signature %v:\n", i) + _, _ = fmt.Fprintf(writer, " Address\t%s\n", e.Address) + _, _ = fmt.Fprintf(writer, " Signature\t%x\n", e.Signature) + _, _ = fmt.Fprintf(writer, " Key Index\t%d\n", e.KeyIndex) + } else { + _, _ = fmt.Fprintf(writer, "\nPayload Signature %v: %s", i, e.Address) + } } for i, e := range r.tx.EnvelopeSignatures { - _, _ = fmt.Fprintf(writer, "\nEnvelope Signature %v:\n", i) - _, _ = fmt.Fprintf(writer, " Address\t%s\n", e.Address) - _, _ = fmt.Fprintf(writer, " Signature\t%x\n", e.Signature) - _, _ = fmt.Fprintf(writer, " Key Index\t%d\n", e.KeyIndex) + if command.ContainsFlag(r.include, "signatures") { + _, _ = fmt.Fprintf(writer, "\nEnvelope Signature %v:\n", i) + _, _ = fmt.Fprintf(writer, " Address\t%s\n", e.Address) + _, _ = fmt.Fprintf(writer, " Signature\t%x\n", e.Signature) + _, _ = fmt.Fprintf(writer, " Key Index\t%d\n", e.KeyIndex) + } else { + _, _ = fmt.Fprintf(writer, "\nEnvelope Signature %v: %s", i, e.Address) + } } - if r.result != nil { + if !command.ContainsFlag(r.include, "signatures") { + _, _ = fmt.Fprintf(writer, "\nSignatures (minimized, use --include signatures)") + } + + if !command.ContainsFlag(r.exclude, "events") { e := events.EventResult{ Events: r.result.Events, } @@ -145,19 +163,27 @@ func (r *TransactionResult) String() string { } if r.tx.Script != nil { - if len(r.tx.Arguments) == 0 { - _, _ = fmt.Fprintf(writer, "\n\nArguments\tNo arguments\n") - } else { - _, _ = fmt.Fprintf(writer, "\n\nArguments (%d):\n", len(r.tx.Arguments)) - for i, argument := range r.tx.Arguments { - _, _ = fmt.Fprintf(writer, " - Argument %d: %s\n", i, argument) + if command.ContainsFlag(r.include, "code") || r.code { + if len(r.tx.Arguments) == 0 { + _, _ = fmt.Fprintf(writer, "\n\nArguments\tNo arguments\n") + } else { + _, _ = fmt.Fprintf(writer, "\n\nArguments (%d):\n", len(r.tx.Arguments)) + for i, argument := range r.tx.Arguments { + _, _ = fmt.Fprintf(writer, " - Argument %d: %s\n", i, argument) + } } - } - _, _ = fmt.Fprintf(writer, "\nCode\n\n%s\n", r.tx.Script) + _, _ = fmt.Fprintf(writer, "\nCode\n\n%s\n", r.tx.Script) + } else { + _, _ = fmt.Fprint(writer, "\n\nCode (hidden, use --include code)") + } } - _, _ = fmt.Fprintf(writer, "\n\nPayload:\n%x", r.tx.Encode()) + if command.ContainsFlag(r.include, "payload") { + _, _ = fmt.Fprintf(writer, "\n\nPayload:\n%x", r.tx.Encode()) + } else { + _, _ = fmt.Fprint(writer, "\n\nPayload (hidden, use --include payload)") + } _ = writer.Flush() return b.String() diff --git a/pkg/flowcli/output/colors.go b/pkg/flowcli/output/colors.go new file mode 100644 index 000000000..a61457745 --- /dev/null +++ b/pkg/flowcli/output/colors.go @@ -0,0 +1,31 @@ +package output + +import ( + "fmt" + "runtime" +) + +var red = "\033[31m" +var green = "\033[32m" +var bold = "\033[1m" +var reset = "\033[0m" + +func printColor(msg string, color string) string { + if runtime.GOOS == "windows" { + return msg + } + + return fmt.Sprintf("%s%s%s", color, msg, reset) +} + +func Red(msg string) string { + return printColor(msg, red) +} + +func Green(msg string) string { + return printColor(msg, green) +} + +func Bold(msg string) string { + return printColor(msg, bold) +} diff --git a/pkg/flowcli/output/emoji.go b/pkg/flowcli/output/emoji.go new file mode 100644 index 000000000..b0465cd61 --- /dev/null +++ b/pkg/flowcli/output/emoji.go @@ -0,0 +1,43 @@ +package output + +import "runtime" + +func printEmoji(emoji string) string { + if runtime.GOOS == "windows" { + return "" + } + + return emoji +} + +func ErrorEmoji() string { + return printEmoji("❌") +} + +func TryEmoji() string { + return printEmoji("🙏") +} + +func WarningEmoji() string { + return printEmoji("⚠️") +} + +func SaveEmoji() string { + return printEmoji("💾") +} + +func StopEmoji() string { + return printEmoji("🔴️") +} + +func GoEmoji() string { + return printEmoji("🟢") +} + +func OkEmoji() string { + return printEmoji("✅") +} + +func SuccessEmoji() string { + return printEmoji("✨") +} diff --git a/pkg/flowcli/output/logger.go b/pkg/flowcli/output/logger.go index cba9a6c73..3cb717637 100644 --- a/pkg/flowcli/output/logger.go +++ b/pkg/flowcli/output/logger.go @@ -20,8 +20,6 @@ package output import ( "fmt" - - "github.com/onflow/flow-cli/pkg/flowcli/util" ) const ( @@ -69,7 +67,7 @@ func (s *StdoutLogger) Debug(msg string) { } func (s *StdoutLogger) Error(msg string) { - s.log(fmt.Sprintf("❌ %s", util.Red(msg)), ErrorLog) + s.log(fmt.Sprintf("%s %s", ErrorEmoji(), Red(msg)), ErrorLog) } func (s *StdoutLogger) StartProgress(msg string) { diff --git a/pkg/flowcli/project/project.go b/pkg/flowcli/project/project.go index e153974f7..e89d43146 100644 --- a/pkg/flowcli/project/project.go +++ b/pkg/flowcli/project/project.go @@ -219,7 +219,7 @@ func (p *Project) AccountNamesForNetwork(network string) []string { for _, account := range p.accounts { if len(p.conf.Deployments.GetByAccountAndNetwork(account.name, network)) > 0 { - if !util.StringContains(names, account.name) { + if !util.ContainsString(names, account.name) { names = append(names, account.name) } } diff --git a/pkg/flowcli/services/accounts.go b/pkg/flowcli/services/accounts.go index 52556a4d7..15c5f6aec 100644 --- a/pkg/flowcli/services/accounts.go +++ b/pkg/flowcli/services/accounts.go @@ -343,15 +343,17 @@ func (a *Accounts) addContract( if updateExisting { a.logger.Info(fmt.Sprintf( - "Contract '%s' updated on the account '%s'.", + "Contract '%s' updated on the account '%s'.\nTransaction ID: %s.", contractName, account.Address(), + sentTx.ID().String(), )) } else { a.logger.Info(fmt.Sprintf( - "Contract '%s' deployed to the account '%s'.", + "Contract '%s' deployed to the account '%s'.\nTransaction ID: %s.", contractName, account.Address(), + sentTx.ID().String(), )) } @@ -398,7 +400,12 @@ func (a *Accounts) RemoveContract( } a.logger.StopProgress() - a.logger.Info(fmt.Sprintf("Contract %s removed from account %s\n", contractName, account.Address())) + a.logger.Info(fmt.Sprintf( + "Contract %s removed from account %s.\nTransaction ID: %s.", + contractName, + account.Address(), + sentTx.ID().String(), + )) return a.gateway.GetAccount(account.Address()) } diff --git a/pkg/flowcli/services/project.go b/pkg/flowcli/services/project.go index 021df62dc..374434403 100644 --- a/pkg/flowcli/services/project.go +++ b/pkg/flowcli/services/project.go @@ -221,7 +221,7 @@ func (p *Project) Deploy(network string, update bool) ([]*contracts.Contract, er } p.logger.StartProgress( - fmt.Sprintf("%s deploying...", util.Bold(contract.Name())), + fmt.Sprintf("%s deploying...", output.Bold(contract.Name())), ) result, err := p.gateway.GetTransactionResult(sentTx, true) @@ -232,7 +232,7 @@ func (p *Project) Deploy(network string, update bool) ([]*contracts.Contract, er if result.Error == nil && !deployErr { p.logger.StopProgress() - fmt.Printf("%s -> 0x%s\n", util.Green(contract.Name()), contract.Target()) + fmt.Printf("%s -> 0x%s\n", output.Green(contract.Name()), contract.Target()) } else { p.logger.StopProgress() p.logger.Error( @@ -242,7 +242,7 @@ func (p *Project) Deploy(network string, update bool) ([]*contracts.Contract, er } if !deployErr { - p.logger.Info("\n✨ All contracts deployed successfully") + p.logger.Info(fmt.Sprintf("\n%s All contracts deployed successfully", output.SuccessEmoji())) } else { err = fmt.Errorf("failed to deploy contracts") p.logger.Error(err.Error()) diff --git a/pkg/flowcli/util/utilities.go b/pkg/flowcli/util/utilities.go index 6831d5b49..f25d57099 100644 --- a/pkg/flowcli/util/utilities.go +++ b/pkg/flowcli/util/utilities.go @@ -24,16 +24,10 @@ import ( "io/ioutil" "text/tabwriter" - "github.com/fatih/color" - "github.com/onflow/flow-go-sdk" "github.com/onflow/flow-go-sdk/crypto" ) -var Green = color.New(color.FgGreen, color.Bold).SprintfFunc() -var Red = color.New(color.FgRed, color.Bold).SprintfFunc() -var Bold = color.New(color.FgCyan).SprintfFunc() - // LoadFile loads a file by filename. func LoadFile(filename string) ([]byte, error) { var code []byte @@ -80,8 +74,8 @@ func ConvertSigAndHashAlgo( return sigAlgo, hashAlgo, nil } -// StringContains returns true if the slice contains the given string. -func StringContains(s []string, e string) bool { +// ContainsString returns true if the slice contains the given string. +func ContainsString(s []string, e string) bool { for _, a := range s { if a == e { return true @@ -111,15 +105,6 @@ func CreateTabWriter(b *bytes.Buffer) *tabwriter.Writer { return tabwriter.NewWriter(b, 0, 8, 1, '\t', tabwriter.AlignRight) } -func ContainsString(s []string, e string) bool { - for _, a := range s { - if a == e { - return true - } - } - return false -} - func ParseAddress(value string) (flow.Address, bool) { address := flow.HexToAddress(value)