Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: view transitions #24

Merged
merged 60 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
25a6a8e
fix: responsiveness with qr code, remove controls
PhearZero Oct 30, 2024
10b0354
Merge remote-tracking branch 'origin/fix/responsive-qr-code' into ref…
PhearZero Nov 5, 2024
da64fee
refactor: use arrow keys and remove hotkeys
PhearZero Nov 5, 2024
236d8ca
Merge branch 'main' into refactor/view-transitions
PhearZero Nov 6, 2024
34a6dde
refactor: move transaction and generate page
PhearZero Nov 6, 2024
d78a619
refactor: overlays with modal
PhearZero Nov 6, 2024
b5cb153
refactor: generate modal
PhearZero Nov 8, 2024
159688b
test: add last voted to test
PhearZero Nov 12, 2024
76974dd
fix: title loading
PhearZero Nov 12, 2024
7b2ff73
refactor: create app module, refactors cmds
PhearZero Nov 13, 2024
e3f2e8f
chore: move account address in confirm modal
PhearZero Nov 13, 2024
723007d
fix: online/offline transactions
PhearZero Nov 14, 2024
603e9cf
fix: block delete key
PhearZero Nov 14, 2024
cd20d0e
refactor: generate command
PhearZero Nov 14, 2024
6458d01
Merge branch 'main' into refactor/view-transitions
PhearZero Nov 18, 2024
e71253c
Merge branch 'main' into refactor/view-transitions
PhearZero Nov 19, 2024
23779eb
test(ui): keys page 100% coverage
PhearZero Nov 19, 2024
f6053bf
test(ui): refactor test fixtures, increase accounts coverage
PhearZero Nov 19, 2024
a0dd193
test(ui): accounts page 100% coverage
PhearZero Nov 19, 2024
233968d
test(ui): confirm modal 100% coverage
PhearZero Nov 19, 2024
4e4e9d9
test(ui): exception modal 100% coverage
PhearZero Nov 19, 2024
79628d2
test(ui): info modal 100% coverage
PhearZero Nov 19, 2024
53ca01c
test(ui): transaction modal increase coverage
PhearZero Nov 19, 2024
7e1a067
test(ui): generate modal 100% coverage
PhearZero Nov 19, 2024
8031447
test(ui): overlay 100% coverage
PhearZero Nov 19, 2024
7abda83
test(ui): increase style coverage
PhearZero Nov 19, 2024
acfbb10
test(ui): utils 100% coverage
PhearZero Nov 20, 2024
4fc1270
test: refactor to interface for client, increase coverage
PhearZero Nov 20, 2024
a39d905
test: allow mock api in internal
PhearZero Nov 20, 2024
e2a3af5
test(internal): status test
PhearZero Nov 20, 2024
af577a7
test(internal): github tests 100%, adds HttpPkg interface
PhearZero Nov 21, 2024
ab6e066
test(internal): metrics tests 100% coverage
PhearZero Nov 21, 2024
dff0cc7
test(internal): status coverage
PhearZero Nov 21, 2024
9a91f8f
feat(ui): lora transaction wizard
PhearZero Nov 21, 2024
ceb0e76
test(ui): update snapshots
PhearZero Nov 21, 2024
e395e99
fix(ui): empty account generate key
PhearZero Nov 21, 2024
a9851e2
fix(ui): input focus and return to accounts on delete
PhearZero Nov 21, 2024
a2f484c
feat(ui): display network and hide qrcode
PhearZero Nov 21, 2024
8b61cf0
chore(ui): remove extra parameters
PhearZero Nov 21, 2024
db34376
refactor(internal): participation watcher
PhearZero Nov 21, 2024
c66b330
fix(ui): state updates for online/offline
PhearZero Nov 21, 2024
194c3af
chore(build): fund TUI account
PhearZero Nov 21, 2024
b8e3149
fix(ui): catch invalid states
PhearZero Nov 21, 2024
c172119
build(docker): change order of clerk call
PhearZero Nov 22, 2024
297d4f1
build(docker): remove funding for now
PhearZero Nov 22, 2024
b89bb06
chore(internal): update generate status and rename idx
PhearZero Nov 26, 2024
d6b8708
chore(internal): remove offset
PhearZero Nov 26, 2024
f9352b9
refactor(internal): move GetAddressFromGenesis to test package
PhearZero Nov 26, 2024
844f286
chore(ui): update verbiage
PhearZero Nov 27, 2024
1069d6e
change build: no CGO dependency
Nov 27, 2024
f90ea9f
Dockerfile lint/warnings
Nov 27, 2024
00c47ca
Merge pull request #29 from algorandfoundation/chore/build-with-no-cho
PhearZero Nov 27, 2024
d77d9b4
test(ui): update modal snapshot
PhearZero Nov 27, 2024
92002bb
text fixes for modals, mostly keyreg
Nov 27, 2024
53c297c
test(ui): update snapshots
PhearZero Nov 27, 2024
f88b5c4
test(ui): fix lint error
PhearZero Nov 27, 2024
4d9c36c
chore(ui): add message while syncing for generate
PhearZero Nov 27, 2024
0b57899
chore(ui): consistent NA values
PhearZero Nov 27, 2024
fc8b3f3
feat(ui): handle fast catchup
PhearZero Nov 27, 2024
58d3e8d
chore(ui): format date value
PhearZero Nov 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ ADD .docker/start_fast_catchup.sh /node/run/start_fast_catchup.sh

