/
scaffold_message.go
149 lines (115 loc) · 4.65 KB
/
scaffold_message.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package ignitecmd
import (
"github.com/spf13/cobra"
"github.com/ignite/cli/v29/ignite/pkg/cliui"
"github.com/ignite/cli/v29/ignite/services/scaffolder"
)
const flagSigner = "signer"
// NewScaffoldMessage returns the command to scaffold messages.
func NewScaffoldMessage() *cobra.Command {
c := &cobra.Command{
Use: "message [name] [field1:type1] [field2:type2] ...",
Short: "Message to perform state transition on the blockchain",
Long: `Message scaffolding is useful for quickly adding functionality to your
blockchain to handle specific Cosmos SDK messages.
Messages are objects whose end goal is to trigger state transitions on the
blockchain. A message is a container for fields of data that affect how the
blockchain's state will change. You can think of messages as "actions" that a
user can perform.
For example, the bank module has a "Send" message for token transfers between
accounts. The send message has three fields: from address (sender), to address
(recipient), and a token amount. When this message is successfully processed,
the token amount will be deducted from the sender's account and added to the
recipient's account.
Ignite's message scaffolding lets you create new types of messages and add them
to your chain. For example:
ignite scaffold message add-pool amount:coins denom active:bool --module dex
The command above will create a new message MsgAddPool with three fields: amount
(in tokens), denom (a string), and active (a boolean). The message will be added
to the "dex" module.
For detailed type information use ignite scaffold type --help
By default, the message is defined as a proto message in the
"proto/{app}/{module}/tx.proto" and registered in the "Msg" service. A CLI command to
create and broadcast a transaction with MsgAddPool is created in the module's
"cli" package. Additionally, Ignite scaffolds a message constructor and the code
to satisfy the sdk.Msg interface and register the message in the module.
Most importantly in the "keeper" package Ignite scaffolds an "AddPool" function.
Inside this function, you can implement message handling logic.
When successfully processed a message can return data. Use the —response flag to
specify response fields and their types. For example
ignite scaffold message create-post title body --response id:int,title
The command above will scaffold MsgCreatePost which returns both an ID (an
integer) and a title (a string).
Message scaffolding follows the rules as "ignite scaffold list/map/single" and
supports fields with standard and custom types. See "ignite scaffold list —help"
for details.
`,
Args: cobra.MinimumNArgs(1),
PreRunE: migrationPreRunHandler,
RunE: messageHandler,
}
flagSetPath(c)
flagSetClearCache(c)
c.Flags().AddFlagSet(flagSetYes())
c.Flags().String(flagModule, "", "module to add the message into. Default: app's main module")
c.Flags().StringSliceP(flagResponse, "r", []string{}, "response fields")
c.Flags().Bool(flagNoSimulation, false, "disable CRUD simulation scaffolding")
c.Flags().StringP(flagDescription, "d", "", "description of the command")
c.Flags().String(flagSigner, "", "label for the message signer (default: creator)")
return c
}
func messageHandler(cmd *cobra.Command, args []string) error {
var (
module, _ = cmd.Flags().GetString(flagModule)
resFields, _ = cmd.Flags().GetStringSlice(flagResponse)
desc, _ = cmd.Flags().GetString(flagDescription)
signer = flagGetSigner(cmd)
appPath = flagGetPath(cmd)
withoutSimulation = flagGetNoSimulation(cmd)
)
session := cliui.New(cliui.StartSpinnerWithText(statusScaffolding))
defer session.End()
cfg, _, err := getChainConfig(cmd)
if err != nil {
return err
}
cacheStorage, err := newCache(cmd)
if err != nil {
return err
}
var options []scaffolder.MessageOption
// Get description
if desc != "" {
options = append(options, scaffolder.WithDescription(desc))
}
// Get signer
if signer != "" {
options = append(options, scaffolder.WithSigner(signer))
}
// Skip scaffold simulation
if withoutSimulation {
options = append(options, scaffolder.WithoutSimulation())
}
sc, err := scaffolder.New(cmd.Context(), appPath, cfg.Build.Proto.Path)
if err != nil {
return err
}
err = sc.AddMessage(cmd.Context(), module, args[0], args[1:], resFields, options...)
if err != nil {
return err
}
sm, err := sc.ApplyModifications()
if err != nil {
return err
}
if err := sc.PostScaffold(cmd.Context(), cacheStorage, false); err != nil {
return err
}
modificationsStr, err := sm.String()
if err != nil {
return err
}
session.Println(modificationsStr)
session.Printf("\n🎉 Created a message `%[1]v`.\n\n", args[0])
return nil
}