Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add gas config to the client.toml #5020

Merged
merged 13 commits into from
May 11, 2023
264 changes: 264 additions & 0 deletions cmd/osmosisd/cmd/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
package cmd

import (
"bytes"
"encoding/json"
"fmt"
"os"
"path/filepath"
"text/template"

"github.com/spf13/cobra"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
viper "github.com/spf13/viper"
tmcli "github.com/tendermint/tendermint/libs/cli"
)

type OsmosisCustomClient struct {
ChainID string `mapstructure:"chain-id" json:"chain-id"`
KeyringBackend string `mapstructure:"keyring-backend" json:"keyring-backend"`
Output string `mapstructure:"output" json:"output"`
Node string `mapstructure:"node" json:"node"`
BroadcastMode string `mapstructure:"broadcast-mode" json:"broadcast-mode"`
Gas string `mapstructure:"gas" json:"gas"`
GasPrices string `mapstructure:"gas-prices" json:"gas-prices"`
GasAdjustment string `mapstructure:"gas-adjustment" json:"gas-adjustment"`
}

// Override sdk ConfigCmd func
func ConfigCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "config <key> [value]",
Short: "Create or query an application CLI configuration file",
RunE: runConfigCmd,
Args: cobra.RangeArgs(0, 2),
}
return cmd
}

func runConfigCmd(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
configPath := filepath.Join(clientCtx.HomeDir, "config")

conf, err := getClientConfig(configPath, clientCtx.Viper)
if err != nil {
return fmt.Errorf("couldn't get client config: %v", err)
}

occ := *conf

switch len(args) {
case 0:
s, err := json.MarshalIndent(occ, "", "\t")
if err != nil {
return err
}

cmd.Println(string(s))

case 1:
// it's a get
key := args[0]

switch key {
case flags.FlagChainID:
cmd.Println(conf.ChainID)
case flags.FlagKeyringBackend:
cmd.Println(conf.KeyringBackend)
case tmcli.OutputFlag:
cmd.Println(conf.Output)
case flags.FlagNode:
cmd.Println(conf.Node)
case flags.FlagBroadcastMode:
cmd.Println(conf.BroadcastMode)
case flags.FlagGas:
cmd.Println(occ.Gas)
case flags.FlagGasPrices:
cmd.Println(occ.GasPrices)
case flags.FlagGasAdjustment:
cmd.Println(occ.GasAdjustment)
default:
err := errUnknownConfigKey(key)
return fmt.Errorf("couldn't get the value for the key: %v, error: %v", key, err)
}

case 2:
// it's set
key, value := args[0], args[1]

switch key {
case flags.FlagChainID:
occ.ChainID = value
case flags.FlagKeyringBackend:
occ.KeyringBackend = value
case tmcli.OutputFlag:
occ.Output = value
case flags.FlagNode:
occ.Node = value
case flags.FlagBroadcastMode:
occ.BroadcastMode = value
case flags.FlagGas:
occ.Gas = value
case flags.FlagGasPrices:
occ.GasPrices = value
case flags.FlagGasAdjustment:
occ.GasAdjustment = value
default:
return errUnknownConfigKey(key)
}

confFile := filepath.Join(configPath, "client.toml")
if err := writeConfigToFile(confFile, &occ); err != nil {
return fmt.Errorf("could not write client config to the file: %v", err)
}

default:
panic("cound not execute config command")
}

return nil
}

const defaultConfigTemplate = `# This is a TOML config file.
# For more information, see https://github.com/toml-lang/toml

###############################################################################
### Client Configuration ###
###############################################################################

# The network chain ID
chain-id = "{{ .ChainID }}"
# The keyring's backend, where the keys are stored (os|file|kwallet|pass|test|memory)
keyring-backend = "{{ .KeyringBackend }}"
# CLI output format (text|json)
output = "{{ .Output }}"
# <host>:<port> to Tendermint RPC interface for this chain
node = "{{ .Node }}"
# Transaction broadcasting mode (sync|async)
broadcast-mode = "{{ .BroadcastMode }}"


###############################################################################
### Osmosis Tx Configuration ###
###############################################################################
# Amount of gas per transaction
gas = "{{ .Gas }}"
# Price per unit of gas (ex: 0.005uosmo)
gas-prices = "{{ .GasPrices }}"
gas-adjustment = "{{ .GasAdjustment }}"
`

// writeConfigToFile parses defaultConfigTemplate, renders config using the template and writes it to
// configFilePath.
func writeConfigToFile(configFilePath string, config *OsmosisCustomClient) error {
var buffer bytes.Buffer

tmpl := template.New("clientConfigFileTemplate")
configTemplate, err := tmpl.Parse(defaultConfigTemplate)
if err != nil {
return err
}

if err := configTemplate.Execute(&buffer, config); err != nil {
return err
}

return os.WriteFile(configFilePath, buffer.Bytes(), 0o600)
}