COPY --from=BUILDER /app/bin/algorun /bin/algorun

RUN apt-get update && apt-get install jq -y

ENTRYPOINT /node/run/start_dev.sh
CMD []

Expand Down
17 changes: 9 additions & 8 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,15 @@ var (
client, err := getClient()
cobra.CheckErr(err)

partkeys, err := internal.GetPartKeys(context.Background(), client)
ctx := context.Background()
partkeys, err := internal.GetPartKeys(ctx, client)
if err != nil {
return fmt.Errorf(
style.Red.Render("failed to get participation keys: %s"),
err)
}

state := internal.StateModel{
Offset: viper.GetInt("offset"),
tasosbit marked this conversation as resolved.
Show resolved Hide resolved
Status: internal.StatusModel{
State: "INITIALIZING",
Version: "NA",
Expand All @@ -75,14 +76,17 @@ var (
TX: 0,
},
ParticipationKeys: partkeys,

Client: client,
Context: ctx,
}
state.Accounts = internal.AccountsFromState(&state, new(internal.Clock), client)

// Fetch current state
err = state.Status.Fetch(context.Background(), client)
err = state.Status.Fetch(ctx, client, new(internal.HttpPkg))
cobra.CheckErr(err)

m, err := ui.MakeViewportViewModel(&state, client)
m, err := ui.NewViewportViewModel(&state, client)
cobra.CheckErr(err)

p := tea.NewProgram(
Expand All @@ -99,12 +103,9 @@ var (
p.Send(state)
p.Send(err)
}
}, context.Background(), client)
}, ctx, client)
}()
_, err = p.Run()
//for {
// time.Sleep(10 * time.Second)
//}
return err
},
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
},
ParticipationKeys: nil,
}
err = state.Status.Fetch(context.Background(), client)
err = state.Status.Fetch(context.Background(), client, new(internal.HttpPkg))

Check warning on line 47 in cmd/status.go

View check run for this annotation

Codecov / codecov/patch

cmd/status.go#L47

Added line #L47 was not covered by tests
cobra.CheckErr(err)
// Create the TUI
view := ui.MakeStatusViewModel(&state)
Expand Down
45 changes: 29 additions & 16 deletions internal/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

// Account represents a user's account, including address, status, balance, and number of keys.
type Account struct {
Participation *api.AccountParticipation
// Account Address is the algorand encoded address
Address string
// Status is the Online/Offline/"NotParticipating" status of the account
Expand All @@ -28,7 +29,7 @@
}

