Skip to content

Commit d026d8a

Browse files
committed
fixes
1 parent 5b92b16 commit d026d8a

File tree

10 files changed

+491
-186
lines changed

10 files changed

+491
-186
lines changed

cmd/push-validator/cmd_register.go

Lines changed: 212 additions & 105 deletions
Large diffs are not rendered by default.

cmd/push-validator/cmd_register_core_test.go

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212

1313
// Tests for runRegisterValidatorWithDeps covering the full registration flow.
1414

15-
func TestRunRegisterValidatorWithDeps_NodeSyncing_JSON(t *testing.T) {
15+
func TestHandleRegisterValidator_NodeSyncing_JSON(t *testing.T) {
1616
origOutput := flagOutput
1717
origNonInteractive := flagNonInteractive
1818
defer func() {
@@ -27,7 +27,7 @@ func TestRunRegisterValidatorWithDeps_NodeSyncing_JSON(t *testing.T) {
2727
d.RemoteNode = &mockNodeClient{}
2828
})
2929

30-
err := runRegisterValidatorWithDeps(d, d.Cfg, "myval", "mykey", "1500000000000000000", "0.10", "")
30+
err := handleRegisterValidator(d)
3131
if err == nil {
3232
t.Fatal("expected error")
3333
}
@@ -36,7 +36,7 @@ func TestRunRegisterValidatorWithDeps_NodeSyncing_JSON(t *testing.T) {
3636
}
3737
}
3838

39-
func TestRunRegisterValidatorWithDeps_NodeSyncing_Text(t *testing.T) {
39+
func TestHandleRegisterValidator_NodeSyncing_Text(t *testing.T) {
4040
origOutput := flagOutput
4141
origNonInteractive := flagNonInteractive
4242
origNoColor := flagNoColor
@@ -57,7 +57,7 @@ func TestRunRegisterValidatorWithDeps_NodeSyncing_Text(t *testing.T) {
5757
d.RemoteNode = &mockNodeClient{}
5858
})
5959

60-
err := runRegisterValidatorWithDeps(d, d.Cfg, "myval", "mykey", "1500000000000000000", "0.10", "")
60+
err := handleRegisterValidator(d)
6161
if err == nil {
6262
t.Fatal("expected error")
6363
}
@@ -295,12 +295,10 @@ func TestRunRegisterValidatorWithDeps_RegistrationError_ValidatorAlreadyExists(t
295295
}
296296
})
297297

298+
// "validator already exist" is now treated as success (validator is already registered)
298299
err := runRegisterValidatorWithDeps(d, d.Cfg, "myval", "mykey", "1500000000000000000", "0.10", "")
299-
if err == nil {
300-
t.Fatal("expected error")
301-
}
302-
if !containsSubstr(err.Error(), "validator registration failed") {
303-
t.Errorf("unexpected error: %v", err)
300+
if err != nil {
301+
t.Fatalf("expected nil (validator already registered treated as success), got: %v", err)
304302
}
305303
}
306304

