Skip to content

Commit 9b53aab

Browse files
committed
feat: minitia launch flows
1 parent 5a0854c commit 9b53aab

File tree

2 files changed

+355
-13
lines changed

2 files changed

+355
-13
lines changed

models/minitia/launch.go

+338-9
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func (m *ExistingMinitiaChecker) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
5555
m.loading = loader
5656
if m.loading.Completing {
5757
if !m.state.existingMinitiaApp {
58-
// TODO: Continue
58+
return NewNetworkSelect(m.state), nil
5959
} else {
6060
return NewDeleteExistingMinitiaInput(m.state), nil
6161
}
@@ -64,7 +64,8 @@ func (m *ExistingMinitiaChecker) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
6464
}
6565

6666
func (m *ExistingMinitiaChecker) View() string {
67-
return styles.Text("🪢 For launching Minitia, once all required configurations are complete, \nit will run for a few blocks to set up neccesary components.\nPlease note that this may take a moment, and your patience is appreciated!\n\n", styles.Ivory) + m.loading.View()
67+
return styles.Text("🪢 For launching Minitia, once all required configurations are complete, \nit will run for a few blocks to set up neccesary components.\nPlease note that this may take a moment, and your patience is appreciated!\n\n", styles.Ivory) +
68+
m.loading.View()
6869
}
6970