// Gets the list of addresses created at genesis from the genesis file
func getAddressesFromGenesis(client *api.ClientWithResponses) ([]string, string, string, error) {
func getAddressesFromGenesis(client api.ClientInterface) ([]string, string, string, error) {
tasosbit marked this conversation as resolved.
Show resolved Hide resolved
resp, err := client.GetGenesis(context.Background())
if err != nil {
return []string{}, "", "", err
Expand Down Expand Up @@ -91,7 +92,7 @@
}

// Get Online Status of Account
func GetAccount(client *api.ClientWithResponses, address string) (api.Account, error) {
func GetAccount(client api.ClientWithResponsesInterface, address string) (api.Account, error) {
var format api.AccountInformationParamsFormat = "json"
r, err := client.AccountInformationWithResponse(
context.Background(),
Expand All @@ -112,8 +113,19 @@
return *r.JSON200, nil
}

func GetExpiresTime(t Time, key api.ParticipationKey, state *StateModel) time.Time {
now := t.Now()
var expires = now.Add(-(time.Hour * 24 * 365 * 100))
if key.LastBlockProposal != nil && state.Status.LastRound != 0 && state.Metrics.RoundTime != 0 {
roundDiff := max(0, *key.EffectiveLastValid-int(state.Status.LastRound))
distance := int(state.Metrics.RoundTime) * roundDiff
expires = now.Add(time.Duration(distance))
}
return expires
}

// AccountsFromParticipationKeys maps an array of api.ParticipationKey to a keyed map of Account
func AccountsFromState(state *StateModel, t Time, client *api.ClientWithResponses) map[string]Account {
func AccountsFromState(state *StateModel, t Time, client api.ClientWithResponsesInterface) map[string]Account {
values := make(map[string]Account)
if state == nil || state.ParticipationKeys == nil {
return values
Expand All @@ -126,7 +138,7 @@
Status: "Unknown",
Amount: 0,
}
if state.Status.State != "SYNCING" {
if state.Status.State != SyncingState {
var err error
account, err = GetAccount(client, key.Address)
// TODO: handle error
Expand All @@ -135,23 +147,24 @@
panic(err)
}
}
now := t.Now()
var expires = now.Add(-(time.Hour * 24 * 365 * 100))
if key.EffectiveLastValid != nil {
roundDiff := max(0, *key.EffectiveLastValid-int(state.Status.LastRound))
distance := int(state.Metrics.RoundTime) * roundDiff
expires = now.Add(time.Duration(distance))
}

values[key.Address] = Account{
Address: key.Address,
Status: account.Status,
Balance: account.Amount / 1000000,
Expires: expires,
Keys: 1,
Participation: account.Participation,
Address: key.Address,
Status: account.Status,
Balance: account.Amount / 1000000,
Expires: GetExpiresTime(t, key, state),
Keys: 1,
}
} else {
val.Keys++
if val.Expires.Before(t.Now()) {
now := t.Now()
var expires = GetExpiresTime(t, key, state)
if !expires.Before(now) {
val.Expires = expires
}

Check warning on line 166 in internal/accounts.go

View check run for this annotation

Codecov / codecov/patch

internal/accounts.go#L162-L166

Added lines #L162 - L166 were not covered by tests
}
values[key.Address] = val
}
}
Expand Down
35 changes: 17 additions & 18 deletions internal/accounts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@ package internal

import (
"github.com/algorandfoundation/hack-tui/api"
"github.com/algorandfoundation/hack-tui/internal/test/mock"
"github.com/oapi-codegen/oapi-codegen/v2/pkg/securityprovider"
"github.com/stretchr/testify/assert"
"testing"
"time"
)

type TestClock struct{}

func (TestClock) Now() time.Time { return time.Time{} }

func Test_AccountsFromState(t *testing.T) {

// Setup elevated client
Expand Down Expand Up @@ -67,7 +64,7 @@ func Test_AccountsFromState(t *testing.T) {

effectiveFirstValid := 0
effectiveLastValid := 10000

lastProposedRound := 1336
// Create mockedPart Keys
var mockedPartKeys = []api.ParticipationKey{
{
Expand All @@ -83,7 +80,7 @@ func Test_AccountsFromState(t *testing.T) {
VoteLastValid: 9999999,
VoteKeyDilution: 0,
},
LastBlockProposal: nil,
LastBlockProposal: &lastProposedRound,
LastStateProof: nil,
LastVote: nil,
},
Expand Down Expand Up @@ -117,7 +114,7 @@ func Test_AccountsFromState(t *testing.T) {
VoteLastValid: 9999999,
VoteKeyDilution: 0,
},
LastBlockProposal: nil,
LastBlockProposal: &lastProposedRound,
LastStateProof: nil,
LastVote: nil,
},
Expand Down Expand Up @@ -145,7 +142,7 @@ func Test_AccountsFromState(t *testing.T) {
}

// Calculate expiration
clock := new(TestClock)
clock := new(mock.Clock)
now := clock.Now()
roundDiff := max(0, effectiveLastValid-int(state.Status.LastRound))
distance := int(state.Metrics.RoundTime) * roundDiff
Expand All @@ -154,18 +151,20 @@ func Test_AccountsFromState(t *testing.T) {
// Construct expected accounts
expectedAccounts := map[string]Account{
onlineAccounts[0].Address: {
Address: onlineAccounts[0].Address,
Status: onlineAccounts[0].Status,
Balance: onlineAccounts[0].Amount / 1_000_000,
Keys: 2,
Expires: expires,
Participation: onlineAccounts[0].Participation,
Address: onlineAccounts[0].Address,
Status: onlineAccounts[0].Status,
Balance: onlineAccounts[0].Amount / 1_000_000,
Keys: 2,
Expires: expires,
},
onlineAccounts[1].Address: {
Address: onlineAccounts[1].Address,
Status: onlineAccounts[1].Status,
Balance: onlineAccounts[1].Amount / 1_000_000,
Keys: 1,
Expires: expires,
Participation: onlineAccounts[1].Participation,
Address: onlineAccounts[1].Address,
Status: onlineAccounts[1].Status,
Balance: onlineAccounts[1].Amount / 1_000_000,
Keys: 1,
Expires: expires,
},
}

Expand Down
2 changes: 1 addition & 1 deletion internal/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type BlockMetrics struct {
TPS float64
}

func GetBlockMetrics(ctx context.Context, client *api.ClientWithResponses, round uint64, window int) (*BlockMetrics, error) {
func GetBlockMetrics(ctx context.Context, client api.ClientWithResponsesInterface, round uint64, window int) (*BlockMetrics, error) {
var avgs = BlockMetrics{
AvgTime: 0,
TPS: 0,
Expand Down
6 changes: 2 additions & 4 deletions internal/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ package internal

import (
"encoding/json"
"log"
"net/http"
"strings"
)

func GetGoAlgorandRelease(channel string) (*string, error) {
func GetGoAlgorandRelease(channel string, http HttpPkgInterface) (*string, error) {
resp, err := http.Get("https://api.github.com/repos/algorand/go-algorand/releases")
if err != nil {
return nil, err
Expand All @@ -16,7 +14,7 @@ func GetGoAlgorandRelease(channel string) (*string, error) {
defer resp.Body.Close()
var versions []map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&versions); err != nil {
log.Fatal("ooopsss! an error occurred, please try again")
return nil, err
}
var versionResponse *string
for i := range versions {
Expand Down
82 changes: 82 additions & 0 deletions internal/github_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package internal

import (
"bytes"
"errors"
"io"
"net/http"
"testing"
)

type testDecoder struct {
HttpPkgInterface
}

func (testDecoder) Get(url string) (resp *http.Response, err error) {
return &http.Response{
Status: "",
StatusCode: 0,
Proto: "",
ProtoMajor: 0,
ProtoMinor: 0,
Header: nil,
Body: http.NoBody,
ContentLength: 0,
TransferEncoding: nil,
Close: false,
Uncompressed: false,
Trailer: nil,
Request: nil,
TLS: nil,
}, nil
}

type testResponse struct {
HttpPkgInterface
}

var jsonStr = `[{
"tag_name": "v3.26.0-beta"
}]`

func (testResponse) Get(url string) (resp *http.Response, err error) {

responseBody := io.NopCloser(bytes.NewReader([]byte(jsonStr)))
return &http.Response{
StatusCode: 200,
Body: responseBody,
}, nil
}

type testError struct {
HttpPkgInterface
}

func (testError) Get(url string) (resp *http.Response, err error) {
return &http.Response{
StatusCode: 404,
}, errors.New("not found")
}

func Test_Github(t *testing.T) {
_, err := GetGoAlgorandRelease("beta", new(testDecoder))
if err == nil {
t.Error("should fail to decode")
}

r, err := GetGoAlgorandRelease("beta", new(testResponse))
if err != nil {
t.Error(err)
}
if r == nil {
t.Error("should not be nil")
}
if *r != "v3.26.0-beta" {
t.Error("should return v3.26.0-beta")
}

_, err = GetGoAlgorandRelease("beta", new(testError))
if err == nil {
t.Error("should fail to get")
}
}
17 changes: 17 additions & 0 deletions internal/http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package internal

import "net/http"

type HttpPkg struct {
HttpPkgInterface
}

func (HttpPkg) Get(url string) (resp *http.Response, err error) {
return http.Get(url)
}

var Http HttpPkg

type HttpPkgInterface interface {
Get(url string) (resp *http.Response, err error)
}
2 changes: 1 addition & 1 deletion internal/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func parseMetricsContent(content string) (MetricsResponse, error) {
}

// GetMetrics parses the /metrics endpoint from algod into a map
func GetMetrics(ctx context.Context, client *api.ClientWithResponses) (MetricsResponse, error) {
func GetMetrics(ctx context.Context, client api.ClientWithResponsesInterface) (MetricsResponse, error) {
res, err := client.MetricsWithResponse(ctx)
if err != nil {
return nil, err
Expand Down
Loading
Loading