@@ -676,3 +674,67 @@ func (m *balanceRetryMockValidator) ImportKey(ctx context.Context, name string,
676674
func (m *balanceRetryMockValidator) GetEVMAddress(ctx context.Context, addr string) (string, error) {
677675
return m.inner.GetEVMAddress(ctx, addr)
678676
}
677+
678+
func (m *balanceRetryMockValidator) IsAddressValidator(ctx context.Context, cosmosAddr string) (bool, error) {
679+
return m.inner.IsAddressValidator(ctx, cosmosAddr)
680+
}
681+
682+
func TestRunRegisterValidatorWithDeps_ValidatorAlreadyExists_ReturnsSuccess(t *testing.T) {
683+
origOutput := flagOutput
684+
origNonInteractive := flagNonInteractive
685+
origNoColor := flagNoColor
686+
origNoEmoji := flagNoEmoji
687+
defer func() {
688+
flagOutput = origOutput
689+
flagNonInteractive = origNonInteractive
690+
flagNoColor = origNoColor
691+
flagNoEmoji = origNoEmoji
692+
}()
693+
flagOutput = "text"
694+
flagNonInteractive = true
695+
flagNoColor = true
696+
flagNoEmoji = true
697+
698+
d := registerDeps(func(d *Deps) {
699+
d.Node = &mockNodeClient{status: node.Status{CatchingUp: false}}
700+
d.RemoteNode = &mockNodeClient{}
701+
d.Validator = &mockValidator{
702+
importKeyResult: validator.KeyInfo{Name: "mykey", Address: "push1test"},
703+
balanceResult: "2000000000000000000",
704+
registerErr: fmt.Errorf("validator already exist"),
705+
evmAddrResult: "0xABCD",
706+
}
707+
})
708+
709+
err := runRegisterValidatorWithDeps(d, d.Cfg, "myval", "mykey", "1500000000000000000", "0.10", "word1 word2 word3 word4 word5 word6 word7 word8 word9 word10 word11 word12")
710+
if err != nil {
711+
t.Fatalf("expected nil (validator already registered treated as success), got: %v", err)
712+
}
713+
}
714+
715+
func TestRunRegisterValidatorWithDeps_ValidatorAlreadyExists_JSON(t *testing.T) {
716+
origOutput := flagOutput
717+
origNonInteractive := flagNonInteractive
718+
defer func() {
719+
flagOutput = origOutput
720+
flagNonInteractive = origNonInteractive
721+
}()
722+
flagOutput = "json"
723+
flagNonInteractive = true
724+
725+
d := registerDeps(func(d *Deps) {
726+
d.Node = &mockNodeClient{status: node.Status{CatchingUp: false}}
727+
d.RemoteNode = &mockNodeClient{}
728+
d.Validator = &mockValidator{
729+
importKeyResult: validator.KeyInfo{Name: "mykey", Address: "push1test"},
730+
balanceResult: "2000000000000000000",
731+
registerErr: fmt.Errorf("validator already exist"),
732+
evmAddrResult: "0xABCD",
733+
}
734+
})
735+
736+
err := runRegisterValidatorWithDeps(d, d.Cfg, "myval", "mykey", "1500000000000000000", "0.10", "word1 word2 word3 word4 word5 word6 word7 word8 word9 word10 word11 word12")
737+
if err != nil {
738+
t.Fatalf("expected nil (validator already registered treated as success), got: %v", err)
739+
}
740+
}

cmd/push-validator/cmd_register_prompt_test.go

Lines changed: 28 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -23,34 +23,37 @@ func TestPromptCommissionRate_ValidInput(t *testing.T) {
2323
}
2424

2525
func TestPromptCommissionRate_InvalidInput(t *testing.T) {
26-
p := &mockPrompter{responses: []string{"abc"}}
26+
// Invalid input, then empty → falls back to default
27+
p := &mockPrompter{responses: []string{"abc", ""}, interactive: true}
2728
rate := promptCommissionRate(p, "0.10")
2829
if rate != "0.10" {
2930
t.Errorf("expected default 0.10, got %s", rate)
3031
}
3132
}
3233

3334
func TestPromptCommissionRate_TooHigh(t *testing.T) {
34-
p := &mockPrompter{responses: []string{"150"}}
35+
// Too high, then empty → falls back to default
36+
p := &mockPrompter{responses: []string{"150", ""}, interactive: true}
3537
rate := promptCommissionRate(p, "0.10")
3638
if rate != "0.10" {
3739
t.Errorf("expected default 0.10 for >100, got %s", rate)
3840
}
3941
}
4042

4143
func TestPromptCommissionRate_TooLow(t *testing.T) {
42-
p := &mockPrompter{responses: []string{"0"}}
44+
// Too low, then empty → falls back to default
45+
p := &mockPrompter{responses: []string{"4", ""}, interactive: true}
4346
rate := promptCommissionRate(p, "0.10")
4447
if rate != "0.10" {
45-
t.Errorf("expected default 0.10 for <1, got %s", rate)
48+
t.Errorf("expected default 0.10 for <5, got %s", rate)
4649
}
4750
}
4851

4952
func TestPromptCommissionRate_BoundaryValues(t *testing.T) {
50-
p := &mockPrompter{responses: []string{"1"}}
53+
p := &mockPrompter{responses: []string{"5"}}
5154
rate := promptCommissionRate(p, "0.10")
52-
if rate != "0.01" {
53-
t.Errorf("expected 0.01 for 1%%, got %s", rate)
55+
if rate != "0.05" {
56+
t.Errorf("expected 0.05 for 5%%, got %s", rate)
5457
}
5558

5659
p = &mockPrompter{responses: []string{"100"}}
@@ -234,12 +237,11 @@ func TestCollectRegistrationInputs_DefaultValues(t *testing.T) {
234237
CommissionRate: "0.10",
235238
}
236239

240+
// Response 0: wallet choice → "" (default = create new)
241+
// Response 1: key name prompt → "" (use default)
237242
// Moniker prompt is skipped (not "" or "push-validator")
238-
// Response 0: key name prompt → "" (use default)
239-
// Response 1: wallet choice → "" (default = create new)
240-
// Response 2: commission rate → "" (use default 0.10)
241243
d.Prompter = &mockPrompter{
242-
responses: []string{"", "", ""},
244+
responses: []string{"", ""},
243245
interactive: true,
244246
}
245247

@@ -253,9 +255,6 @@ func TestCollectRegistrationInputs_DefaultValues(t *testing.T) {
253255
if result.KeyName != "my-key" {
254256
t.Errorf("expected keyName my-key, got %s", result.KeyName)
255257
}
256-
if result.CommissionRate != "0.10" {
257-
t.Errorf("expected rate 0.10, got %s", result.CommissionRate)
258-
}
259258
}
260259

261260
func TestCollectRegistrationInputs_CustomValues(t *testing.T) {
@@ -275,13 +274,12 @@ func TestCollectRegistrationInputs_CustomValues(t *testing.T) {
275274
CommissionRate: "0.10",
276275
}
277276

278-
// Moniker IS "push-validator" so moniker prompt fires
279-
// Response 0: moniker → "custom-moniker"
277+
// Response 0: wallet choice → "" (default = create new)
280278
// Response 1: key name → "custom-key"
281-
// Response 2: wallet choice → "" (default = create new)
282-
// Response 3: commission rate → "20"
279+
// Moniker IS "push-validator" so moniker prompt fires
280+
// Response 2: moniker → "custom-moniker"
283281
d.Prompter = &mockPrompter{
284-
responses: []string{"custom-moniker", "custom-key", "", "20"},
282+
responses: []string{"", "custom-key", "custom-moniker"},
285283
interactive: true,
286284
}
287285

@@ -295,9 +293,6 @@ func TestCollectRegistrationInputs_CustomValues(t *testing.T) {
295293
if result.KeyName != "custom-key" {
296294
t.Errorf("expected custom-key, got %s", result.KeyName)
297295
}
298-
if result.CommissionRate != "0.20" {
299-
t.Errorf("expected 0.20, got %s", result.CommissionRate)
300-
}
301296
}
302297

303298
func TestCollectRegistrationInputs_KeyExists_UseExisting(t *testing.T) {
@@ -324,9 +319,9 @@ func TestCollectRegistrationInputs_KeyExists_UseExisting(t *testing.T) {
324319
runner.outputs[binPath+" keys show my-key -a --keyring-backend "+cfg.KeyringBackend+" --home "+cfg.HomeDir] = []byte("push1existing\n")
325320
d.Runner = runner
326321

327-
// Response 0: key name → "" (use default "my-key" which exists)
328-
// Key exists branch: Response 1: enter different name → "" (use existing)
329-
// Response 2: commission rate → ""
322+
// Response 0: wallet choice → "" (create new)
323+
// Response 1: key name → "" (use default "my-key" which exists)
324+
// Key exists branch: Response 2: enter different name → "" (use existing)
330325
d.Prompter = &mockPrompter{
331326
responses: []string{"", "", ""},
332327
interactive: true,
@@ -370,13 +365,11 @@ func TestCollectRegistrationInputs_KeyExists_EnterNewName(t *testing.T) {
370365
runner.errors[binPath+" keys show new-key -a --keyring-backend "+cfg.KeyringBackend+" --home "+cfg.HomeDir] = errMock
371366
d.Runner = runner
372367

373-
// Response 0: key name → "" (use default "existing-key" which exists)
374-
// Key exists: Response 1: enter different name → "new-key"
375-
// new-key doesn't exist, so wallet choice fires
376-
// Response 2: wallet choice → "" (create new)
377-
// Response 3: commission rate → "15"
368+
// Response 0: wallet choice → "" (create new)
369+
// Response 1: key name → "" (use default "existing-key" which exists)
370+
// Key exists: Response 2: enter different name → "new-key"
378371
d.Prompter = &mockPrompter{
379-
responses: []string{"", "new-key", "", "15"},
372+
responses: []string{"", "", "new-key"},
380373
interactive: true,
381374
}
382375

@@ -387,9 +380,6 @@ func TestCollectRegistrationInputs_KeyExists_EnterNewName(t *testing.T) {
387380
if result.KeyName != "new-key" {
388381
t.Errorf("expected new-key, got %s", result.KeyName)
389382
}
390-
if result.CommissionRate != "0.15" {
391-
t.Errorf("expected 0.15, got %s", result.CommissionRate)
392-
}
393383
}
394384

395385
func TestCollectRegistrationInputs_KeyExists_NewNameAlsoExists(t *testing.T) {
@@ -417,12 +407,11 @@ func TestCollectRegistrationInputs_KeyExists_NewNameAlsoExists(t *testing.T) {
417407
runner.outputs[binPath+" keys show also-exists -a --keyring-backend "+cfg.KeyringBackend+" --home "+cfg.HomeDir] = []byte("push1b\n")
418408
d.Runner = runner
419409

420-
// Response 0: key name → "" (use default which exists)
421-
// Key exists: Response 1: enter different name → "also-exists" (also exists)
422-
// Since new key also exists, wallet choice NOT called
423-
// Response 2: commission rate → ""
410+
// Response 0: wallet choice → "" (create new)
411+
// Response 1: key name → "" (use default which exists)
412+
// Key exists: Response 2: enter different name → "also-exists" (also exists)
424413
d.Prompter = &mockPrompter{
425-
responses: []string{"", "also-exists", ""},
414+
responses: []string{"", "", "also-exists"},
426415
interactive: true,
427416
}
428417

cmd/push-validator/cmd_reset.go

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -135,28 +135,7 @@ func handleFullReset(cfg config.Config, sup process.Supervisor, prompters ...Pro
135135
prompter = &ttyPrompter{}
136136
}
137137

138-
// Stop node first and verify it stopped
139-
if sup.IsRunning() {
140-
if flagOutput != "json" {
141-
fmt.Println(p.Colors.Info("Stopping node..."))
142-
}
143-
if err := sup.Stop(); err != nil {
144-
if flagOutput == "json" {
145-
p.JSON(map[string]any{"ok": false, "error": fmt.Sprintf("failed to stop node: %v", err)})
146-
return err
147-
} else {
148-
p.Warn(p.Colors.Emoji("⚠") + fmt.Sprintf(" Could not stop node: %v", err))
149-
response, pErr := prompter.ReadLine("Continue with full reset anyway? (y/N): ")
150-
if pErr != nil || strings.ToLower(strings.TrimSpace(response)) != "y" {
151-
p.Info("Full reset cancelled")
152-
return nil
153-
}
154-
}
155-
} else if flagOutput != "json" {
156-
p.Success("✓ Node stopped")
157-
}
158-
}
159-
138+
// Require confirmation before stopping or modifying anything
160139
if flagOutput != "json" {
161140
fmt.Println()
162141
fmt.Println(p.Colors.Warning(p.Colors.Emoji("⚠️") + " FULL RESET - This will delete EVERYTHING"))
@@ -184,6 +163,28 @@ func handleFullReset(cfg config.Config, sup process.Supervisor, prompters ...Pro
184163
}
185164
}
186165

166+
// Stop node after confirmation
167+
if sup.IsRunning() {
168+
if flagOutput != "json" {
169+
fmt.Println(p.Colors.Info("Stopping node..."))
170+
}
171+
if err := sup.Stop(); err != nil {
172+
if flagOutput == "json" {
173+
p.JSON(map[string]any{"ok": false, "error": fmt.Sprintf("failed to stop node: %v", err)})
174+
return err
175+
} else {
176+
p.Warn(p.Colors.Emoji("⚠") + fmt.Sprintf(" Could not stop node: %v", err))
177+
response, pErr := prompter.ReadLine("Continue with full reset anyway? (y/N): ")
178+
if pErr != nil || strings.ToLower(strings.TrimSpace(response)) != "y" {
179+
p.Info("Full reset cancelled")
180+
return nil
181+
}
182+
}
183+
} else if flagOutput != "json" {
184+
p.Success("✓ Node stopped")
185+
}
186+
}
187+
187188
// Perform full reset
188189
err := admin.FullReset(admin.FullResetOptions{
189190
HomeDir: cfg.HomeDir,

cmd/push-validator/cmd_start.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,9 @@ func createSnapshotProgressCallback(output string) snapshot.ProgressFunc {
559559
message = message[:57] + "..."
560560
}
561561
fmt.Printf("\r → Extracting: %-60s", message)
562+
if current == total && total > 0 {
563+
fmt.Println()
564+
}
562565
}
563566
}
564567
}

cmd/push-validator/helpers_balance_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,7 @@ func (m *balanceIncrementingValidator) GetEVMAddress(ctx context.Context, addr s
216216
return "", nil
217217
}
218218

219+
func (m *balanceIncrementingValidator) IsAddressValidator(ctx context.Context, cosmosAddr string) (bool, error) {
220+
return false, nil
221+
}
222+

cmd/push-validator/testutil_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,10 @@ type mockValidator struct {
111111
ensureKeyErr error
112112
importKeyResult validator.KeyInfo
113113
importKeyErr error
114-
evmAddrResult string
115-
evmAddrErr error
114+
evmAddrResult string
115+
evmAddrErr error
116+
isAddressValidatorRes bool
117+
isAddressValidatorErr error
116118
}
117119

118120
func (m *mockValidator) Balance(ctx context.Context, addr string) (string, error) {
@@ -151,6 +153,10 @@ func (m *mockValidator) GetEVMAddress(ctx context.Context, addr string) (string,
151153
return m.evmAddrResult, m.evmAddrErr
152154
}
153155

156+
func (m *mockValidator) IsAddressValidator(ctx context.Context, cosmosAddr string) (bool, error) {
157+
return m.isAddressValidatorRes, m.isAddressValidatorErr
158+
}
159+
154160
// mockRunner implements CommandRunner for testing.
155161
type mockRunner struct {
156162
outputs map[string][]byte // key: "name arg1 arg2", value: output

0 commit comments

Comments
 (0)