Skip to content

Commit 2ef335f

Browse files
feat: initial empty command
1 parent 18ddc93 commit 2ef335f

File tree

3 files changed

+283
-1
lines changed

3 files changed

+283
-1
lines changed

app/prefix.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
)
66

77
const (
8-
AccountAddressPrefix = "fetch"
8+
AccountAddressPrefix = "asi"
99
)
1010

1111
var (

cmd/fetchd/cmd/genasiupgrade.go

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
package cmd
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"github.com/btcsuite/btcutil/bech32"
7+
"github.com/cosmos/cosmos-sdk/codec"
8+
cosmostypes "github.com/cosmos/cosmos-sdk/types"
9+
"github.com/spf13/cobra"
10+
"github.com/tendermint/tendermint/types"
11+
"regexp"
12+
"strings"
13+
14+
"github.com/cosmos/cosmos-sdk/client"
15+
"github.com/cosmos/cosmos-sdk/client/flags"
16+
"github.com/cosmos/cosmos-sdk/server"
17+
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
18+
"github.com/cosmos/cosmos-sdk/x/genutil"
19+
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
20+
)
21+
22+
const (
23+
flagNewDescription = "new-description"
24+
Bech32Chars = "023456789acdefghjklmnpqrstuvwxyz"
25+
AddrDataLength = 32
26+
WasmDataLength = 52
27+
AddrChecksumLength = 6
28+
AccAddressPrefix = ""
29+
ValAddressPrefix = "valoper"
30+
ConsAddressPrefix = "valcons"
31+
32+
NewBaseDenom = "asi"
33+
NewDenom = "aasi"
34+
NewAddrPrefix = "asi"
35+
NewChainId = "asi-1"
36+
NewDescription = "ASI Token"
37+
38+
OldBaseDenom = "fet"
39+
OldDenom = "afet"
40+
OldAddrPrefix = "fetch"
41+
)
42+
43+
//" fetch char* [bech32 chars] limited by size " CHECKSUM?
44+
//verify functions after!
45+
46+
// ASIGenesisUpgradeCmd returns replace-genesis-values cobra Command.
47+
func ASIGenesisUpgradeCmd(defaultNodeHome string) *cobra.Command {
48+
cmd := &cobra.Command{
49+
Use: "asi-genesis-upgrade",
50+
Short: "This command carries out a full upgrade of the genesis file to the new ASI chain parameters.",
51+
Long: `The following command will upgrade the current genesis file to the new ASI chain parameters. The following changes will be made:
52+
- Chain ID will be updated to "asi-1"
53+
- The native coin denom will be updated to "asi"
54+
- The address prefix will be updated to "asi"
55+
- The old fetch addresses will be updated to the new asi addresses`,
56+
57+
Args: cobra.ExactArgs(0),
58+
RunE: func(cmd *cobra.Command, args []string) error {
59+
clientCtx := client.GetClientContextFromCmd(cmd)
60+
cdc := clientCtx.Codec
61+
62+
serverCtx := server.GetServerContextFromCmd(cmd)
63+
config := serverCtx.Config
64+
65+
config.SetRoot(clientCtx.HomeDir)
66+
67+
genFile := config.GenesisFile()
68+
69+
appState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFile)
70+
if err != nil {
71+
return fmt.Errorf("failed to unmarshal genesis state: %w", err)
72+
}
73+
74+
// replace chain-id
75+
ASIGenesisUpgradeReplaceChainID(genDoc)
76+
77+
// set denom metadata in bank module
78+
err = ASIGenesisUpgradeReplaceDenomMetadata(cdc, &appState)
79+
if err != nil {
80+
return fmt.Errorf("failed to replace denom metadata: %w", err)
81+
}
82+
83+
appStateJSON, err := json.Marshal(appState)
84+
if err != nil {
85+
return fmt.Errorf("failed to marshal application genesis state: %w", err)
86+
}
87+
88+
appStateStr := string(appStateJSON)
89+
90+
// replace denom across the genesis file
91+
ASIGenesisUpgradeReplaceDenom(&appStateStr)
92+
93+
// replace addresses across the genesis file
94+
ASIGenesisUpgradeReplaceAddresses(&appStateStr)
95+
96+
genDoc.AppState = []byte(appStateStr)
97+
return genutil.ExportGenesisFile(genDoc, genFile)
98+
},
99+
}
100+
101+
cmd.Flags().String(flags.FlagHome, defaultNodeHome, "The application home directory")
102+
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)")
103+
cmd.Flags().String(flagNewDescription, "", "The new description for the native coin in the genesis file")
104+
flags.AddQueryFlagsToCmd(cmd)
105+
106+
return cmd
107+
}
108+
109+
func ASIGenesisUpgradeReplaceDenomMetadata(cdc codec.Codec, appState *map[string]json.RawMessage) error {
110+
bankGenState := banktypes.GetGenesisStateFromAppState(cdc, *appState)
111+
112+
OldBaseDenomUpper := strings.ToUpper(OldBaseDenom)
113+
NewBaseDenomUpper := strings.ToUpper(NewBaseDenom)
114+
115+
denomRegex := getRegex(OldDenom, NewDenom)
116+
upperDenomRegex := getRegex(OldBaseDenomUpper, NewBaseDenomUpper)
117+
exponentDenomRegex := getPartialRegexLeft(OldBaseDenom, NewBaseDenom)
118+
119+
for _, metadata := range bankGenState.DenomMetadata {
120+
replaceString(&metadata.Base, []*regexPair{denomRegex})
121+
if metadata.Name == OldBaseDenomUpper {
122+
metadata.Description = NewDescription
123+
metadata.Display = NewBaseDenomUpper
124+
metadata.Name = NewBaseDenomUpper
125+
metadata.Symbol = NewBaseDenomUpper
126+
}
127+
for _, unit := range metadata.DenomUnits {
128+
replaceString(&unit.Denom, []*regexPair{upperDenomRegex})
129+
replaceString(&unit.Denom, []*regexPair{exponentDenomRegex})
130+
}
131+
}
132+
133+
bankGenStateBytes, err := cdc.MarshalJSON(bankGenState)
134+
if err != nil {
135+
return fmt.Errorf("failed to marshal auth genesis state: %w", err)
136+
}
137+
138+
(*appState)[banktypes.ModuleName] = bankGenStateBytes
139+
return nil
140+
}
141+
142+
func ASIGenesisUpgradeReplaceChainID(genesisData *types.GenesisDoc) {
143+
genesisData.ChainID = NewChainId
144+
}
145+
146+
func ASIGenesisUpgradeReplaceDenom(jsonString *string) {
147+
for _, target := range []string{"denom", "bond_denom", "mint_denom", "base_denom", "base"} {
148+
re := regexp.MustCompile(fmt.Sprintf(`("%s"\s*:\s*)"%s"`, target, OldDenom))
149+
if re.MatchString(*jsonString) {
150+
*jsonString = re.ReplaceAllString(*jsonString, fmt.Sprintf(`${1}"%s"`, NewDenom))
151+
}
152+
}
153+
}
154+
155+
func ASIGenesisUpgradeReplaceAddresses(jsonString *string) {
156+
// account addresses
157+
replaceAddresses(AccAddressPrefix, jsonString, AddrDataLength+AddrChecksumLength)
158+
// validator addresses
159+
replaceAddresses(ValAddressPrefix, jsonString, AddrDataLength+AddrChecksumLength)
160+
// consensus addresses
161+
replaceAddresses(ConsAddressPrefix, jsonString, AddrDataLength+AddrChecksumLength)
162+
// contract addresses
163+
replaceAddresses(AccAddressPrefix, jsonString, WasmDataLength+AddrChecksumLength)
164+
}
165+
166+
func replaceAddresses(addressTypePrefix string, jsonString *string, dataLength int) {
167+
re := regexp.MustCompile(fmt.Sprintf(`"%s%s1([%s]{%d})"`, OldAddrPrefix, addressTypePrefix, Bech32Chars, dataLength))
168+
matches := re.FindAllString(*jsonString, -1)
169+
170+
replacements := make(map[string]string, len(matches))
171+
for _, match := range matches {
172+
matchedAddr := strings.ReplaceAll(match, `"`, "")
173+
_, decodedAddrData, err := bech32.Decode(matchedAddr)
174+
if err != nil {
175+
panic(err)
176+
}
177+
178+
newAddress, err := bech32.Encode(NewAddrPrefix+addressTypePrefix, decodedAddrData)
179+
if err != nil {
180+
panic(err)
181+
}
182+
183+
err = cosmostypes.VerifyAddressFormat(decodedAddrData)
184+
if err != nil {
185+
panic(err)
186+
}
187+
188+
switch addressTypePrefix {
189+
case AccAddressPrefix:
190+
_, err = cosmostypes.AccAddressFromBech32(newAddress)
191+
case ValAddressPrefix:
192+
_, err = cosmostypes.ValAddressFromBech32(newAddress)
193+
case ConsAddressPrefix:
194+
_, err = cosmostypes.ConsAddressFromBech32(newAddress)
195+
default:
196+
panic("invalid address type prefix")
197+
}
198+
if err != nil {
199+
panic(err)
200+
}
201+
replacements[matchedAddr] = newAddress
202+
}
203+
204+
var jsonData map[string]interface{}
205+
err := json.Unmarshal([]byte(*jsonString), &jsonData)
206+
if err != nil {
207+
panic(err)
208+
}
209+
210+
modified := crawlJson(jsonData, func(data interface{}) interface{} {
211+
if str, ok := data.(string); ok {
212+
if !re.MatchString(fmt.Sprintf(`"%s"`, str)) || len(str) > 200 {
213+
return data
214+
}
215+
216+
return replacements[str]
217+
}
218+
return data
219+
})
220+
221+
modifiedJSON, err := json.Marshal(modified)
222+
if err != nil {
223+
panic(err)
224+
}
225+
*jsonString = string(modifiedJSON)
226+
}
227+
228+
func ASIGenesisUpgradeWithdrawIBCChannelsBalances() {
229+
230+
}
231+
232+
func ASIGenesisUpgradeWithdrawReconciliationBalances() {
233+
234+
}
235+
236+
func getRegex(oldValue string, newValue string) *regexPair {
237+
return &regexPair{
238+
pattern: fmt.Sprintf(`^%s$`, oldValue),
239+
replacement: fmt.Sprintf(`%s`, newValue),
240+
}
241+
}
242+
243+
func getPartialRegexLeft(oldValue string, newValue string) *regexPair {
244+
return &regexPair{
245+
pattern: fmt.Sprintf(`(.*?)%s"`, oldValue),
246+
replacement: fmt.Sprintf(`${1}%s"`, newValue),
247+
}
248+
}
249+
250+
func replaceString(s *string, replacements []*regexPair) {
251+
for _, pair := range replacements {
252+
re := regexp.MustCompile(pair.pattern)
253+
if re.MatchString(*s) {
254+
*s = re.ReplaceAllString(*s, pair.replacement)
255+
}
256+
}
257+
}
258+
259+
type regexPair struct {
260+
pattern string
261+
replacement string
262+
}
263+
264+
func crawlJson(data interface{}, strHandler func(interface{}) interface{}) interface{} {
265+
switch value := data.(type) {
266+
case string:
267+
if strHandler != nil {
268+
return strHandler(data)
269+
}
270+
case []interface{}:
271+
for i := range value {
272+
value[i] = crawlJson(value[i], strHandler)
273+
}
274+
case map[string]interface{}:
275+
for k := range value {
276+
value[k] = crawlJson(value[k], strHandler)
277+
}
278+
default:
279+
}
280+
return data
281+
}

cmd/fetchd/cmd/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) {
130130
// AddStakeReconciliationMigrateCmd(),
131131
genutilcli.GenTxCmd(app.ModuleBasics, encodingConfig.TxConfig, banktypes.GenesisBalancesIterator{}, app.DefaultNodeHome),
132132
genutilcli.ValidateGenesisCmd(app.ModuleBasics),
133+
ASIGenesisUpgradeCmd(app.DefaultNodeHome),
133134
AddGenesisAccountCmd(app.DefaultNodeHome),
134135
AddGenesisDelegationCmd(app.DefaultNodeHome),
135136
ReplaceGenesisValuesCmd(app.DefaultNodeHome),

0 commit comments

Comments
 (0)