@@ -9,16 +9,28 @@ import (
9
9
10
10
"github.com/charmbracelet/bubbles/progress"
11
11
tea "github.com/charmbracelet/bubbletea"
12
+ "github.com/charmbracelet/lipgloss"
12
13
13
14
"github.com/algorand/go-algorand-sdk/client/v2/common/models"
15
+ "github.com/algorand/go-algorand-sdk/types"
14
16
15
17
"github.com/algorand/node-ui/messages"
18
+ "github.com/algorand/node-ui/tui/internal/bubbles/explorer"
16
19
"github.com/algorand/node-ui/tui/internal/style"
17
20
)
18
21
22
+ const roundTo = time .Second / 10
23
+
24
+ // consensus constants, in theory these could be modified by a consensus upgrade.
25
+ const (
26
+ upgradeVoteRounds = 10000
27
+ upgradeThreshold = 9000
28
+ )
29
+
19
30
// Model representing the status.
20
31
type Model struct {
21
32
Status models.NodeStatus
33
+ Header types.BlockHeader
22
34
Network messages.NetworkMsg
23
35
Err error
24
36
@@ -71,6 +83,18 @@ func (m Model) averageBlockTime() time.Duration {
71
83
// Update is part of the tea.Model interface.
72
84
func (m Model ) Update (msg tea.Msg ) (tea.Model , tea.Cmd ) {
73
85
switch msg := msg .(type ) {
86
+ case explorer.BlocksMsg :
87
+ // Still initializing.
88
+ if m .Status .LastRound == 0 {
89
+ return m , nil
90
+ }
91
+
92
+ for _ , blk := range msg .Blocks {
93
+ if uint64 (blk .Block .Block .Round ) == m .Status .LastRound {
94
+ m .Header = blk .Block .Block .BlockHeader
95
+ }
96
+ }
97
+ return m , nil
74
98
case messages.StatusMsg :
75
99
if msg .Error != nil {
76
100
m .Err = fmt .Errorf ("error fetching status: %w" , msg .Error )
@@ -80,14 +104,14 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
80
104
81
105
// Save the times for computing round time
82
106
if m .latestBlock < m .Status .LastRound {
107
+ since := time .Duration (m .Status .TimeSinceLastRound )
83
108
m .latestBlock = m .Status .LastRound
84
- m .latestTime = time .Now ().Add (- time . Duration ( m . Status . TimeSinceLastRound ) )
109
+ m .latestTime = time .Now ().Add (- since )
85
110
86
111
// Grab the start time
87
112
if m .startBlock == 0 {
88
113
m .startBlock = m .Status .LastRound
89
- since := time .Duration (m .Status .TimeSinceLastRound )
90
- m .startTime = time .Now ().Add (- since )
114
+ m .startTime = m .latestTime
91
115
}
92
116
}
93
117
@@ -107,14 +131,16 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
107
131
108
132
case messages.NetworkMsg :
109
133
m .Network = msg
134
+ return m , nil
110
135
111
136
case progress.FrameMsg :
112
137
progressModel , cmd := m .progress .Update (msg )
113
138
m .progress = progressModel .(progress.Model )
114
139
return m , cmd
115
- }
116
140
117
- return m , nil
141
+ default :
142
+ return m , nil
143
+ }
118
144
}
119
145
120
146
func formatVersion (v string ) string {
@@ -131,6 +157,12 @@ func writeProgress(b *strings.Builder, prefix string, progress progress.Model, p
131
157
b .WriteString ("\n " )
132
158
}
133
159
160
+ func (m Model ) calculateTimeToGo (start , end uint64 , style lipgloss.Style ) string {
161
+ rounds := end - start
162
+ timeRemaining := time .Duration (int64 (rounds ) * m .averageBlockTime ().Nanoseconds ()).Round (roundTo )
163
+ return style .Render (fmt .Sprintf ("%d to go, %s" , rounds , timeRemaining ))
164
+ }
165
+
134
166
// View is part of the tea.Model interface.
135
167
func (m Model ) View () string {
136
168
bold := m .style .StatusBoldText
@@ -166,12 +198,34 @@ func (m Model) View() string {
166
198
height -= 7
167
199
default :
168
200
builder .WriteString (fmt .Sprintf ("Current round: %s\n " , key .Render (strconv .FormatUint (m .Status .LastRound , 10 ))))
169
- roundTo := time .Second / 10
170
201
builder .WriteString (fmt .Sprintf ("Block wait time: %s\n " , time .Duration (m .Status .TimeSinceLastRound ).Round (roundTo )))
171
202
builder .WriteString (fmt .Sprintf ("Sync time: %s\n " , time .Duration (m .Status .CatchupTime ).Round (roundTo )))
172
203
height -= 3
173
- // TODO: Display consensus upgrade progress
174
- if m .Status .LastVersion == m .Status .NextVersion {
204
+ if m .Header .UpgradeState != (types.UpgradeState {}) {
205
+ //remainingToUpgrade := m.calculateTimeToGo(
206
+ // m.Status.LastRound, uint64(m.Header.NextProtocolSwitchOn), m.style.AccountBlueText)
207
+ remainingToVote := m .calculateTimeToGo (
208
+ m .Status .LastRound , uint64 (m .Header .NextProtocolVoteBefore ), m .style .AccountBlueText )
209
+
210
+ // calculate yes/no votes
211
+ votesToGo := uint64 (m .Header .NextProtocolVoteBefore ) - m .Status .LastRound
212
+ votes := upgradeVoteRounds - votesToGo
213
+ voteYes := m .Header .NextProtocolApprovals
214
+ voteNo := votes - voteYes
215
+ voteString := fmt .Sprintf ("%d / %d" , voteYes , voteNo )
216
+ yesPct := float64 (voteYes ) / float64 (votes )
217
+ windowPct := float64 (votes ) / float64 (upgradeVoteRounds )
218
+ builder .WriteString (fmt .Sprintf ("%s\n " , bold .Render ("Consensus Upgrade Pending: Votes" )))
219
+ builder .WriteString (fmt .Sprintf ("Next Protocol: %s\n " , formatVersion (m .Header .NextProtocol )))
220
+ builder .WriteString (fmt .Sprintf ("Yes/No votes: %s (%.0f%%, 90%% required)\n " , voteString , yesPct * 100 ))
221
+ //builder.WriteString(fmt.Sprintf("Vote window: %s (%f%%)\n", voteString, *100))
222
+ builder .WriteString (fmt .Sprintf ("Vote window close: %d (%.0f%%, %s)\n " ,
223
+ m .Header .UpgradeState .NextProtocolVoteBefore ,
224
+ windowPct * 100 ,
225
+ remainingToVote ))
226
+
227
+ height -= 5
228
+ } else if m .Status .LastVersion == m .Status .NextVersion {
175
229
// no upgrade in progress
176
230
builder .WriteString (fmt .Sprintf ("Protocol: %s\n " , formatVersion (m .Status .LastVersion )))
177
231
builder .WriteString (fmt .Sprintf (" %s\n " , bold .Render ("No upgrade in progress." )))
@@ -184,7 +238,7 @@ func (m Model) View() string {
184
238
fmt .Sprintf ("%d to go, %s" , togo , timeRemaining ))
185
239
186
240
// upgrade in progress
187
- builder .WriteString (fmt .Sprintf ("%s\n " , bold .Render ("Consensus Upgrade Pending " )))
241
+ builder .WriteString (fmt .Sprintf ("%s\n " , bold .Render ("Consensus Upgrade Scheduled " )))
188
242
builder .WriteString (fmt .Sprintf ("Current Protocol: %s\n " , formatVersion (m .Status .LastVersion )))
189
243
builder .WriteString (fmt .Sprintf ("Next Protocol: %s\n " , formatVersion (m .Status .NextVersion )))
190
244
builder .WriteString (fmt .Sprintf ("Upgrade round: %d (%s)\n " , m .Status .NextVersionRound , remaining ))
0 commit comments