7071
type DeleteExistingMinitiaInput struct {
@@ -96,7 +97,7 @@ func (m *DeleteExistingMinitiaInput) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
9697
input, cmd, done := m.TextInput.Update(msg)
9798
if done {
9899
// TODO: Delete .minitia folder
99-
return NewExistingAppReplaceSelect(m.state), nil
100+
return NewNetworkSelect(m.state), nil
100101
}
101102
m.TextInput = input
102103
return m, cmd
@@ -121,14 +122,14 @@ var (
121122
Mainnet NetworkSelectOption = ""
122123
)
123124

124-
func NewExistingAppReplaceSelect(state *LaunchState) *NetworkSelect {
125+
func NewNetworkSelect(state *LaunchState) *NetworkSelect {
125126
Testnet = NetworkSelectOption(fmt.Sprintf("Testnet (%s)", utils.GetConfig("constants.chain_id.testnet")))
126127
Mainnet = NetworkSelectOption(fmt.Sprintf("Mainnet (%s)", utils.GetConfig("constants.chain_id.mainnet")))
127128
return &NetworkSelect{
128129
Selector: utils.Selector[NetworkSelectOption]{
129130
Options: []NetworkSelectOption{
130131
Testnet,
131-
Mainnet,
132+
//Mainnet,
132133
},
133134
},
134135
state: state,
@@ -156,7 +157,8 @@ func (m *NetworkSelect) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
156157
}
157158

158159
func (m *NetworkSelect) View() string {
159-
return m.state.weave.Render() + styles.RenderPrompt(
160+
return styles.Text("🪢 For launching Minitia, once all required configurations are complete, \nit will run for a few blocks to set up neccesary components.\nPlease note that this may take a moment, and your patience is appreciated!\n\n", styles.Ivory) +
161+
m.state.weave.Render() + styles.RenderPrompt(
160162
m.GetQuestion(),
161163
[]string{"Initia L1 network"},
162164
styles.Question,
@@ -248,9 +250,10 @@ func (m *VersionSelect) Init() tea.Cmd {
248250
func (m *VersionSelect) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
249251
selected, cmd := m.Select(msg)
250252
if selected != nil {
251-
// TODO: Set the selected version
252-
m.state.weave.PushPreviousResponse(styles.RenderPreviousResponse(styles.DotsSeparator, m.GetQuestion(), []string{"minitiad version"}, ""))
253-
return m, nil
253+
m.state.minitiadVersion = *selected
254+
m.state.minitiadEndpoint = m.versions[*selected]
255+
m.state.weave.PushPreviousResponse(styles.RenderPreviousResponse(styles.DotsSeparator, m.GetQuestion(), []string{"minitiad version"}, *selected))
256+
return NewChainIdInput(m.state), nil
254257
}
255258

256259
return m, cmd
@@ -259,3 +262,329 @@ func (m *VersionSelect) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
259262
func (m *VersionSelect) View() string {
260263
return m.state.weave.Render() + styles.RenderPrompt(m.GetQuestion(), []string{"minitiad version"}, styles.Question) + m.Selector.View()
261264
}
265+
266+
type ChainIdInput struct {
267+
utils.TextInput
268+
state *LaunchState
269+
question string
270+
}
271+
272+
func NewChainIdInput(state *LaunchState) *ChainIdInput {
273+
model := &ChainIdInput{
274+
TextInput: utils.NewTextInput(),
275+
state: state,
276+
question: "Please specify the L2 chain id",
277+
}
278+
model.WithPlaceholder("Enter in alphanumeric format")
279+
return model
280+
}
281+
282+
func (m *ChainIdInput) GetQuestion() string {
283+
return m.question
284+
}
285+
286+
func (m *ChainIdInput) Init() tea.Cmd {
287+
return nil
288+
}
289+
290+
func (m *ChainIdInput) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
291+
input, cmd, done := m.TextInput.Update(msg)
292+
if done {
293+
m.state.chainId = input.Text
294+
m.state.weave.PushPreviousResponse(styles.RenderPreviousResponse(styles.DotsSeparator, m.GetQuestion(), []string{"L2 chain id"}, input.Text))
295+
return NewGasDenomInput(m.state), nil
296+
}
297+
m.TextInput = input
298+
return m, cmd
299+
}
300+
301+
func (m *ChainIdInput) View() string {
302+
return m.state.weave.Render() + styles.RenderPrompt(m.GetQuestion(), []string{"L2 chain id"}, styles.Question) + m.TextInput.View()
303+
}
304+
305+
type GasDenomInput struct {
306+
utils.TextInput
307+
state *LaunchState
308+
question string
309+
}
310+
311+
func NewGasDenomInput(state *LaunchState) *GasDenomInput {
312+
model := &GasDenomInput{
313+
TextInput: utils.NewTextInput(),
314+
state: state,
315+
question: "Please specify the L2 Gas Token Denom",
316+
}
317+
model.WithPlaceholder("Enter the denom")
318+
return model
319+
}
320+
321+
func (m *GasDenomInput) GetQuestion() string {
322+
return m.question
323+
}
324+
325+
func (m *GasDenomInput) Init() tea.Cmd {
326+
return nil
327+
}
328+
329+
func (m *GasDenomInput) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
330+
input, cmd, done := m.TextInput.Update(msg)
331+
if done {
332+
m.state.gasDenom = input.Text
333+
m.state.weave.PushPreviousResponse(styles.RenderPreviousResponse(styles.DotsSeparator, m.GetQuestion(), []string{"L2 Gas Token Denom"}, input.Text))
334+
return NewMonikerInput(m.state), nil
335+
}
336+
m.TextInput = input
337+
return m, cmd
338+
}
339+
340+
func (m *GasDenomInput) View() string {
341+
return m.state.weave.Render() + styles.RenderPrompt(m.GetQuestion(), []string{"L2 Gas Token Denom"}, styles.Question) + m.TextInput.View()
342+
}
343+
344+
type MonikerInput struct {
345+
utils.TextInput
346+
state *LaunchState
347+
question string
348+
}
349+
350+
func NewMonikerInput(state *LaunchState) *MonikerInput {
351+
model := &MonikerInput{
352+
TextInput: utils.NewTextInput(),
353+
state: state,
354+
question: "Please specify the moniker",
355+
}
356+
model.WithPlaceholder("Enter the moniker")
357+
return model
358+
}
359+
360+
func (m *MonikerInput) GetQuestion() string {
361+
return m.question
362+
}
363+
364+
func (m *MonikerInput) Init() tea.Cmd {
365+
return nil
366+
}
367+
368+
func (m *MonikerInput) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
369+
input, cmd, done := m.TextInput.Update(msg)
370+
if done {
371+
m.state.moniker = input.Text
372+
m.state.weave.PushPreviousResponse(styles.RenderPreviousResponse(styles.DotsSeparator, m.GetQuestion(), []string{"moniker"}, input.Text))
373+
return NewAddGenesisAccountsSelect(false, m.state), nil
374+
}
375+
m.TextInput = input
376+
return m, cmd
377+
}
378+
379+
func (m *MonikerInput) View() string {
380+
return m.state.weave.Render() + styles.RenderPrompt(m.GetQuestion(), []string{"moniker"}, styles.Question) + m.TextInput.View()
381+
}
382+
383+
type AddGenesisAccountsSelect struct {
384+
utils.Selector[AddGenesisAccountsOption]
385+
state *LaunchState
386+
recurring bool
387+
firstTimeQuestion string
388+
recurringQuestion string
389+
}
390+
391+
type AddGenesisAccountsOption string
392+
393+
const (
394+
Yes AddGenesisAccountsOption = "Yes"
395+
No AddGenesisAccountsOption = "No"
396+
)
397+
398+
func NewAddGenesisAccountsSelect(recurring bool, state *LaunchState) *AddGenesisAccountsSelect {
399+
if !recurring {
400+
state.preGenesisAccountsResponsesCount = len(state.weave.PreviousResponse)
401+
}
402+
return &AddGenesisAccountsSelect{
403+
Selector: utils.Selector[AddGenesisAccountsOption]{
404+
Options: []AddGenesisAccountsOption{
405+
Yes,
406+
No,
407+
},
408+
},
409+
state: state,
410+
recurring: recurring,
411+
firstTimeQuestion: "Would you like to add genesis accounts?",
412+
recurringQuestion: "Would you like to add another genesis account?",
413+
}
414+
}
415+
416+
func (m *AddGenesisAccountsSelect) GetQuestionAndHighlight() (string, string) {
417+
if m.recurring {
418+
return m.recurringQuestion, "genesis account"
419+
}
420+
return m.firstTimeQuestion, "genesis accounts"
421+
}
422+
423+
func (m *AddGenesisAccountsSelect) Init() tea.Cmd {
424+
return nil
425+
}
426+
427+
func (m *AddGenesisAccountsSelect) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
428+
selected, cmd := m.Select(msg)
429+
if selected != nil {
430+
switch *selected {
431+
case Yes:
432+
question, highlight := m.GetQuestionAndHighlight()
433+
m.state.weave.PushPreviousResponse(styles.RenderPreviousResponse(styles.ArrowSeparator, question, []string{highlight}, string(*selected)))
434+
return NewGenesisAccountsAddressInput(m.state), nil
435+
case No:
436+
question := m.firstTimeQuestion
437+
highlight := "genesis accounts"
438+
if len(m.state.genesisAccounts) > 0 {
439+
m.state.weave.PreviousResponse = m.state.weave.PreviousResponse[:m.state.preGenesisAccountsResponsesCount]
440+
m.state.weave.PushPreviousResponse(styles.RenderPreviousResponse(styles.ArrowSeparator, question, []string{highlight}, string(Yes)))
441+
currentResponse := " List of the Genesis Accounts\n"
442+
for _, account := range m.state.genesisAccounts {
443+
currentResponse += styles.Text(fmt.Sprintf(" %s\tInitial Balance: %s\n", account.address, account.balance), styles.Gray)
444+
}
445+
m.state.weave.PushPreviousResponse(currentResponse)
446+
} else {
447+
m.state.weave.PushPreviousResponse(styles.RenderPreviousResponse(styles.ArrowSeparator, question, []string{highlight}, string(No)))
448+
}
449+
return NewOpBridgeSubmissionIntervalInput(m.state), nil
450+
}
451+
}
452+
453+
return m, cmd
454+
}
455+
456+
func (m *AddGenesisAccountsSelect) View() string {
457+
preText := ""
458+
if !m.recurring {
459+
preText += "\n" + styles.RenderPrompt("You can add genesis accounts by first entering the addresses, then assigning the initial balance one by one.", []string{"genesis accounts"}, styles.Information) + "\n"
460+
}
461+
question, highlight := m.GetQuestionAndHighlight()
462+
return m.state.weave.Render() + preText + styles.RenderPrompt(
463+
question,
464+
[]string{highlight},
465+
styles.Question,
466+
) + m.Selector.View()
467+
}
468+
469+
type GenesisAccountsAddressInput struct {
470+
utils.TextInput
471+
state *LaunchState
472+
question string
473+
}
474+
475+
func NewGenesisAccountsAddressInput(state *LaunchState) *GenesisAccountsAddressInput {
476+
model := &GenesisAccountsAddressInput{
477+
TextInput: utils.NewTextInput(),
478+
state: state,
479+
question: "Please specify genesis account address",
480+
}
481+
model.WithPlaceholder("Enter the address")
482+
return model
483+
}
484+
485+
func (m *GenesisAccountsAddressInput) GetQuestion() string {
486+
return m.question
487+
}
488+
489+
func (m *GenesisAccountsAddressInput) Init() tea.Cmd {
490+
return nil
491+
}
492+
493+
func (m *GenesisAccountsAddressInput) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
494+
input, cmd, done := m.TextInput.Update(msg)
495+
if done {
496+
m.state.weave.PushPreviousResponse(styles.RenderPreviousResponse(styles.DotsSeparator, m.GetQuestion(), []string{"genesis account address"}, input.Text))
497+
return NewGenesisAccountsBalanceInput(input.Text, m.state), nil
498+
}
499+
m.TextInput = input
500+
return m, cmd
501+
}
502+
503+
func (m *GenesisAccountsAddressInput) View() string {
504+
return m.state.weave.Render() + styles.RenderPrompt(m.GetQuestion(), []string{"moniker"}, styles.Question) + m.TextInput.View()
505+
}
506+
507+
type GenesisAccountsBalanceInput struct {
508+
utils.TextInput
509+
state *LaunchState
510+
address string
511+
question string
512+
}
513+
514+
func NewGenesisAccountsBalanceInput(address string, state *LaunchState) *GenesisAccountsBalanceInput {
515+
model := &GenesisAccountsBalanceInput{
516+
TextInput: utils.NewTextInput(),
517+
state: state,
518+
address: address,
519+
question: fmt.Sprintf("Please specify initial balance for %s (%s)", address, state.gasDenom),
520+
}
521+
model.WithPlaceholder("Enter the desired balance")
522+
// TODO: Maybe Coin validate here
523+
return model
524+
}
525+
526+
func (m *GenesisAccountsBalanceInput) GetQuestion() string {
527+
return m.question
528+
}
529+
530+
func (m *GenesisAccountsBalanceInput) Init() tea.Cmd {
531+
return nil
532+
}
533+
534+
func (m *GenesisAccountsBalanceInput) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
535+
input, cmd, done := m.TextInput.Update(msg)
536+
if done {
537+
m.state.genesisAccounts = append(m.state.genesisAccounts, GenesisAccount{
538+
address: m.address,
539+
balance: input.Text,
540+
})
541+
m.state.weave.PushPreviousResponse(styles.RenderPreviousResponse(styles.DotsSeparator, m.GetQuestion(), []string{m.address}, input.Text))
542+
return NewAddGenesisAccountsSelect(true, m.state), nil
543+
}
544+
m.TextInput = input
545+
return m, cmd
546+
}
547+
548+
func (m *GenesisAccountsBalanceInput) View() string {
549+
return m.state.weave.Render() + styles.RenderPrompt(m.GetQuestion(), []string{m.address}, styles.Question) + m.TextInput.View()
550+
}
551+
552+
type OpBridgeSubmissionIntervalInput struct {
553+
utils.TextInput
554+
state *LaunchState
555+
question string
556+
}
557+
558+
func NewOpBridgeSubmissionIntervalInput(state *LaunchState) *OpBridgeSubmissionIntervalInput {
559+
model := &OpBridgeSubmissionIntervalInput{
560+
TextInput: utils.NewTextInput(),
561+
state: state,
562+
question: "Please specify OP bridge config: Submission Interval (format m, h or d - ex. 1m, 23h, 7d)",
563+
}
564+
model.WithPlaceholder("Press tab to use “1m”")
565+
return model
566+
}
567+
568+
func (m *OpBridgeSubmissionIntervalInput) GetQuestion() string {
569+
return m.question
570+
}
571+
572+
func (m *OpBridgeSubmissionIntervalInput) Init() tea.Cmd {
573+
return nil
574+
}
575+
576+
func (m *OpBridgeSubmissionIntervalInput) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
577+
input, cmd, done := m.TextInput.Update(msg)
578+
if done {
579+
// TODO: Continue flow
580+
m.state.opBridgeSubmissionInterval = input.Text
581+
m.state.weave.PushPreviousResponse(styles.RenderPreviousResponse(styles.DotsSeparator, m.GetQuestion(), []string{"Submission Interval"}, input.Text))
582+
return m, tea.Quit
583+
}
584+
m.TextInput = input
585+
return m, cmd
586+
}
587+
588+
func (m *OpBridgeSubmissionIntervalInput) View() string {
589+
return m.state.weave.Render() + styles.RenderPrompt(m.GetQuestion(), []string{"Submission Interval"}, styles.Question) + m.TextInput.View()
590+
}

0 commit comments

Comments
 (0)