feat(tui): render tx inputs explicitly
Some checks are pending
Security Scan / security (push) Waiting to run
Test / Test (push) Waiting to run

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-04 22:51:57 +00:00
parent 602c886400
commit 9c5b179375
2 changed files with 71 additions and 8 deletions

View file

@ -309,14 +309,7 @@ func (m *ExplorerModel) viewTxDetail() string {
if len(tx.Vin) > 0 {
b.WriteString(" Inputs:\n")
for i, in := range tx.Vin {
switch v := in.(type) {
case types.TxInputGenesis:
b.WriteString(fmt.Sprintf(" [%d] coinbase height=%d\n", i, v.Height))
case types.TxInputToKey:
b.WriteString(fmt.Sprintf(" [%d] to_key amount=%d key_image=%x\n", i, v.Amount, v.KeyImage[:4]))
default:
b.WriteString(fmt.Sprintf(" [%d] %T\n", i, v))
}
b.WriteString(fmt.Sprintf(" [%d] %s\n", i, describeTxInput(in)))
}
}
@ -357,6 +350,25 @@ func describeTxOutTarget(target types.TxOutTarget) string {
}
}
// describeTxInput renders a human-readable summary for transaction inputs in
// the explorer tx detail view.
func describeTxInput(input types.TxInput) string {
switch v := input.(type) {
case types.TxInputGenesis:
return fmt.Sprintf("coinbase height=%d", v.Height)
case types.TxInputToKey:
return fmt.Sprintf("to_key amount=%d key_image=%x", v.Amount, v.KeyImage[:4])
case types.TxInputHTLC:
return fmt.Sprintf("htlc origin=%q amount=%d key_image=%x", v.HTLCOrigin, v.Amount, v.KeyImage[:4])
case types.TxInputMultisig:
return fmt.Sprintf("multisig amount=%d sigs=%d out=%x", v.Amount, v.SigsCount, v.MultisigOutID[:4])
case types.TxInputZC:
return fmt.Sprintf("zc inputs=%d key_image=%x", len(v.KeyOffsets), v.KeyImage[:4])
default:
return fmt.Sprintf("%T", v)
}
}
// loadBlocks refreshes the block list from the chain store.
// Blocks are listed from newest (top) to oldest.
func (m *ExplorerModel) loadBlocks() {

View file

@ -10,6 +10,8 @@ import (
"testing"
tea "github.com/charmbracelet/bubbletea"
"dappco.re/go/core/blockchain/types"
)
func TestExplorerModel_View_Good_BlockList(t *testing.T) {
@ -174,3 +176,52 @@ func TestExplorerModel_ViewBlockDetail_Good_CoinbaseOnly(t *testing.T) {
t.Errorf("block detail should contain 'coinbase only' for blocks with no TxHashes, got:\n%s", out)
}
}
func TestDescribeTxInput_Good(t *testing.T) {
tests := []struct {
name string
input types.TxInput
want string
}{
{
name: "genesis",
input: types.TxInputGenesis{Height: 12},
want: "coinbase height=12",
},
{
name: "to_key",
input: types.TxInputToKey{
Amount: 42,
KeyImage: types.KeyImage{0xaa, 0xbb, 0xcc, 0xdd},
},
want: "to_key amount=42 key_image=aabbccdd",
},
{
name: "htlc",
input: types.TxInputHTLC{
HTLCOrigin: "origin-hash",
Amount: 7,
KeyImage: types.KeyImage{0x10, 0x20, 0x30, 0x40},
},
want: `htlc origin="origin-hash" amount=7 key_image=10203040`,
},
{
name: "multisig",
input: types.TxInputMultisig{
Amount: 99,
SigsCount: 3,
MultisigOutID: types.Hash{0x01, 0x02, 0x03, 0x04},
},
want: "multisig amount=99 sigs=3 out=01020304",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := describeTxInput(tt.input)
if got != tt.want {
t.Fatalf("describeTxInput() = %q, want %q", got, tt.want)
}
})
}
}