Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions AICHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@
idempotency, rejected requests, redirects, and missing confirmation without
exposing credentials or response bodies.

- **Put each vault-state token on its own line (#99)**: the shared pretty
renderer now right-aligns amounts across the section and indents continuation
lines under the value column. It preserves zero values, token order, readable
units, and separators. CLI and monitor share the layout; JSON/YAML and other
commands' compact coin output are unchanged.

- **The live Console lifecycle repeated an unchanged runtime-limit PATCH**:
the sandbox API rejects an equal total because it is not an extension, so the
otherwise successful protected job failed late in its lifecycle and cleanup
Expand Down
6 changes: 6 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -1389,6 +1389,12 @@ small void rendering API cannot hide a broken stdout behind that API.
rendering alone applies the shared readable-unit conversion above; this
keeps `1000000uakt` machine-readable as such while displaying it as `1 AKT`.

Vault-state output uses one token per line with a shared right-aligned amount
column across balances, burned, minted, and remint-credit fields. Its shared
renderer owns the layout for both CLI and monitor consumers. Each coin still
uses the standard readable-unit formatter; the general compact coin formatter
and machine JSON/YAML representations remain unchanged.

Governance proposal output separates discovery from inspection. The proposal
list stays compact and reports how many executable messages each proposal
contains. The single-proposal view is the audit view: it shows the exact
Expand Down
8 changes: 8 additions & 0 deletions SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -6153,6 +6153,14 @@ carries; the raw gRPC/ABCI status must never reach the user verbatim.

#### BME

Vault-state pretty output lists one token per line within Balances, Total
Burned, Total Minted, and Remint Credits. Labels appear only on the first line
of each field. Amounts are right-aligned across the section, and continuation
lines use the same value column. Retain the response order, zero-valued coins,
and comma separators between tokens; format each coin through `FormatCoin`.
The shared renderer supplies identical CLI and monitor output. JSON/YAML and
other commands' compact coin formatting are unchanged.

**Status/Vault**: Key-value sections with amounts. The collateral ratio and the
warn/halt thresholds are `LegacyDec` ratios, not coins: they render through
the ratio formatter (`1.5`, not `1.500000000000000000`), matching the oracle
Expand Down
41 changes: 31 additions & 10 deletions internal/output/pretty/bme.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,38 @@ func RenderBMEVaultState(res *types.QueryVaultStateResponse) string {

fmt.Fprintln(&buf, Section("Vault State"))

if len(s.Balances) > 0 {
KV(&buf, "Balances", FormatCoins(s.Balances))
}
if len(s.TotalBurned) > 0 {
KV(&buf, "Total Burned", FormatCoins(s.TotalBurned))
}
if len(s.TotalMinted) > 0 {
KV(&buf, "Total Minted", FormatCoins(s.TotalMinted))
type coinRow struct{ label, amount, denom string }
var rows []coinRow
amountWidth := 0
for _, field := range []struct {
label string
coins sdk.Coins
}{
{"Balances", s.Balances},
{"Total Burned", s.TotalBurned},
{"Total Minted", s.TotalMinted},
{"Remint Credits", s.RemintCredits},
} {
for i, coin := range field.coins {
amount, denom, _ := strings.Cut(FormatCoin(coin), " ")
label := ""
if i == 0 {
label = field.label
}
if i < len(field.coins)-1 {
denom += ","
}
rows = append(rows, coinRow{label, amount, denom})
amountWidth = max(amountWidth, len(amount))
}
}
if len(s.RemintCredits) > 0 {
KV(&buf, "Remint Credits", FormatCoins(s.RemintCredits))
for _, row := range rows {
value := fmt.Sprintf("%*s %s", amountWidth, row.amount, row.denom)
if row.label != "" {
KV(&buf, row.label, value)
} else {
fmt.Fprintln(&buf, strings.Repeat(" ", KVKeyWidth+3)+value)
}
}
return buf.String()
}
Expand Down
56 changes: 56 additions & 0 deletions internal/output/pretty/bme_layout_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package pretty

import (
"strings"
"testing"

"github.com/charmbracelet/x/ansi"
sdk "github.com/cosmos/cosmos-sdk/types"
bmetypes "pkg.akt.dev/go/node/bme/v1"
)

func TestRenderBMEVaultStateTokenLines(t *testing.T) {
response := &bmetypes.QueryVaultStateResponse{VaultState: bmetypes.State{
Balances: sdk.Coins{sdk.NewInt64Coin("uact", 195427161531), sdk.NewInt64Coin("uakt", 572320058657)},
TotalBurned: sdk.Coins{sdk.NewInt64Coin("uact", 1062528246771), sdk.NewInt64Coin("uakt", 0)},
TotalMinted: sdk.Coins{sdk.NewInt64Coin("uact", 1226632271979), sdk.NewInt64Coin("uakt", 0)},
RemintCredits: sdk.Coins{sdk.NewInt64Coin("uakt", 272320058657)},
}}
got := ansi.Strip(RenderBMEVaultState(response))
rows := []struct{ label, amount, denom string }{
{"Balances", "195427.161531", "ACT,"},
{"", "572320.058657", "AKT"},
{"Total Burned", "1062528.246771", "ACT,"},
{"", "0", "AKT"},
{"Total Minted", "1226632.271979", "ACT,"},
{"", "0", "AKT"},
{"Remint Credits", "272320.058657", "AKT"},
}
lines := strings.Split(strings.TrimSuffix(got, "\n"), "\n")
if len(lines) != len(rows)+1 {
t.Fatalf("got %d lines, want one header and %d token lines:\n%s", len(lines), len(rows), got)
}
amountEnd := -1
for i, row := range rows {
line := lines[i+1]
if !strings.HasSuffix(line, row.amount+" "+row.denom) {
t.Errorf("line %d lost a token, precision, or separator: %q", i, line)
}
if row.label == "" {
if strings.Contains(line, ":") || !strings.HasPrefix(line, strings.Repeat(" ", KVKeyWidth+3)) {
t.Errorf("continuation line %d is not indented under the value column: %q", i, line)
}
} else if !strings.HasPrefix(line, " "+row.label+":") {
t.Errorf("line %d lost its label: %q", i, line)
}
end := strings.LastIndex(line, " "+row.denom)
if amountEnd == -1 {
amountEnd = end
} else if end != amountEnd {
t.Errorf("line %d amount ends at column %d, want %d", i, end, amountEnd)
}
}
if compact := FormatCoins(response.VaultState.Balances); compact != "195427.161531 ACT, 572320.058657 AKT" {
t.Fatalf("compact coin formatting changed: %q", compact)
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.