Skip to content

Commit

Permalink
feat: initial genesis replace cmd
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonathansumner committed Apr 9, 2024
1 parent fe70928 commit 18ddc93
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 0 deletions.
164 changes: 164 additions & 0 deletions cmd/fetchd/cmd/genreplace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package cmd

import (
"encoding/json"
"fmt"
"regexp"
"strings"

"github.com/spf13/cobra"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/server"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/genutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
)

const (
flagNewDescription = "new-description"
)

// ReplaceGenesisValuesCmd returns replace-genesis-values cobra Command.
func ReplaceGenesisValuesCmd(defaultNodeHome string) *cobra.Command {
cmd := &cobra.Command{
Use: "replace-genesis-values [new-denom] [old-denom]",
Short: "Replace the major values within genesis.json, such as native denom",
Long: `Replace the major values within genesis.json, such as native denom.
`,
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
cdc := clientCtx.Codec

serverCtx := server.GetServerContextFromCmd(cmd)
config := serverCtx.Config

config.SetRoot(clientCtx.HomeDir)

newDesc, err := cmd.Flags().GetString(flagNewDescription)
if err != nil {
return err
}

inputData := replacementData{
NewBaseDenom: args[0],
OldBaseDenom: args[1],
NewDenom: fmt.Sprintf("a%s", args[0]),
OldDenom: fmt.Sprintf("a%s", args[1]),
NewDescription: newDesc,
OldAddrPrefix: "fetch",
NewAddrPrefix: "asi",
}

genFile := config.GenesisFile()

appState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFile)
if err != nil {
return fmt.Errorf("failed to unmarshal genesis state: %w", err)
}

//authGenState := authtypes.GetGenesisStateFromAppState(cdc, appState) TODO: amend account prefix here, potentially

bankGenState := banktypes.GetGenesisStateFromAppState(cdc, appState)
replaceDenomMetadata(&inputData, bankGenState)

bankGenStateBz, err := cdc.MarshalJSON(bankGenState)
if err != nil {
return fmt.Errorf("failed to marshal auth genesis state: %w", err)
}

appState[banktypes.ModuleName] = bankGenStateBz

appStateJSON, err := json.Marshal(appState)
if err != nil {
return fmt.Errorf("failed to marshal application genesis state: %w", err)
}

appStateStr := string(appStateJSON)
for _, target := range []string{"denom", "bond_denom", "mint_denom", "base_denom", "base"} {
re := regexp.MustCompile(fmt.Sprintf(`("%s"\s*:\s*)"%s"`, target, inputData.OldDenom))
if re.MatchString(appStateStr) {
appStateStr = re.ReplaceAllString(appStateStr, fmt.Sprintf(`${1}"%s"`, inputData.NewDenom))
}
}

genDoc.AppState = []byte(appStateStr)
return genutil.ExportGenesisFile(genDoc, genFile)
},
}

cmd.Flags().String(flags.FlagHome, defaultNodeHome, "The application home directory")
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)")
cmd.Flags().String(flagNewDescription, "", "The new description for the native coin in the genesis file")
flags.AddQueryFlagsToCmd(cmd)

return cmd
}

func replaceDenomMetadata(d *replacementData, b *banktypes.GenesisState) {
denomRegex := getRegex(d.OldDenom, d.NewDenom)
upperDenomRegex := getRegex(strings.ToUpper(d.OldBaseDenom), strings.ToUpper(d.NewBaseDenom))
exponentDenomRegex := getPartialRegexLeft(d.OldBaseDenom, d.NewBaseDenom)

for _, metadata := range b.DenomMetadata {
replaceString(&metadata.Base, []*regexPair{denomRegex})
if metadata.Name == d.OldBaseDenom {
metadata.Description = d.NewDescription
}
replaceString(&metadata.Display, []*regexPair{upperDenomRegex})
replaceString(&metadata.Name, []*regexPair{upperDenomRegex})
replaceString(&metadata.Symbol, []*regexPair{upperDenomRegex})
for _, unit := range metadata.DenomUnits {
replaceString(&unit.Denom, []*regexPair{upperDenomRegex})
replaceString(&unit.Denom, []*regexPair{exponentDenomRegex})
}

}
}

func getRegex(oldValue string, newValue string) *regexPair {
return &regexPair{
pattern: fmt.Sprintf(`^%s$`, oldValue),
replacement: fmt.Sprintf(`%s`, newValue),
}
}

func getPartialRegexLeft(oldValue string, newValue string) *regexPair {
return &regexPair{
pattern: fmt.Sprintf(`(.*?)%s`, oldValue),
replacement: fmt.Sprintf(`${1}%s`, newValue),
}
}

func getPartialRegexRight(oldValue string, newValue string) *regexPair {
return &regexPair{
pattern: fmt.Sprintf(`%s(.*)`, oldValue),
replacement: fmt.Sprintf(`%s${1}`, newValue),
}
}

func replaceString(s *string, replacements []*regexPair) {
for _, pair := range replacements {
re := regexp.MustCompile(pair.pattern)
if re.MatchString(*s) {
*s = re.ReplaceAllString(*s, pair.replacement)
}
}
}

type regexPair struct {
pattern string
replacement string
}

type replacementData struct {
NewBaseDenom string
OldBaseDenom string
NewDenom string
OldDenom string
NewDescription string
OldAddrPrefix string
NewAddrPrefix string
}
1 change: 1 addition & 0 deletions cmd/fetchd/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) {
genutilcli.ValidateGenesisCmd(app.ModuleBasics),
AddGenesisAccountCmd(app.DefaultNodeHome),
AddGenesisDelegationCmd(app.DefaultNodeHome),
ReplaceGenesisValuesCmd(app.DefaultNodeHome),
tmcli.NewCompletionCmd(rootCmd, true),
debug.Cmd(),
AddGenesisWasmMsgCmd(app.DefaultNodeHome),
Expand Down

0 comments on commit 18ddc93

Please sign in to comment.