// getClientConfig reads values from client.toml file and unmarshalls them into ClientConfig
func getClientConfig(configPath string, v *viper.Viper) (*OsmosisCustomClient, error) {
v.AddConfigPath(configPath)
v.SetConfigName("client")
v.SetConfigType("toml")

if err := v.ReadInConfig(); err != nil {
return nil, err
}

conf := new(OsmosisCustomClient)
if err := v.Unmarshal(conf); err != nil {
return nil, err
}

return conf, nil
}

// Reads the custom extra values in the config.toml file if set.
// If they are, then use them.
func SetCustomEnvVariablesFromClientToml(ctx client.Context) {
configFilePath := filepath.Join(ctx.HomeDir, "config", "client.toml")

if _, err := os.Stat(configFilePath); os.IsNotExist(err) {
return
}

viper := ctx.Viper
viper.SetConfigFile(configFilePath)

if err := viper.ReadInConfig(); err != nil {
panic(err)
}
}

func errUnknownConfigKey(key string) error {
return fmt.Errorf("unknown configuration key: %q", key)
}

// ReadFromClientConfig reads values from client.toml file and updates them in client Context
func ReadFromClientConfig(ctx client.Context) (client.Context, error) {
configPath := filepath.Join(ctx.HomeDir, "config")
configFilePath := filepath.Join(configPath, "client.toml")
conf := defaultClientConfig()

// if config.toml file does not exist we create it and write default ClientConfig values into it.
if _, err := os.Stat(configFilePath); os.IsNotExist(err) {
if err := ensureConfigPath(configPath); err != nil {
return ctx, fmt.Errorf("couldn't make client config: %v", err)
}

if err := writeConfigToFile(configFilePath, conf); err != nil {
return ctx, fmt.Errorf("could not write client config to the file: %v", err)
}
}

conf, err := getClientConfig(configPath, ctx.Viper)
if err != nil {
return ctx, fmt.Errorf("couldn't get client config: %v", err)
}
// we need to update KeyringDir field on Client Context first cause it is used in NewKeyringFromBackend
ctx = ctx.WithOutputFormat(conf.Output).
WithChainID(conf.ChainID).
WithKeyringDir(ctx.HomeDir)

keyring, err := client.NewKeyringFromBackend(ctx, conf.KeyringBackend)
if err != nil {
return ctx, fmt.Errorf("couldn't get key ring: %v", err)
}

ctx = ctx.WithKeyring(keyring)

// https://github.com/cosmos/cosmos-sdk/issues/8986
client, err := client.NewClientFromNode(conf.Node)
if err != nil {
return ctx, fmt.Errorf("couldn't get client from nodeURI: %v", err)
}

ctx = ctx.WithNodeURI(conf.Node).
WithClient(client).
WithBroadcastMode(conf.BroadcastMode)

return ctx, nil
}

// defaultClientConfig returns the reference to ClientConfig with default values.
func defaultClientConfig() *OsmosisCustomClient {
return &OsmosisCustomClient{"", "os", "text", "tcp://localhost:26657", "sync", "", "", ""}
}

// ensureConfigPath creates a directory configPath if it does not exist
func ensureConfigPath(configPath string) error {
return os.MkdirAll(configPath, os.ModePerm)
}
9 changes: 6 additions & 3 deletions cmd/osmosisd/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (

"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/config"
"github.com/cosmos/cosmos-sdk/client/debug"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/keys"
Expand Down Expand Up @@ -68,6 +67,10 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
WithHomeDir(homeDir).
WithViper("OSMOSIS")

// Allows you to add extra params to your client.toml
// gas, gas-price, gas-adjustment
SetCustomEnvVariablesFromClientToml(initClientCtx)

rootCmd := &cobra.Command{
Use: "osmosisd",
Short: "Start osmosis app",
Expand All @@ -76,7 +79,7 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
if err != nil {
return err
}
initClientCtx, err = config.ReadFromClientConfig(initClientCtx)
initClientCtx, err = ReadFromClientConfig(initClientCtx)
if err != nil {
return err
}
Expand Down Expand Up @@ -182,7 +185,7 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) {
testnetCmd(osmosis.ModuleBasics, banktypes.GenesisBalancesIterator{}),
tmcmds.RollbackStateCmd,
debugCmd,
config.Cmd(),
ConfigCmd(),
ChangeEnvironmentCmd(),
PrintEnvironmentCmd(),
)
Expand Down