Skip to content

Commit

Permalink
Merge pull request #124 from algorandfoundation/feat/accounts-page-ad…
Browse files Browse the repository at this point in the history
…d-incentive-eligibility

Feat/accounts page add incentive eligibility, fix: non-resident keys in txn modal
  • Loading branch information
PhearZero authored Jan 22, 2025
2 parents a3421bc + 2d00496 commit c2a483f
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 17 deletions.
67 changes: 57 additions & 10 deletions ui/modal/controller.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package modal

import (
"bytes"
"fmt"
"github.com/algorandfoundation/nodekit/internal/algod"
"github.com/algorandfoundation/nodekit/internal/algod/participation"
Expand All @@ -23,6 +24,13 @@ func (m ViewModel) Init() tea.Cmd {
)
}

func boolToInt(input bool) int {
if input {
return 1
}
return 0
}

// HandleMessage processes the given message, updates the ViewModel state, and returns any commands to execute.
func (m ViewModel) HandleMessage(msg tea.Msg) (*ViewModel, tea.Cmd) {
var (
Expand Down Expand Up @@ -75,24 +83,63 @@ func (m ViewModel) HandleMessage(msg tea.Msg) (*ViewModel, tea.Cmd) {
// If the previous state is not active
if ok {
if !m.transactionModal.Active {
if acct.Participation != nil &&
acct.Participation.VoteFirstValid == m.transactionModal.Participation.Key.VoteFirstValid {
m.SetActive(true)
m.infoModal.Active = true
m.infoModal.Prefix = "Successfully registered online!\n"
m.HasPrefix = true
m.SetType(app.InfoModal)
if acct.Participation != nil && acct.Status == "Online" {
// comparing values to detect corrupted/non-resident keys
fvMatch := boolToInt(acct.Participation.VoteFirstValid == m.transactionModal.Participation.Key.VoteFirstValid)
lvMatch := boolToInt(acct.Participation.VoteLastValid == m.transactionModal.Participation.Key.VoteLastValid)
kdMatch := boolToInt(acct.Participation.VoteKeyDilution == m.transactionModal.Participation.Key.VoteKeyDilution)
selMatch := boolToInt(bytes.Equal(acct.Participation.SelectionParticipationKey, m.transactionModal.Participation.Key.SelectionParticipationKey))
votMatch := boolToInt(bytes.Equal(acct.Participation.VoteParticipationKey, m.transactionModal.Participation.Key.VoteParticipationKey))
spkMatch := boolToInt(bytes.Equal(*acct.Participation.StateProofKey, *m.transactionModal.Participation.Key.StateProofKey))
matchCount := fvMatch + lvMatch + kdMatch + selMatch + votMatch + spkMatch
if matchCount == 6 {
m.SetActive(true)
m.infoModal.Active = true
m.infoModal.Prefix = "Successfully registered online!\n"
m.HasPrefix = true
m.SetType(app.InfoModal)
} else if matchCount >= 4 {
// We use 4 as the "non resident key" threshold here
// because it would be valid to re-reg with a key that has the same fv / lv / kd
// but it would trigger the non resident condition
// TOOD: refactor this beast to have {previous state} -> compare with next state
m.SetActive(true)
m.infoModal.Active = true
m.infoModal.Prefix = "***WARNING***\nRegistered online but keys do not fully match\nCheck your registered keys carefully against the node keys\n\n"
if fvMatch == 0 {
m.infoModal.Prefix = m.infoModal.Prefix + "Mismatched: Vote First Valid\n"
}
if lvMatch == 0 {
m.infoModal.Prefix = m.infoModal.Prefix + "Mismatched: Vote Last Valid\n"
}
if kdMatch == 0 {
m.infoModal.Prefix = m.infoModal.Prefix + "Mismatched: Vote Key Dilution\n"
}
if votMatch == 0 {
m.infoModal.Prefix = m.infoModal.Prefix + "Mismatched: Vote Key\n"
}
if selMatch == 0 {
m.infoModal.Prefix = m.infoModal.Prefix + "Mismatched: Selection Key\n"
}
if spkMatch == 0 {
m.infoModal.Prefix = m.infoModal.Prefix + "Mismatched: State Proof Key\n"
}
m.HasPrefix = true
m.SetType(app.InfoModal)
}
}
} else {
// TODO: This includes suspended keys, where Status == offline but .Participation is set
// Detect and display this
if acct.Participation == nil {
m.SetActive(false)
m.infoModal.Active = false
m.transactionModal.Active = false
m.SetType(app.InfoModal)
} else {
m.SetSuspended()
m.SetType(app.InfoModal)
}
}
}

}

case app.ModalEvent:
Expand Down
10 changes: 10 additions & 0 deletions ui/modal/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ func (m *ViewModel) SetActive(active bool) {
m.transactionModal.UpdateState()
}

// SetSuspended sets the active state to false both infoModal and transactionModal, and sets suspended state to true, also for both modals.
func (m *ViewModel) SetSuspended() {
m.infoModal.Active = false
m.infoModal.Suspended = true
m.infoModal.UpdateState()
m.transactionModal.Active = false
m.transactionModal.Suspended = true
m.transactionModal.UpdateState()
}

func (m *ViewModel) SetShortLink(res participation.ShortLinkResponse) {
m.Link = &res
m.transactionModal.Link = &res
Expand Down
7 changes: 5 additions & 2 deletions ui/modals/info/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type ViewModel struct {
Controls string
BorderColor string
Active bool
Suspended bool
Prefix string
Participation *api.ParticipationKey
State *algod.StateModel
Expand Down Expand Up @@ -74,9 +75,8 @@ func (m *ViewModel) UpdateState() {
if m.Participation == nil {
return
}
accountStatus := m.State.Accounts[m.Participation.Address].Status

if accountStatus == "Online" && m.Active {
if m.Active && !m.Suspended {
m.BorderColor = "1"
m.Controls = "( take " + style.Red.Render(style.Red.Render("(o)ffline")) + " )"
}
Expand All @@ -100,6 +100,9 @@ func (m ViewModel) View() string {
voteKeyDilution := style.Purple("Vote Key Dilution: ") + utils.IntToStr(m.Participation.Key.VoteKeyDilution)

prefix := ""
if m.Suspended {
prefix = "**KEY SUSPENDED**: Re-register online"
}
if m.Prefix != "" {
prefix = "\n" + m.Prefix
}
Expand Down
1 change: 1 addition & 0 deletions ui/modals/transaction/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type ViewModel struct {
// Active Participation Key
Participation *api.ParticipationKey
Active bool
Suspended bool
Link *participation.ShortLinkResponse

// Pointer to the State
Expand Down
34 changes: 31 additions & 3 deletions ui/pages/accounts/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import (
"github.com/charmbracelet/lipgloss"
)

var minEligibleBalance = 30_000
var maxEligibleBalance = 70_000_000

type ViewModel struct {
Data *algod.StateModel

Expand Down Expand Up @@ -67,8 +70,8 @@ func (m ViewModel) makeColumns(width int) []table.Column {
avgWidth := (width - lipgloss.Width(style.Border.Render("")) - 9) / 5
return []table.Column{
{Title: "Account", Width: avgWidth},
{Title: "Keys", Width: avgWidth},
{Title: "Status", Width: avgWidth},
{Title: "Rewards", Width: avgWidth},
{Title: "Expires", Width: avgWidth},
{Title: "Balance", Width: avgWidth},
}
Expand All @@ -78,11 +81,13 @@ func (m ViewModel) makeRows() *[]table.Row {
rows := make([]table.Row, 0)

for addr := range m.Data.Accounts {
expired := false
var expires = "N/A"
if m.Data.Accounts[addr].Expires != nil {
// This condition will only exist for a split second
// until algod deletes the key
if m.Data.Accounts[addr].Expires.Before(time.Now()) {
expired = true
expires = "EXPIRED"
} else {
expires = m.Data.Accounts[addr].Expires.Format(time.RFC822)
Expand All @@ -105,10 +110,33 @@ func (m ViewModel) makeRows() *[]table.Row {
}
}

status := m.Data.Accounts[addr].Status
if status == "Online" && !expired {
status = "PARTICIPATING"
} else {
status = "IDLE"
}

incentiveLevel := ""
balance := m.Data.Accounts[addr].Balance
if m.Data.Accounts[addr].IncentiveEligible && status == "PARTICIPATING" {
if balance >= minEligibleBalance && balance <= maxEligibleBalance {
incentiveLevel = "ELIGIBLE"
} else {
incentiveLevel = "PAUSED"
}
} else {
if status == "PARTICIPATING" {
incentiveLevel = "INELIGIBLE"
} else {
incentiveLevel = ""
}
}

rows = append(rows, table.Row{
m.Data.Accounts[addr].Address,
strconv.Itoa(m.Data.Accounts[addr].Keys),
m.Data.Accounts[addr].Status,
status,
incentiveLevel,
expires,
strconv.Itoa(m.Data.Accounts[addr].Balance),
})
Expand Down
4 changes: 2 additions & 2 deletions ui/pages/accounts/testdata/Test_Snapshot/Visible.golden
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
╭──Accounts────────────────────────────────────────────────────────────────────╮
│ Account Keys Status Expires Balance │
│ Account Status Rewards Expires Balance │
│─────────────────────────────────────────────────────────────────────────── │
│ ABC 2 Offline N/A 0 │
│ ABC IDLE N/A 0 │
│ │
│ │
│ │
Expand Down

0 comments on commit c2a483f

Please sign in to comment.